diff options
46 files changed, 2044 insertions, 960 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 94022ec1be..3bc3d74de6 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -4411,7 +4411,7 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, /* apply the route-map */ if (bgp_vrf->adv_cmd_rmap[afi][safi].map) { - int ret = 0; + route_map_result_t ret; ret = route_map_apply( bgp_vrf->adv_cmd_rmap[afi][safi] diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index aa02cc3c63..bc49f7eb06 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1243,10 +1243,12 @@ static int bgp_cluster_filter(struct peer *peer, struct attr *attr) static int bgp_input_modifier(struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi, - const char *rmap_name) + const char *rmap_name, mpls_label_t *label, + uint32_t num_labels) { struct bgp_filter *filter; - struct bgp_path_info rmap_path; + struct bgp_path_info rmap_path = { 0 }; + struct bgp_path_info_extra extra = { 0 }; route_map_result_t ret; struct route_map *rmap = NULL; @@ -1276,6 +1278,11 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p, /* Duplicate current value to new strucutre for modification. */ rmap_path.peer = peer; rmap_path.attr = attr; + rmap_path.extra = &extra; + extra.num_labels = num_labels; + if (label && num_labels && num_labels <= BGP_MAX_LABELS) + memcpy(extra.label, label, + num_labels * sizeof(mpls_label_t)); SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN); @@ -1465,7 +1472,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, struct bgp *bgp; struct attr *piattr; char buf[PREFIX_STRLEN]; - int ret; + route_map_result_t ret; int transparent; int reflect; afi_t afi; @@ -2544,12 +2551,12 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, /* apply the route-map */ if (bgp->adv_cmd_rmap[afi][safi].map) { - int ret = 0; + route_map_result_t ret; ret = route_map_apply( bgp->adv_cmd_rmap[afi][safi].map, &rn->p, RMAP_BGP, new_select); - if (ret == RMAP_MATCH) + if (ret == RMAP_PERMITMATCH) bgp_evpn_advertise_type5_route( bgp, &rn->p, new_select->attr, afi, safi); @@ -3149,8 +3156,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, * commands, so we need bgp_attr_flush in the error paths, until we * intern * the attr (which takes over the memory references) */ - if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL) - == RMAP_DENY) { + if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, + label, num_labels) == RMAP_DENY) { peer->stat_pfx_filter++; reason = "route-map;"; bgp_attr_flush(&new_attr); @@ -4593,7 +4600,7 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, struct bgp_path_info rmap_path; struct attr attr; struct attr *attr_new; - int ret; + route_map_result_t ret; #if ENABLE_BGP_VNC int vnc_implicit_withdraw = 0; #endif @@ -4941,7 +4948,7 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, if (bgp_static->rmap.name) { struct attr attr_tmp = attr; struct bgp_path_info rmap_path; - int ret; + route_map_result_t ret; rmap_path.peer = bgp->peer_self; rmap_path.attr = &attr_tmp; @@ -6620,7 +6627,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, struct attr attr; struct attr *new_attr; afi_t afi; - int ret; + route_map_result_t ret; struct bgp_redist *red; /* Make default attribute. */ @@ -9139,7 +9146,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, struct route_map *rmap = output_arg; struct bgp_path_info path; struct attr dummy_attr; - int ret; + route_map_result_t ret; bgp_attr_dup(&dummy_attr, pi->attr); @@ -11284,7 +11291,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, /* Filter prefix using route-map */ ret = bgp_input_modifier(peer, &rn->p, &attr, - afi, safi, rmap_name); + afi, safi, rmap_name, NULL, 0); if (type == bgp_show_adj_route_filtered && !route_filtered && ret != RMAP_DENY) { diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 1f90fa742a..dd3382a1e7 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -62,6 +62,7 @@ #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_pbr.h" #include "bgpd/bgp_flowspec_util.h" +#include "bgpd/bgp_encap_types.h" #if ENABLE_BGP_VNC #include "bgpd/rfapi/bgp_rfapi_cfg.h" @@ -239,10 +240,9 @@ struct bgp_match_peer_compiled { /* Compares the peer specified in the 'match peer' clause with the peer received in bgp_path_info->peer. If it is the same, or if the peer structure received is a peer_group containing it, returns RMAP_MATCH. */ -static route_map_result_t route_match_peer(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_peer(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct bgp_match_peer_compiled *pc; union sockunion *su; @@ -335,10 +335,9 @@ struct route_map_rule_cmd route_match_peer_cmd = {"peer", route_match_peer, route_match_peer_free}; #if defined(HAVE_LUA) -static route_map_result_t route_match_command(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_command(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { int status = RMAP_NOMATCH; u_int32_t locpref = 0; @@ -434,10 +433,9 @@ struct route_map_rule_cmd route_match_command_cmd = { /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; @@ -474,10 +472,9 @@ struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip next-hop IP_ADDRESS' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_next_hop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_next_hop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; struct bgp_path_info *path; @@ -521,10 +518,9 @@ struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* `match ip route-source ACCESS-LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_route_source(void *rule, - const struct prefix *pfx, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_route_source(void *rule, const struct prefix *pfx, + route_map_object_t type, void *object) { struct access_list *alist; struct bgp_path_info *path; @@ -571,9 +567,9 @@ struct route_map_rule_cmd route_match_ip_route_source_cmd = { "ip route-source", route_match_ip_route_source, route_match_ip_route_source_compile, route_match_ip_route_source_free}; -static route_map_result_t route_match_prefix_list_flowspec(afi_t afi, - struct prefix_list *plist, - const struct prefix *p) +static enum route_map_cmd_result_t +route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist, + const struct prefix *p) { int ret; struct bgp_pbr_entry_main api; @@ -604,8 +600,7 @@ static route_map_result_t route_match_prefix_list_flowspec(afi_t afi, return RMAP_NOMATCH; } -/* `match ip address prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_address_prefix_list(void *rule, afi_t afi, const struct prefix *prefix, route_map_object_t type, void *object) @@ -626,7 +621,7 @@ route_match_address_prefix_list(void *rule, afi_t afi, : RMAP_MATCH); } -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -651,7 +646,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -693,7 +688,7 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* `match ip next-hop type <blackhole>' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -702,7 +697,7 @@ route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, if (type == RMAP_BGP && prefix->family == AF_INET) { path = (struct bgp_path_info *)object; if (!path || !path->attr) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; /* If nexthop interface's index can't be resolved and nexthop is set to any address then mark it as type `blackhole`. @@ -732,7 +727,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = { /* `match ip route-source prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) @@ -782,10 +777,9 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = { /* `match evpn default-route' */ /* Match function should return 1 if match is success else 0 */ -static route_map_result_t route_match_evpn_default_route(void *rule, - const struct prefix *p, - route_map_object_t - type, void *object) +static enum route_map_cmd_result_t +route_match_evpn_default_route(void *rule, const struct prefix *p, + route_map_object_t type, void *object) { if (type == RMAP_BGP && is_evpn_prefix_default(p)) return RMAP_MATCH; @@ -801,10 +795,9 @@ struct route_map_rule_cmd route_match_evpn_default_route_cmd = { /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_mac_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_mac_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; struct prefix p; @@ -847,26 +840,51 @@ struct route_map_rule_cmd route_match_mac_address_cmd = { "mac address", route_match_mac_address, route_match_mac_address_compile, route_match_mac_address_free}; -/* `match vni' */ - -/* Match function should return 1 if match is success else return - zero. */ -static route_map_result_t route_match_vni(void *rule, - const struct prefix *prefix, - route_map_object_t type, void *object) +/* + * Match function returns: + * ...RMAP_MATCH if match is found. + * ...RMAP_NOMATCH if match is not found. + * ...RMAP_NOOP to ignore this match check. + */ +static enum route_map_cmd_result_t +route_match_vni(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { vni_t vni = 0; + unsigned int label_cnt = 0; struct bgp_path_info *path = NULL; + struct prefix_evpn *evp = (struct prefix_evpn *) prefix; if (type == RMAP_BGP) { vni = *((vni_t *)rule); path = (struct bgp_path_info *)object; + /* + * This rmap filter is valid for vxlan tunnel type only. + * For any other tunnel type, return noop to ignore + * this check. + */ + if (path->attr && path->attr->encap_tunneltype != + BGP_ENCAP_TYPE_VXLAN) + return RMAP_NOOP; + + /* + * Apply filter to type 1, 2, 5 routes only. + * Other route types do not have vni label. + */ + if (evp && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE && + evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE && + evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)) + return RMAP_NOOP; + if (path->extra == NULL) return RMAP_NOMATCH; - if (vni == label2vni(&path->extra->label[0])) - return RMAP_MATCH; + for ( ; label_cnt < BGP_MAX_LABELS && + label_cnt < path->extra->num_labels; label_cnt++) { + if (vni == label2vni(&path->extra->label[label_cnt])) + return RMAP_MATCH; + } } return RMAP_NOMATCH; @@ -904,10 +922,9 @@ struct route_map_rule_cmd route_match_evpn_vni_cmd = { /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_evpn_route_type(void *rule, - const struct prefix *pfx, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_evpn_route_type(void *rule, const struct prefix *pfx, + route_map_object_t type, void *object) { uint8_t route_type = 0; @@ -950,7 +967,7 @@ struct route_map_rule_cmd route_match_evpn_route_type_cmd = { route_match_evpn_route_type_compile, route_match_evpn_route_type_free}; /* Route map commands for VRF route leak with source vrf matching */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_vrl_source_vrf(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -999,10 +1016,9 @@ struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = { /* `match local-preference LOCAL-PREF' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_local_pref(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_local_pref(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { uint32_t *local_pref; struct bgp_path_info *path; @@ -1056,10 +1072,9 @@ struct route_map_rule_cmd route_match_local_pref_cmd = { /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_metric(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_metric(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rmap_value *rv; struct bgp_path_info *path; @@ -1080,10 +1095,9 @@ struct route_map_rule_cmd route_match_metric_cmd = { /* `match as-path ASPATH' */ /* Match function for as-path match. I assume given object is */ -static route_map_result_t route_match_aspath(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_aspath(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct as_list *as_list; @@ -1130,10 +1144,9 @@ struct rmap_community { }; /* Match function for community match. */ -static route_map_result_t route_match_community(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_community(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct community_list *list; struct bgp_path_info *path; @@ -1200,10 +1213,9 @@ struct route_map_rule_cmd route_match_community_cmd = { route_match_community_free}; /* Match function for lcommunity match. */ -static route_map_result_t route_match_lcommunity(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_lcommunity(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct community_list *list; struct bgp_path_info *path; @@ -1273,10 +1285,9 @@ struct route_map_rule_cmd route_match_lcommunity_cmd = { /* Match function for extcommunity match. */ -static route_map_result_t route_match_ecommunity(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ecommunity(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct community_list *list; struct bgp_path_info *path; @@ -1327,10 +1338,9 @@ struct route_map_rule_cmd route_match_ecommunity_cmd = { and `address-family vpnv4'. */ /* `match origin' */ -static route_map_result_t route_match_origin(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_origin(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { uint8_t *origin; struct bgp_path_info *path; @@ -1375,10 +1385,9 @@ struct route_map_rule_cmd route_match_origin_cmd = { /* match probability { */ -static route_map_result_t route_match_probability(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_probability(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { long r = random(); @@ -1430,10 +1439,9 @@ struct route_map_rule_cmd route_match_probability_cmd = { /* `match interface IFNAME' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_interface(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_interface(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct interface *ifp; struct bgp_path_info *path; @@ -1477,9 +1485,9 @@ struct route_map_rule_cmd route_match_interface_cmd = { /* `set ip next-hop IP_ADDRESS' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, - const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_match_tag(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { route_tag_t *tag; struct bgp_path_info *path; @@ -1509,10 +1517,9 @@ struct rmap_ip_nexthop_set { int unchanged; }; -static route_map_result_t route_set_ip_nexthop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_ip_nexthop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rmap_ip_nexthop_set *rins = rule; struct bgp_path_info *path; @@ -1615,10 +1622,9 @@ struct route_map_rule_cmd route_set_ip_nexthop_cmd = { /* `set local-preference LOCAL_PREF' */ /* Set local preference. */ -static route_map_result_t route_set_local_pref(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_local_pref(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rmap_value *rv; struct bgp_path_info *path; @@ -1650,10 +1656,9 @@ struct route_map_rule_cmd route_set_local_pref_cmd = { /* `set weight WEIGHT' */ /* Set weight. */ -static route_map_result_t route_set_weight(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_weight(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rmap_value *rv; struct bgp_path_info *path; @@ -1678,10 +1683,9 @@ struct route_map_rule_cmd route_set_weight_cmd = { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_metric(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rmap_value *rv; struct bgp_path_info *path; @@ -1709,10 +1713,9 @@ struct route_map_rule_cmd route_set_metric_cmd = { /* `set as-path prepend ASPATH' */ /* For AS path prepend mechanism. */ -static route_map_result_t route_set_aspath_prepend(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_aspath_prepend(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct aspath *aspath; struct aspath *new; @@ -1772,10 +1775,9 @@ struct route_map_rule_cmd route_set_aspath_prepend_cmd = { * one. * Make a deep copy of existing AS_PATH, but for the first ASn only. */ -static route_map_result_t route_set_aspath_exclude(void *rule, - const struct prefix *dummy, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_aspath_exclude(void *rule, const struct prefix *dummy, + route_map_object_t type, void *object) { struct aspath *new_path, *exclude_path; struct bgp_path_info *path; @@ -1807,10 +1809,9 @@ struct rmap_com_set { }; /* For community set mechanism. */ -static route_map_result_t route_set_community(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_community(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rmap_com_set *rcs; struct bgp_path_info *path; @@ -1923,10 +1924,9 @@ struct rmap_lcom_set { /* For lcommunity set mechanism. */ -static route_map_result_t route_set_lcommunity(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_lcommunity(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rmap_lcom_set *rcs; struct bgp_path_info *path; @@ -2036,10 +2036,9 @@ struct route_map_rule_cmd route_set_lcommunity_cmd = { /* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */ /* For large community set mechanism. */ -static route_map_result_t route_set_lcommunity_delete(void *rule, - const struct prefix *pfx, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_lcommunity_delete(void *rule, const struct prefix *pfx, + route_map_object_t type, void *object) { struct community_list *list; struct lcommunity *merge; @@ -2120,11 +2119,9 @@ struct route_map_rule_cmd route_set_lcommunity_delete_cmd = { /* `set comm-list (<1-99>|<100-500>|WORD) delete' */ /* For community set mechanism. */ -static route_map_result_t route_set_community_delete( - void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_community_delete(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct community_list *list; struct community *merge; @@ -2204,10 +2201,9 @@ struct route_map_rule_cmd route_set_community_delete_cmd = { /* `set extcommunity rt COMMUNITY' */ /* For community set mechanism. Used by _rt and _soo. */ -static route_map_result_t route_set_ecommunity(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_ecommunity(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct ecommunity *ecom; struct ecommunity *new_ecom; @@ -2292,10 +2288,9 @@ struct route_map_rule_cmd route_set_ecommunity_soo_cmd = { /* `set origin ORIGIN' */ /* For origin set. */ -static route_map_result_t route_set_origin(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_origin(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { uint8_t *origin; struct bgp_path_info *path; @@ -2342,10 +2337,9 @@ struct route_map_rule_cmd route_set_origin_cmd = { /* `set atomic-aggregate' */ /* For atomic aggregate set. */ -static route_map_result_t route_set_atomic_aggregate(void *rule, - const struct prefix *pfx, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_atomic_aggregate(void *rule, const struct prefix *pfx, + route_map_object_t type, void *object) { struct bgp_path_info *path; @@ -2381,10 +2375,9 @@ struct aggregator { struct in_addr address; }; -static route_map_result_t route_set_aggregator_as(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_aggregator_as(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct bgp_path_info *path; struct aggregator *aggregator; @@ -2435,9 +2428,9 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = { }; /* Set tag to object. object must be pointer to struct bgp_path_info */ -static route_map_result_t route_set_tag(void *rule, - const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_set_tag(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { route_tag_t *tag; struct bgp_path_info *path; @@ -2460,10 +2453,9 @@ static struct route_map_rule_cmd route_set_tag_cmd = { }; /* Set label-index to object. object must be pointer to struct bgp_path_info */ -static route_map_result_t route_set_label_index(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_label_index(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rmap_value *rv; struct bgp_path_info *path; @@ -2493,10 +2485,9 @@ static struct route_map_rule_cmd route_set_label_index_cmd = { /* `match ipv6 address IP_ACCESS_LIST' */ -static route_map_result_t route_match_ipv6_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ipv6_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; @@ -2529,10 +2520,9 @@ struct route_map_rule_cmd route_match_ipv6_address_cmd = { /* `match ipv6 next-hop IP_ADDRESS' */ -static route_map_result_t route_match_ipv6_next_hop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct in6_addr *addr = rule; struct bgp_path_info *path; @@ -2581,7 +2571,7 @@ struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = { /* `match ipv6 address prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2606,9 +2596,9 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { /* `match ipv6 next-hop type <TYPE>' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + route_map_object_t type, void *object) { struct bgp_path_info *path; struct in6_addr *addr = rule; @@ -2616,7 +2606,7 @@ route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, if (type == RMAP_BGP && prefix->family == AF_INET6) { path = (struct bgp_path_info *)object; if (!path || !path->attr) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr) && !path->attr->nh_ifindex) @@ -2654,10 +2644,9 @@ struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = { /* `set ipv6 nexthop global IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_ipv6_nexthop_global(void *rule, - const struct prefix *p, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, + route_map_object_t type, void *object) { struct in6_addr *address; struct bgp_path_info *path; @@ -2713,7 +2702,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = { route_set_ipv6_nexthop_global_free}; /* Set next-hop preference value. */ -static route_map_result_t +static enum route_map_cmd_result_t route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2767,10 +2756,9 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = { /* `set ipv6 nexthop local IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_ipv6_nexthop_local(void *rule, - const struct prefix *p, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, + route_map_object_t type, void *object) { struct in6_addr *address; struct bgp_path_info *path; @@ -2830,10 +2818,9 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = { /* `set ipv6 nexthop peer-address' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_ipv6_nexthop_peer(void *rule, - const struct prefix *pfx, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, + route_map_object_t type, void *object) { struct in6_addr peer_address; struct bgp_path_info *path; @@ -2908,10 +2895,9 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = { /* `set ipv4 vpn next-hop A.B.C.D' */ -static route_map_result_t route_set_vpnv4_nexthop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct in_addr *address; struct bgp_path_info *path; @@ -2948,10 +2934,9 @@ static void *route_set_vpnv4_nexthop_compile(const char *arg) /* `set ipv6 vpn next-hop A.B.C.D' */ -static route_map_result_t route_set_vpnv6_nexthop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct in6_addr *address; struct bgp_path_info *path; @@ -3004,10 +2989,9 @@ struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = { /* `set originator-id' */ /* For origin set. */ -static route_map_result_t route_set_originator_id(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_originator_id(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct in_addr *address; struct bgp_path_info *path; diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 0637723990..408d423aac 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -129,8 +129,10 @@ static void print_record(const struct pfx_record *record, struct vty *vty); static int is_synchronized(void); static int is_running(void); static void route_match_free(void *rule); -static route_map_result_t route_match(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object); +static enum route_map_cmd_result_t route_match(void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object); static void *route_match_compile(const char *arg); static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi, safi_t safi); @@ -213,8 +215,10 @@ static void ipv6_addr_to_host_byte_order(const uint32_t *src, uint32_t *dest) dest[i] = ntohl(src[i]); } -static route_map_result_t route_match(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t route_match(void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object) { int *rpki_status = rule; struct bgp_path_info *path; diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index b64c51f341..21f1dff60d 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -716,7 +716,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) struct bgp_node *rn; struct bgp_path_info *ri; struct peer *peer; - int ret = RMAP_DENYMATCH; + route_map_result_t ret = RMAP_DENYMATCH; afi_t afi; safi_t safi; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index d7f6b65384..27042017dd 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -624,18 +624,12 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); - else - found = true; } /* This is to apply read-only mode on this clear. */ if (stype == BGP_CLEAR_SOFT_NONE) bgp->update_delay_over = 0; - if (!found) - vty_out(vty, "%%BGP: No %s peer configured\n", - afi_safi_print(afi, safi)); - return CMD_SUCCESS; } @@ -7287,6 +7281,9 @@ DEFUN (clear_ip_bgp_all, } else if (argv_find(argv, argc, "PGNAME", &idx)) { clr_sort = clear_peer; clr_arg = argv[idx]->arg; + } else if (argv_find(argv, argc, "WORD", &idx)) { + clr_sort = clear_peer; + clr_arg = argv[idx]->arg; } else if (argv_find(argv, argc, "(1-4294967295)", &idx)) { clr_sort = clear_as; clr_arg = argv[idx]->arg; @@ -13199,20 +13196,44 @@ void bgp_vty_init(void) install_element(BGP_NODE, &no_neighbor_nexthop_self_all_hidden_cmd); install_element(BGP_IPV4_NODE, &neighbor_nexthop_self_force_cmd); install_element(BGP_IPV4_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV4_NODE, &neighbor_nexthop_self_all_hidden_cmd); + install_element(BGP_IPV4_NODE, + &no_neighbor_nexthop_self_all_hidden_cmd); install_element(BGP_IPV4M_NODE, &neighbor_nexthop_self_force_cmd); install_element(BGP_IPV4M_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_nexthop_self_all_hidden_cmd); + install_element(BGP_IPV4M_NODE, + &no_neighbor_nexthop_self_all_hidden_cmd); install_element(BGP_IPV4L_NODE, &neighbor_nexthop_self_force_cmd); install_element(BGP_IPV4L_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_nexthop_self_all_hidden_cmd); + install_element(BGP_IPV4L_NODE, + &no_neighbor_nexthop_self_all_hidden_cmd); install_element(BGP_IPV6_NODE, &neighbor_nexthop_self_force_cmd); install_element(BGP_IPV6_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6_NODE, &neighbor_nexthop_self_all_hidden_cmd); + install_element(BGP_IPV6_NODE, + &no_neighbor_nexthop_self_all_hidden_cmd); install_element(BGP_IPV6M_NODE, &neighbor_nexthop_self_force_cmd); install_element(BGP_IPV6M_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_nexthop_self_all_hidden_cmd); + install_element(BGP_IPV6M_NODE, + &no_neighbor_nexthop_self_all_hidden_cmd); install_element(BGP_IPV6L_NODE, &neighbor_nexthop_self_force_cmd); install_element(BGP_IPV6L_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_nexthop_self_all_hidden_cmd); + install_element(BGP_IPV6L_NODE, + &no_neighbor_nexthop_self_all_hidden_cmd); install_element(BGP_VPNV4_NODE, &neighbor_nexthop_self_force_cmd); install_element(BGP_VPNV4_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_nexthop_self_all_hidden_cmd); + install_element(BGP_VPNV4_NODE, + &no_neighbor_nexthop_self_all_hidden_cmd); install_element(BGP_VPNV6_NODE, &neighbor_nexthop_self_force_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_nexthop_self_all_hidden_cmd); + install_element(BGP_VPNV6_NODE, + &no_neighbor_nexthop_self_all_hidden_cmd); /* "neighbor as-override" commands. */ install_element(BGP_NODE, &neighbor_as_override_hidden_cmd); diff --git a/doc/developer/cli.rst b/doc/developer/cli.rst index c0716a5c93..cf35b03f0c 100644 --- a/doc/developer/cli.rst +++ b/doc/developer/cli.rst @@ -160,27 +160,27 @@ parser, but this is merely a dumb copy job. Here is a brief summary of the various token types along with examples. -+-----------------+-----------------+-------------------------------------------------------------+ -| Token type | Syntax | Description | -+=================+=================+=============================================================+ -| ``WORD`` | ``show ip bgp`` | Matches itself. In the given example every token is a WORD. | -+-----------------+-----------------+-------------------------------------------------------------+ -| ``IPV4`` | ``A.B.C.D`` | Matches an IPv4 address. | -+-----------------+-----------------+-------------------------------------------------------------+ -| ``IPV6`` | ``X:X::X:X`` | Matches an IPv6 address. | -+-----------------+-----------------+-------------------------------------------------------------+ -| ``IPV4_PREFIX`` | ``A.B.C.D/M`` | Matches an IPv4 prefix in CIDR notation. | -+-----------------+-----------------+-------------------------------------------------------------+ -| ``IPV6_PREFIX`` | ``X:X::X:X/M`` | Matches an IPv6 prefix in CIDR notation. | -+-----------------+-----------------+-------------------------------------------------------------+ -| ``MAC`` | ``M:A:C`` | Matches a 48-bit mac address. | -+-----------------+-----------------+-------------------------------------------------------------+ -| ``MAC_PREFIX`` | ``M:A:C/M`` | Matches a 48-bit mac address with a mask. | -+-----------------+-----------------+-------------------------------------------------------------+ -| ``VARIABLE`` | ``FOOBAR`` | Matches anything. | -+-----------------+-----------------+-------------------------------------------------------------+ -| ``RANGE`` | ``(X-Y)`` | Matches numbers in the range X..Y inclusive. | -+-----------------+-----------------+-------------------------------------------------------------+ ++-----------------+-------------------+-------------------------------------------------------------+ +| Token type | Syntax | Description | ++=================+===================+=============================================================+ +| ``WORD`` | ``show ip bgp`` | Matches itself. In the given example every token is a WORD. | ++-----------------+-------------------+-------------------------------------------------------------+ +| ``IPV4`` | ``A.B.C.D`` | Matches an IPv4 address. | ++-----------------+-------------------+-------------------------------------------------------------+ +| ``IPV6`` | ``X:X::X:X`` | Matches an IPv6 address. | ++-----------------+-------------------+-------------------------------------------------------------+ +| ``IPV4_PREFIX`` | ``A.B.C.D/M`` | Matches an IPv4 prefix in CIDR notation. | ++-----------------+-------------------+-------------------------------------------------------------+ +| ``IPV6_PREFIX`` | ``X:X::X:X/M`` | Matches an IPv6 prefix in CIDR notation. | ++-----------------+-------------------+-------------------------------------------------------------+ +| ``MAC`` | ``X:X:X:X:X:X`` | Matches a 48-bit mac address. | ++-----------------+-------------------+-------------------------------------------------------------+ +| ``MAC_PREFIX`` | ``X:X:X:X:X:X/M`` | Matches a 48-bit mac address with a mask. | ++-----------------+-------------------+-------------------------------------------------------------+ +| ``VARIABLE`` | ``FOOBAR`` | Matches anything. | ++-----------------+-------------------+-------------------------------------------------------------+ +| ``RANGE`` | ``(X-Y)`` | Matches numbers in the range X..Y inclusive. | ++-----------------+-------------------+-------------------------------------------------------------+ When presented with user input, the parser will search over all defined commands in the current context to find a match. It is aware of the various diff --git a/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c index f080ba4876..bac7494774 100644 --- a/eigrpd/eigrp_routemap.c +++ b/eigrpd/eigrp_routemap.c @@ -251,9 +251,9 @@ void eigrp_route_map_update(const char *notused) /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_metric(void *rule, struct prefix *prefix, route_map_object_t type, + void *object) { // uint32_t *metric; // uint32_t check; @@ -311,10 +311,9 @@ struct route_map_rule_cmd route_match_metric_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_interface(void *rule, - struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_interface(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { // struct rip_info *rinfo; // struct interface *ifp; @@ -360,10 +359,9 @@ struct route_map_rule_cmd route_match_interface_cmd = { /* `match ip next-hop IP_ACCESS_LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_next_hop(void *rule, - struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_next_hop(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { // struct access_list *alist; // struct rip_info *rinfo; @@ -407,7 +405,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { @@ -452,10 +450,9 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_address(void *rule, - struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_address(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; @@ -491,7 +488,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { @@ -526,8 +523,9 @@ static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_match_tag(void *rule, struct prefix *prefix, route_map_object_t type, + void *object) { // unsigned short *tag; // struct rip_info *rinfo; @@ -568,9 +566,9 @@ struct route_map_rule_cmd route_match_tag_cmd = { "tag", route_match_tag, route_match_tag_compile, route_match_tag_free}; /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { // if (type == RMAP_RIP) // { @@ -662,10 +660,9 @@ static struct route_map_rule_cmd route_set_metric_cmd = { /* `set ip next-hop IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_ip_nexthop(void *rule, - struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_ip_nexthop(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { // struct in_addr *address; // struct rip_info *rinfo; @@ -718,8 +715,9 @@ static struct route_map_rule_cmd route_set_ip_nexthop_cmd = { /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_set_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { // unsigned short *tag; // struct rip_info *rinfo; diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index d63676256b..eb9b661d37 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -48,10 +48,9 @@ #include "isis_zebra.h" #include "isis_routemap.h" -static route_map_result_t route_match_ip_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; @@ -81,7 +80,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* ------------------------------------------------------------*/ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -114,10 +113,9 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* ------------------------------------------------------------*/ -static route_map_result_t route_match_ipv6_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ipv6_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; @@ -147,7 +145,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_cmd = { /* ------------------------------------------------------------*/ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -180,10 +178,9 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { /* ------------------------------------------------------------*/ -static route_map_result_t route_set_metric(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_metric(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { uint32_t *metric; struct isis_ext_info *info; diff --git a/lib/compiler.h b/lib/compiler.h index 7c7f4ce294..6700ca9e8b 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -165,6 +165,13 @@ extern "C" { _min_a < _min_b ? _min_a : _min_b; \ }) +#define numcmp(a, b) \ + ({ \ + typeof(a) _cmp_a = (a); \ + typeof(b) _cmp_b = (b); \ + (_cmp_a < _cmp_b) ? -1 : ((_cmp_a > _cmp_b) ? 1 : 0); \ + }) + #ifndef offsetof #ifdef __compiler_offsetof #define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER) diff --git a/lib/filter.c b/lib/filter.c index 276df4b4d7..14b89217b8 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -60,6 +60,9 @@ struct filter { /* Filter type information. */ enum filter_type type; + /* Sequence number */ + int64_t seq; + /* Cisco access-list */ int cisco; @@ -406,23 +409,35 @@ void access_list_delete_hook(void (*func)(struct access_list *access)) access_master_mac.delete_hook = func; } -/* Add new filter to the end of specified access_list. */ -static void access_list_filter_add(struct access_list *access, - struct filter *filter) +/* Calculate new sequential number. */ +static int64_t filter_new_seq_get(struct access_list *access) { - filter->next = NULL; - filter->prev = access->tail; + int64_t maxseq; + int64_t newseq; + struct filter *filter; - if (access->tail) - access->tail->next = filter; - else - access->head = filter; - access->tail = filter; + maxseq = newseq = 0; - /* Run hook function. */ - if (access->master->add_hook) - (*access->master->add_hook)(access); - route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_ADDED); + for (filter = access->head; filter; filter = filter->next) { + if (maxseq < filter->seq) + maxseq = filter->seq; + } + + newseq = ((maxseq / 5) * 5) + 5; + + return (newseq > UINT_MAX) ? UINT_MAX : newseq; +} + +/* Return access list entry which has same seq number. */ +static struct filter *filter_seq_check(struct access_list *access, + int64_t seq) +{ + struct filter *filter; + + for (filter = access->head; filter; filter = filter->next) + if (filter->seq == seq) + return filter; + return NULL; } /* If access_list has no filter then return 1. */ @@ -465,6 +480,58 @@ static void access_list_filter_delete(struct access_list *access, access_list_delete(access); } +/* Add new filter to the end of specified access_list. */ +static void access_list_filter_add(struct access_list *access, + struct filter *filter) +{ + struct filter *replace; + struct filter *point; + + /* Automatic asignment of seq no. */ + if (filter->seq == -1) + filter->seq = filter_new_seq_get(access); + + if (access->tail && filter->seq > access->tail->seq) + point = NULL; + else { + /* Is there any same seq access list filter? */ + replace = filter_seq_check(access, filter->seq); + if (replace) + access_list_filter_delete(access, replace); + + /* Check insert point. */ + for (point = access->head; point; point = point->next) + if (point->seq >= filter->seq) + break; + } + + /* In case of this is the first element of the list. */ + filter->next = point; + + if (point) { + if (point->prev) + point->prev->next = filter; + else + access->head = filter; + + filter->prev = point->prev; + point->prev = filter; + } else { + if (access->tail) + access->tail->next = filter; + else + access->head = filter; + + filter->prev = access->tail; + access->tail = filter; + } + + /* Run hook function. */ + if (access->master->add_hook) + (*access->master->add_hook)(access); + route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_ADDED); +} + /* deny Specify packets to reject permit Specify packets to forward @@ -553,12 +620,13 @@ static int vty_access_list_remark_unset(struct vty *vty, afi_t afi, } static int filter_set_cisco(struct vty *vty, const char *name_str, - const char *type_str, const char *addr_str, - const char *addr_mask_str, const char *mask_str, - const char *mask_mask_str, int extended, int set) + const char *seq, const char *type_str, + const char *addr_str, const char *addr_mask_str, + const char *mask_str, const char *mask_mask_str, + int extended, int set) { int ret; - enum filter_type type; + enum filter_type type = FILTER_DENY; struct filter *mfilter; struct filter_cisco *filter; struct access_list *access; @@ -566,15 +634,21 @@ static int filter_set_cisco(struct vty *vty, const char *name_str, struct in_addr addr_mask; struct in_addr mask; struct in_addr mask_mask; + int64_t seqnum = -1; + + if (seq) + seqnum = (int64_t)atol(seq); /* Check of filter type. */ - if (strncmp(type_str, "p", 1) == 0) - type = FILTER_PERMIT; - else if (strncmp(type_str, "d", 1) == 0) - type = FILTER_DENY; - else { - vty_out(vty, "%% filter type must be permit or deny\n"); - return CMD_WARNING_CONFIG_FAILED; + if (type_str) { + if (strncmp(type_str, "p", 1) == 0) + type = FILTER_PERMIT; + else if (strncmp(type_str, "d", 1) == 0) + type = FILTER_DENY; + else { + vty_out(vty, "%% filter type must be permit or deny\n"); + return CMD_WARNING_CONFIG_FAILED; + } } ret = inet_aton(addr_str, &addr); @@ -606,6 +680,7 @@ static int filter_set_cisco(struct vty *vty, const char *name_str, mfilter = filter_new(); mfilter->type = type; mfilter->cisco = 1; + mfilter->seq = seqnum; filter = &mfilter->u.cfilter; filter->extended = extended; filter->addr.s_addr = addr.s_addr & ~addr_mask.s_addr; @@ -640,163 +715,311 @@ static int filter_set_cisco(struct vty *vty, const char *name_str, /* Standard access-list */ DEFUN (access_list_standard, access_list_standard_cmd, - "access-list <(1-99)|(1300-1999)> <deny|permit> A.B.C.D A.B.C.D", + "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> A.B.C.D A.B.C.D", "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Address to match\n" "Wildcard bits\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, NULL, NULL, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + char *wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + address = argv[idx]->arg; + wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, wildcard, NULL, NULL, 0, 1); } DEFUN (access_list_standard_nomask, access_list_standard_nomask_cmd, - "access-list <(1-99)|(1300-1999)> <deny|permit> A.B.C.D", + "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> A.B.C.D", "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Address to match\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 3; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", NULL, NULL, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + address = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, "0.0.0.0", NULL, NULL, 0, 1); } DEFUN (access_list_standard_host, access_list_standard_host_cmd, - "access-list <(1-99)|(1300-1999)> <deny|permit> host A.B.C.D", + "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> host A.B.C.D", "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "A single host address\n" "Address to match\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", NULL, NULL, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + address = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, "0.0.0.0", NULL, NULL, 0, 1); } DEFUN (access_list_standard_any, access_list_standard_any_cmd, - "access-list <(1-99)|(1300-1999)> <deny|permit> any", + "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> any", "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any source host\n") { int idx_acl = 1; - int idx_permit_deny = 2; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", NULL, NULL, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", NULL, NULL, 0, 1); } DEFUN (no_access_list_standard, no_access_list_standard_cmd, - "no access-list <(1-99)|(1300-1999)> <deny|permit> A.B.C.D A.B.C.D", + "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> A.B.C.D A.B.C.D", NO_STR "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Address to match\n" "Wildcard bits\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, NULL, NULL, 0, 0); + int idx_acl = 1; + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + char *wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + address = argv[idx]->arg; + wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, wildcard, NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_nomask, no_access_list_standard_nomask_cmd, - "no access-list <(1-99)|(1300-1999)> <deny|permit> A.B.C.D", + "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> A.B.C.D", NO_STR "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Address to match\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 4; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", NULL, NULL, 0, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + address = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, "0.0.0.0", NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_host, no_access_list_standard_host_cmd, - "no access-list <(1-99)|(1300-1999)> <deny|permit> host A.B.C.D", + "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> host A.B.C.D", NO_STR "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "A single host address\n" "Address to match\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", NULL, NULL, 0, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + address = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, "0.0.0.0", NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_any, no_access_list_standard_any_cmd, - "no access-list <(1-99)|(1300-1999)> <deny|permit> any", + "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> any", NO_STR "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any source host\n") { int idx_acl = 2; - int idx_permit_deny = 3; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", NULL, NULL, 0, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", NULL, NULL, 0, 0); } /* Extended access-list */ DEFUN (access_list_extended, access_list_extended_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -806,23 +1029,45 @@ DEFUN (access_list_extended, "Destination Wildcard bits\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - int idx_ipv4_3 = 6; - int idx_ipv4_4 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - argv[idx_ipv4_4]->arg, 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *src_wildcard = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + dst = argv[idx + 2]->arg; + dst_wildcard = argv[idx + 3]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, dst, dst_wildcard, 1, 1); } DEFUN (access_list_extended_mask_any, access_list_extended_mask_any_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D any", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D any", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -831,21 +1076,42 @@ DEFUN (access_list_extended_mask_any, "Any destination host\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, "0.0.0.0", - "255.255.255.255", 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *src_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, "0.0.0.0", "255.255.255.255", 1, + 1); } DEFUN (access_list_extended_any_mask, access_list_extended_any_mask_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip any A.B.C.D A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any A.B.C.D A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -854,21 +1120,42 @@ DEFUN (access_list_extended_any_mask, "Destination Wildcard bits\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *dst = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + dst = argv[idx]->arg; + dst_wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", dst, dst_wildcard, + 1, 1); } DEFUN (access_list_extended_any_any, access_list_extended_any_any_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip any any", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any any", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -876,18 +1163,33 @@ DEFUN (access_list_extended_any_any, "Any destination host\n") { int idx_acl = 1; - int idx_permit_deny = 2; - return filter_set_cisco( - vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", "0.0.0.0", "255.255.255.255", 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", "0.0.0.0", + "255.255.255.255", 1, 1); } DEFUN (access_list_extended_mask_host, access_list_extended_mask_host_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D host A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D host A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -897,22 +1199,43 @@ DEFUN (access_list_extended_mask_host, "Destination address\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - int idx_ipv4_3 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - "0.0.0.0", 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *src_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + dst = argv[idx + 3]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, dst, "0.0.0.0", 1, 1); } DEFUN (access_list_extended_host_mask, access_list_extended_host_mask_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D A.B.C.D A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D A.B.C.D A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -922,22 +1245,43 @@ DEFUN (access_list_extended_host_mask, "Destination Wildcard bits\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, - argv[idx_ipv4_3]->arg, 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + dst = argv[idx + 1]->arg; + dst_wildcard = argv[idx + 2]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + "0.0.0.0", dst, dst_wildcard, 1, 1); } DEFUN (access_list_extended_host_host, access_list_extended_host_host_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D host A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D host A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -947,21 +1291,41 @@ DEFUN (access_list_extended_host_host, "Destination address\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, "0.0.0.0", 1, - 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + dst = argv[idx + 2]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + "0.0.0.0", dst, "0.0.0.0", 1, 1); } DEFUN (access_list_extended_any_host, access_list_extended_any_host_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip any host A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any host A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -970,19 +1334,39 @@ DEFUN (access_list_extended_any_host, "Destination address\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 6; - return filter_set_cisco( - vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, "0.0.0.0", 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *dst = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + dst = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", dst, "0.0.0.0", 1, + 1); } DEFUN (access_list_extended_host_any, access_list_extended_host_any_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D any", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D any", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -991,20 +1375,39 @@ DEFUN (access_list_extended_host_any, "Any destination host\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + src = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, "0.0.0.0", "0.0.0.0", "255.255.255.255", 1, 1); } DEFUN (no_access_list_extended, no_access_list_extended_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1014,24 +1417,46 @@ DEFUN (no_access_list_extended, "Destination Wildcard bits\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 7; - int idx_ipv4_4 = 8; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - argv[idx_ipv4_4]->arg, 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *src_wildcard = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + dst = argv[idx + 2]->arg; + dst_wildcard = argv[idx + 3]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, dst, dst_wildcard, 1, 0); } DEFUN (no_access_list_extended_mask_any, no_access_list_extended_mask_any_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D any", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D any", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1040,22 +1465,43 @@ DEFUN (no_access_list_extended_mask_any, "Any destination host\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, "0.0.0.0", - "255.255.255.255", 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *src_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, "0.0.0.0", "255.255.255.255", 1, + 0); } DEFUN (no_access_list_extended_any_mask, no_access_list_extended_any_mask_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip any A.B.C.D A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any A.B.C.D A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1064,22 +1510,43 @@ DEFUN (no_access_list_extended_any_mask, "Destination Wildcard bits\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *dst = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + dst = argv[idx]->arg; + dst_wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", dst, dst_wildcard, + 1, 0); } DEFUN (no_access_list_extended_any_any, no_access_list_extended_any_any_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip any any", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any any", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1087,19 +1554,34 @@ DEFUN (no_access_list_extended_any_any, "Any destination host\n") { int idx_acl = 2; - int idx_permit_deny = 3; - return filter_set_cisco( - vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", "0.0.0.0", "255.255.255.255", 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", "0.0.0.0", + "255.255.255.255", 1, 0); } DEFUN (no_access_list_extended_mask_host, no_access_list_extended_mask_host_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D host A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D host A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1109,23 +1591,44 @@ DEFUN (no_access_list_extended_mask_host, "Destination address\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 8; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - "0.0.0.0", 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *src_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + dst = argv[idx + 3]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, dst, "0.0.0.0", 1, 0); } DEFUN (no_access_list_extended_host_mask, no_access_list_extended_host_mask_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D A.B.C.D A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D A.B.C.D A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1135,23 +1638,44 @@ DEFUN (no_access_list_extended_host_mask, "Destination Wildcard bits\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 7; - int idx_ipv4_3 = 8; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, - argv[idx_ipv4_3]->arg, 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + dst = argv[idx + 1]->arg; + dst_wildcard = argv[idx + 2]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + "0.0.0.0", dst, dst_wildcard, 1, 0); } DEFUN (no_access_list_extended_host_host, no_access_list_extended_host_host_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D host A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D host A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1161,22 +1685,42 @@ DEFUN (no_access_list_extended_host_host, "Destination address\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 8; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, "0.0.0.0", 1, - 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + dst = argv[idx + 2]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + "0.0.0.0", dst, "0.0.0.0", 1, 0); } DEFUN (no_access_list_extended_any_host, no_access_list_extended_any_host_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip any host A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any host A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1185,20 +1729,40 @@ DEFUN (no_access_list_extended_any_host, "Destination address\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 7; - return filter_set_cisco( - vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, "0.0.0.0", 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *dst = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + dst = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", dst, "0.0.0.0", 1, + 0); } DEFUN (no_access_list_extended_host_any, no_access_list_extended_host_any_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D any", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D any", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1207,23 +1771,41 @@ DEFUN (no_access_list_extended_host_any, "Any destination host\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + src = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, "0.0.0.0", "0.0.0.0", "255.255.255.255", 1, 0); } static int filter_set_zebra(struct vty *vty, const char *name_str, - const char *type_str, afi_t afi, + const char *seq, const char *type_str, afi_t afi, const char *prefix_str, int exact, int set) { int ret; - enum filter_type type; + enum filter_type type = FILTER_DENY; struct filter *mfilter; struct filter_zebra *filter; struct access_list *access; struct prefix p; + int64_t seqnum = -1; if (strlen(name_str) > ACL_NAMSIZ) { vty_out(vty, @@ -1233,14 +1815,19 @@ static int filter_set_zebra(struct vty *vty, const char *name_str, return CMD_WARNING_CONFIG_FAILED; } + if (seq) + seqnum = (int64_t)atol(seq); + /* Check of filter type. */ - if (strncmp(type_str, "p", 1) == 0) - type = FILTER_PERMIT; - else if (strncmp(type_str, "d", 1) == 0) - type = FILTER_DENY; - else { - vty_out(vty, "filter type must be [permit|deny]\n"); - return CMD_WARNING_CONFIG_FAILED; + if (type_str) { + if (strncmp(type_str, "p", 1) == 0) + type = FILTER_PERMIT; + else if (strncmp(type_str, "d", 1) == 0) + type = FILTER_DENY; + else { + vty_out(vty, "filter type must be [permit|deny]\n"); + return CMD_WARNING_CONFIG_FAILED; + } } /* Check string format of prefix and prefixlen. */ @@ -1269,6 +1856,7 @@ static int filter_set_zebra(struct vty *vty, const char *name_str, mfilter = filter_new(); mfilter->type = type; + mfilter->seq = seqnum; filter = &mfilter->u.zfilter; prefix_copy(&filter->prefix, &p); @@ -1298,67 +1886,145 @@ static int filter_set_zebra(struct vty *vty, const char *name_str, DEFUN (mac_access_list, mac_access_list_cmd, - "mac access-list WORD <deny|permit> X:X:X:X:X:X", + "mac access-list WORD [seq (1-4294967295)] <deny|permit> X:X:X:X:X:X", "Add a mac access-list\n" "Add an access list entry\n" "MAC zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "MAC address to match. e.g. 00:01:00:01:00:01\n") { - return filter_set_zebra(vty, argv[2]->arg, argv[3]->arg, AFI_L2VPN, - argv[4]->arg, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *mac = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "X:X:X:X:X:X", &idx); + if (idx) + mac = argv[idx]->arg; + + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, + mac, 0, 1); } DEFUN (no_mac_access_list, no_mac_access_list_cmd, - "no mac access-list WORD <deny|permit> X:X:X:X:X:X", + "no mac access-list WORD [seq (1-4294967295)] <deny|permit> X:X:X:X:X:X", NO_STR "Remove a mac access-list\n" "Remove an access list entry\n" "MAC zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "MAC address to match. e.g. 00:01:00:01:00:01\n") { - return filter_set_zebra(vty, argv[3]->arg, argv[4]->arg, AFI_L2VPN, - argv[5]->arg, 0, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *mac = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "X:X:X:X:X:X", &idx); + if (idx) + mac = argv[idx]->arg; + + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, + mac, 0, 0); } DEFUN (mac_access_list_any, mac_access_list_any_cmd, - "mac access-list WORD <deny|permit> any", + "mac access-list WORD [seq (1-4294967295)] <deny|permit> any", "Add a mac access-list\n" "Add an access list entry\n" "MAC zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "MAC address to match. e.g. 00:01:00:01:00:01\n") { - return filter_set_zebra(vty, argv[2]->arg, argv[3]->arg, AFI_L2VPN, + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, "00:00:00:00:00:00", 0, 1); } DEFUN (no_mac_access_list_any, no_mac_access_list_any_cmd, - "no mac access-list WORD <deny|permit> any", + "no mac access-list WORD [seq (1-4294967295)] <deny|permit> any", NO_STR "Remove a mac access-list\n" "Remove an access list entry\n" "MAC zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "MAC address to match. e.g. 00:01:00:01:00:01\n") { - return filter_set_zebra(vty, argv[3]->arg, argv[4]->arg, AFI_L2VPN, + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, "00:00:00:00:00:00", 0, 0); } DEFUN (access_list_exact, access_list_exact_cmd, - "access-list WORD <deny|permit> A.B.C.D/M [exact-match]", + "access-list WORD [seq (1-4294967295)] <deny|permit> A.B.C.D/M [exact-match]", "Add an access list entry\n" "IP zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n" @@ -1366,41 +2032,71 @@ DEFUN (access_list_exact, { int idx = 0; int exact = 0; - int idx_word = 1; - int idx_permit_deny = 2; - int idx_ipv4_prefixlen = 3; - idx = idx_ipv4_prefixlen; - + char *seq = NULL; + char *permit_deny = NULL; + char *prefix = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D/M", &idx); + if (idx) + prefix = argv[idx]->arg; + + idx = 0; if (argv_find(argv, argc, "exact-match", &idx)) exact = 1; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP, - argv[idx_ipv4_prefixlen]->arg, exact, 1); + return filter_set_zebra(vty, argv[1]->arg, seq, permit_deny, + AFI_IP, prefix, exact, 1); } DEFUN (access_list_any, access_list_any_cmd, - "access-list WORD <deny|permit> any", + "access-list WORD [seq (1-4294967295)] <deny|permit> any", "Add an access list entry\n" "IP zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n") { int idx_word = 1; - int idx_permit_deny = 2; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP, "0.0.0.0/0", - 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP, "0.0.0.0/0", 0, 1); } DEFUN (no_access_list_exact, no_access_list_exact_cmd, - "no access-list WORD <deny|permit> A.B.C.D/M [exact-match]", + "no access-list WORD [seq (1-4294967295)] <deny|permit> A.B.C.D/M [exact-match]", NO_STR "Add an access list entry\n" "IP zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n" @@ -1408,34 +2104,62 @@ DEFUN (no_access_list_exact, { int idx = 0; int exact = 0; - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv4_prefixlen = 4; - idx = idx_ipv4_prefixlen; - + char *seq = NULL; + char *permit_deny = NULL; + char *prefix = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D/M", &idx); + if (idx) + prefix = argv[idx]->arg; + + idx = 0; if (argv_find(argv, argc, "exact-match", &idx)) exact = 1; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP, - argv[idx_ipv4_prefixlen]->arg, exact, 0); + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, + AFI_IP, prefix, exact, 0); } DEFUN (no_access_list_any, no_access_list_any_cmd, - "no access-list WORD <deny|permit> any", + "no access-list WORD [seq (1-4294967295)] <deny|permit> any", NO_STR "Add an access list entry\n" "IP zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n") { - int idx_word = 2; - int idx_permit_deny = 3; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP, "0.0.0.0/0", - 0, 0); + int idx_word = 1; + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP, "0.0.0.0/0", 0, 0); } DEFUN (no_access_list_all, @@ -1536,10 +2260,12 @@ DEFUN (no_access_list_remark_comment, DEFUN (ipv6_access_list_exact, ipv6_access_list_exact_cmd, - "ipv6 access-list WORD <deny|permit> X:X::X:X/M [exact-match]", + "ipv6 access-list WORD [seq (1-4294967295)] <deny|permit> X:X::X:X/M [exact-match]", IPV6_STR "Add an access list entry\n" "IPv6 zebra access-list\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "IPv6 prefix\n" @@ -1548,41 +2274,73 @@ DEFUN (ipv6_access_list_exact, int idx = 0; int exact = 0; int idx_word = 2; - int idx_allow = 3; - int idx_addr = 4; - idx = idx_addr; - + char *seq = NULL; + char *permit_deny = NULL; + char *prefix = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "X:X::X:X/M", &idx); + if (idx) + prefix = argv[idx]->arg; + + idx = 0; if (argv_find(argv, argc, "exact-match", &idx)) exact = 1; - return filter_set_zebra(vty, argv[idx_word]->arg, argv[idx_allow]->text, - AFI_IP6, argv[idx_addr]->arg, exact, 1); + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP6, prefix, exact, 1); } DEFUN (ipv6_access_list_any, ipv6_access_list_any_cmd, - "ipv6 access-list WORD <deny|permit> any", + "ipv6 access-list WORD [seq (1-4294967295)] <deny|permit> any", IPV6_STR "Add an access list entry\n" "IPv6 zebra access-list\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any prefixi to match\n") { int idx_word = 2; - int idx_permit_deny = 3; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP6, "::/0", 0, - 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP6, "::/0", 0, 1); } DEFUN (no_ipv6_access_list_exact, no_ipv6_access_list_exact_cmd, - "no ipv6 access-list WORD <deny|permit> X:X::X:X/M [exact-match]", + "no ipv6 access-list WORD [seq (1-4294967295)] <deny|permit> X:X::X:X/M [exact-match]", NO_STR IPV6_STR "Add an access list entry\n" "IPv6 zebra access-list\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 3ffe:506::/32\n" @@ -1590,35 +2348,64 @@ DEFUN (no_ipv6_access_list_exact, { int idx = 0; int exact = 0; - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv6_prefixlen = 5; - idx = idx_ipv6_prefixlen; - + int idx_word = 2; + char *seq = NULL; + char *permit_deny = NULL; + char *prefix = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "X:X::X:X/M", &idx); + if (idx) + prefix = argv[idx]->arg; + + idx = 0; if (argv_find(argv, argc, "exact-match", &idx)) exact = 1; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP6, - argv[idx_ipv6_prefixlen]->arg, exact, 0); + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP6, prefix, exact, 0); } DEFUN (no_ipv6_access_list_any, no_ipv6_access_list_any_cmd, - "no ipv6 access-list WORD <deny|permit> any", + "no ipv6 access-list WORD [seq (1-4294967295)] <deny|permit> any", NO_STR IPV6_STR "Add an access list entry\n" "IPv6 zebra access-list\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any prefixi to match\n") { - int idx_word = 3; - int idx_permit_deny = 4; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP6, "::/0", 0, - 0); + int idx_word = 2; + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP6, "::/0", 0, 0); } @@ -1748,7 +2535,8 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi) write = 0; } - vty_out(vty, " %s%s", filter_type_str(mfilter), + vty_out(vty, " seq %" PRId64, mfilter->seq); + vty_out(vty, " %s%s", filter_type_str(mfilter), mfilter->type == FILTER_DENY ? " " : ""); if (!mfilter->cisco) @@ -1795,7 +2583,8 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi) write = 0; } - vty_out(vty, " %s%s", filter_type_str(mfilter), + vty_out(vty, " seq %" PRId64, mfilter->seq); + vty_out(vty, " %s%s", filter_type_str(mfilter), mfilter->type == FILTER_DENY ? " " : ""); if (!mfilter->cisco) @@ -1978,11 +2767,12 @@ static int config_write_access(struct vty *vty, afi_t afi) } for (mfilter = access->head; mfilter; mfilter = mfilter->next) { - vty_out(vty, "%saccess-list %s %s", + vty_out(vty, "%saccess-list %s seq %" PRId64 " %s", (afi == AFI_IP) ? ("") : ((afi == AFI_IP6) ? ("ipv6 ") : ("mac ")), - access->name, filter_type_str(mfilter)); + access->name, mfilter->seq, + filter_type_str(mfilter)); if (mfilter->cisco) config_write_access_cisco(vty, mfilter); @@ -2004,11 +2794,12 @@ static int config_write_access(struct vty *vty, afi_t afi) } for (mfilter = access->head; mfilter; mfilter = mfilter->next) { - vty_out(vty, "%saccess-list %s %s", + vty_out(vty, "%saccess-list %s seq %" PRId64 " %s", (afi == AFI_IP) ? ("") : ((afi == AFI_IP6) ? ("ipv6 ") : ("mac ")), - access->name, filter_type_str(mfilter)); + access->name, mfilter->seq, + filter_type_str(mfilter)); if (mfilter->cisco) config_write_access_cisco(vty, mfilter); diff --git a/lib/prefix.c b/lib/prefix.c index 7abeebcd09..1a4a914e05 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -628,8 +628,15 @@ int prefix_match_network_statement(const struct prefix *n, return 1; } -void prefix_copy(struct prefix *dest, const struct prefix *src) +#ifdef __clang_analyzer__ +#undef prefix_copy /* cf. prefix.h */ +#endif + +void prefix_copy(union prefixptr udest, union prefixconstptr usrc) { + struct prefix *dest = udest.p; + const struct prefix *src = usrc.p; + dest->family = src->family; dest->prefixlen = src->prefixlen; @@ -674,8 +681,11 @@ void prefix_copy(struct prefix *dest, const struct prefix *src) * the same. Note that this routine has the same return value sense * as '==' (which is different from prefix_cmp). */ -int prefix_same(const struct prefix *p1, const struct prefix *p2) +int prefix_same(union prefixconstptr up1, union prefixconstptr up2) { + const struct prefix *p1 = up1.p; + const struct prefix *p2 = up2.p; + if ((p1 && !p2) || (!p1 && p2)) return 0; @@ -712,57 +722,59 @@ int prefix_same(const struct prefix *p1, const struct prefix *p2) } /* - * Return 0 if the network prefixes represented by the struct prefix - * arguments are the same prefix, and 1 otherwise. Network prefixes - * are considered the same if the prefix lengths are equal and the - * network parts are the same. Host bits (which are considered masked + * Return -1/0/1 comparing the prefixes in a way that gives a full/linear + * order. + * + * Network prefixes are considered the same if the prefix lengths are equal + * and the network parts are the same. Host bits (which are considered masked * by the prefix length) are not significant. Thus, 10.0.0.1/8 and * 10.0.0.2/8 are considered equivalent by this routine. Note that * this routine has the same return sense as strcmp (which is different * from prefix_same). */ -int prefix_cmp(const struct prefix *p1, const struct prefix *p2) +int prefix_cmp(union prefixconstptr up1, union prefixconstptr up2) { + const struct prefix *p1 = up1.p; + const struct prefix *p2 = up2.p; int offset; int shift; + int i; /* Set both prefix's head pointer. */ const uint8_t *pp1; const uint8_t *pp2; if (p1->family != p2->family) - return 1; + return numcmp(p1->family, p2->family); if (p1->family == AF_FLOWSPEC) { pp1 = (const uint8_t *)p1->u.prefix_flowspec.ptr; pp2 = (const uint8_t *)p2->u.prefix_flowspec.ptr; if (p1->u.prefix_flowspec.prefixlen != p2->u.prefix_flowspec.prefixlen) - return 1; + return numcmp(p1->u.prefix_flowspec.prefixlen, + p2->u.prefix_flowspec.prefixlen); offset = p1->u.prefix_flowspec.prefixlen; while (offset--) if (pp1[offset] != pp2[offset]) - return 1; + return numcmp(pp1[offset], pp2[offset]); return 0; } pp1 = p1->u.val; pp2 = p2->u.val; if (p1->prefixlen != p2->prefixlen) - return 1; + return numcmp(p1->prefixlen, p2->prefixlen); offset = p1->prefixlen / PNBBY; shift = p1->prefixlen % PNBBY; - if (shift) - if (maskbit[shift] & (pp1[offset] ^ pp2[offset])) - return 1; - - while (offset--) - if (pp1[offset] != pp2[offset]) - return 1; + i = memcmp(pp1, pp2, offset); + if (i) + return i; - return 0; + return numcmp(pp1[offset] & maskbit[shift], + pp2[offset] & maskbit[shift]); } /* diff --git a/lib/prefix.h b/lib/prefix.h index d57b43dac6..e338140f1a 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -410,12 +410,20 @@ extern const char *prefix2str(union prefixconstptr, char *, int); extern int prefix_match(const struct prefix *, const struct prefix *); extern int prefix_match_network_statement(const struct prefix *, const struct prefix *); -extern int prefix_same(const struct prefix *, const struct prefix *); -extern int prefix_cmp(const struct prefix *, const struct prefix *); +extern int prefix_same(union prefixconstptr, union prefixconstptr); +extern int prefix_cmp(union prefixconstptr, union prefixconstptr); extern int prefix_common_bits(const struct prefix *, const struct prefix *); -extern void prefix_copy(struct prefix *dest, const struct prefix *src); +extern void prefix_copy(union prefixptr, union prefixconstptr); extern void apply_mask(struct prefix *); +#ifdef __clang_analyzer__ +/* clang-SA doesn't understand transparent unions, making it think that the + * target of prefix_copy is uninitialized. So just memset the target. + * cf. https://bugs.llvm.org/show_bug.cgi?id=42811 + */ +#define prefix_copy(a, b) ({ memset(a, 0, sizeof(*a)); prefix_copy(a, b); }) +#endif + extern struct prefix *sockunion2prefix(const union sockunion *dest, const union sockunion *mask); extern struct prefix *sockunion2hostprefix(const union sockunion *, diff --git a/lib/routemap.c b/lib/routemap.c index 2fee3a479e..eca02e8366 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -927,15 +927,15 @@ static const char *route_map_type_str(enum route_map_type type) return ""; } -static const char *route_map_result_str(route_map_result_t res) +static const char *route_map_cmd_result_str(enum route_map_cmd_result_t res) { switch (res) { case RMAP_MATCH: return "match"; - case RMAP_DENYMATCH: - return "deny"; case RMAP_NOMATCH: return "no match"; + case RMAP_NOOP: + return "noop"; case RMAP_ERROR: return "error"; case RMAP_OKAY: @@ -945,6 +945,18 @@ static const char *route_map_result_str(route_map_result_t res) return "invalid"; } +static const char *route_map_result_str(route_map_result_t res) +{ + switch (res) { + case RMAP_DENYMATCH: + return "deny"; + case RMAP_PERMITMATCH: + return "permit"; + } + + return "invalid"; +} + static int route_map_empty(struct route_map *map) { if (map->head == NULL && map->tail == NULL) @@ -1558,20 +1570,98 @@ int route_map_delete_set(struct route_map_index *index, const char *set_name, return 1; } +static enum route_map_cmd_result_t +route_map_apply_match(struct route_map_rule_list *match_list, + const struct prefix *prefix, route_map_object_t type, + void *object) +{ + enum route_map_cmd_result_t ret = RMAP_NOMATCH; + struct route_map_rule *match; + bool is_matched = false; + + + /* Check all match rule and if there is no match rule, go to the + set statement. */ + if (!match_list->head) + ret = RMAP_MATCH; + else { + for (match = match_list->head; match; match = match->next) { + /* + * Try each match statement. If any match does not + * return RMAP_MATCH or RMAP_NOOP, return. + * Otherwise continue on to next match statement. + * All match statements must MATCH for + * end-result to be a match. + * (Exception:If match stmts result in a mix of + * MATCH/NOOP, then also end-result is a match) + * If all result in NOOP, end-result is NOOP. + */ + ret = (*match->cmd->func_apply)(match->value, prefix, + type, object); + + /* + * If the consolidated result of func_apply is: + * ----------------------------------------------- + * | MATCH | NOMATCH | NOOP | Final Result | + * ------------------------------------------------ + * | yes | yes | yes | NOMATCH | + * | no | no | yes | NOOP | + * | yes | no | yes | MATCH | + * | no | yes | yes | NOMATCH | + * |----------------------------------------------- + * + * Traditionally, all rules within route-map + * should match for it to MATCH. + * If there are noops within the route-map rules, + * it follows the above matrix. + * + * Eg: route-map rm1 permit 10 + * match rule1 + * match rule2 + * match rule3 + * .... + * route-map rm1 permit 20 + * match ruleX + * match ruleY + * ... + */ + + switch (ret) { + case RMAP_MATCH: + is_matched = true; + break; + + case RMAP_NOMATCH: + return ret; + + case RMAP_NOOP: + if (is_matched) + ret = RMAP_MATCH; + break; + + default: + break; + } + + } + } + return ret; +} + /* Apply route map's each index to the object. The matrix for a route-map looks like this: (note, this includes the description for the "NEXT" and "GOTO" frobs now - Match | No Match - | - permit action | cont - | - ------------------+--------------- - | - deny deny | cont - | + | Match | No Match | No op + |-----------|--------------|------- + permit | action | cont | cont. + | | default:deny | default:permit + -------------------+----------------------- + | deny | cont | cont. + deny | | default:deny | default:permit + |-----------|--------------|-------- action) -Apply Set statements, accept route @@ -1604,45 +1694,13 @@ int route_map_delete_set(struct route_map_index *index, const char *set_name, We need to make sure our route-map processing matches the above */ - -static route_map_result_t -route_map_apply_match(struct route_map_rule_list *match_list, - const struct prefix *prefix, route_map_object_t type, - void *object) -{ - route_map_result_t ret = RMAP_NOMATCH; - struct route_map_rule *match; - - - /* Check all match rule and if there is no match rule, go to the - set statement. */ - if (!match_list->head) - ret = RMAP_MATCH; - else { - for (match = match_list->head; match; match = match->next) { - /* Try each match statement in turn, If any do not - return - RMAP_MATCH, return, otherwise continue on to next - match - statement. All match statements must match for - end-result - to be a match. */ - ret = (*match->cmd->func_apply)(match->value, prefix, - type, object); - if (ret != RMAP_MATCH) - return ret; - } - } - return ret; -} - -/* Apply route map to the object. */ route_map_result_t route_map_apply(struct route_map *map, const struct prefix *prefix, route_map_object_t type, void *object) { static int recursion = 0; - int ret = 0; + enum route_map_cmd_result_t match_ret = RMAP_NOMATCH; + route_map_result_t ret = RMAP_PERMITMATCH; struct route_map_index *index; struct route_map_rule *set; char buf[PREFIX_STRLEN]; @@ -1656,7 +1714,7 @@ route_map_result_t route_map_apply(struct route_map *map, return RMAP_DENYMATCH; } - if (map == NULL) { + if (map == NULL || map->head == NULL) { ret = RMAP_DENYMATCH; goto route_map_apply_end; } @@ -1665,29 +1723,64 @@ route_map_result_t route_map_apply(struct route_map *map, for (index = map->head; index; index = index->next) { /* Apply this index. */ index->applied++; - ret = route_map_apply_match(&index->match_list, prefix, type, - object); + match_ret = route_map_apply_match(&index->match_list, prefix, + type, object); if (rmap_debug) { zlog_debug("Route-map: %s, sequence: %d, prefix: %s, result: %s", map->name, index->pref, prefix2str(prefix, buf, sizeof(buf)), - route_map_result_str(ret)); + route_map_cmd_result_str(match_ret)); } /* Now we apply the matrix from above */ - if (ret == RMAP_NOMATCH) - /* 'cont' from matrix - continue to next route-map - * sequence */ + if (match_ret == RMAP_NOOP) + /* + * Do not change the return value. Retain the previous + * return value. Previous values can be: + * 1)permitmatch (if a nomatch was never + * seen before in this route-map.) + * 2)denymatch (if a nomatch was seen earlier in one + * of the previous sequences) + */ + + /* + * 'cont' from matrix - continue to next route-map + * sequence + */ continue; - else if (ret == RMAP_MATCH) { + else if (match_ret == RMAP_NOMATCH) { + + /* + * The return value is now changed to denymatch. + * So from here on out, even if we see more noops, + * we retain this return value and return this + * eventually if there are no matches. + */ + ret = RMAP_DENYMATCH; + + /* + * 'cont' from matrix - continue to next route-map + * sequence + */ + continue; + } else if (match_ret == RMAP_MATCH) { if (index->type == RMAP_PERMIT) /* 'action' */ { + /* Match succeeded, rmap is of type permit */ + ret = RMAP_PERMITMATCH; + /* permit+match must execute sets */ for (set = index->set_list.head; set; set = set->next) - ret = (*set->cmd->func_apply)( + /* + * set cmds return RMAP_OKAY or + * RMAP_ERROR. We do not care if + * set succeeded or not. So, ignore + * return code. + */ + (void) (*set->cmd->func_apply)( set->value, prefix, type, object); @@ -1741,8 +1834,6 @@ route_map_result_t route_map_apply(struct route_map *map, } } } - /* Finally route-map does not match at all. */ - ret = RMAP_DENYMATCH; route_map_apply_end: if (rmap_debug) { diff --git a/lib/routemap.h b/lib/routemap.h index 90df1048ed..f9ad0f64a9 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -38,13 +38,35 @@ DECLARE_MTYPE(ROUTE_MAP_COMPILED) enum route_map_type { RMAP_PERMIT, RMAP_DENY, RMAP_ANY }; typedef enum { - RMAP_MATCH, RMAP_DENYMATCH, - RMAP_NOMATCH, - RMAP_ERROR, - RMAP_OKAY + RMAP_PERMITMATCH } route_map_result_t; +/* + * Route-map match or set result "Eg: match evpn vni xx" + * route-map match cmd always returns match/nomatch/noop + * match--> found a match + * nomatch--> didnt find a match + * noop--> not applicable + * route-map set retuns okay/error + * okay --> set was successful + * error --> set was not successful + */ +enum route_map_cmd_result_t { + /* + * route-map match cmd results + */ + RMAP_MATCH, + RMAP_NOMATCH, + RMAP_NOOP, + /* + * route-map set cmd results + */ + RMAP_OKAY, + RMAP_ERROR +}; + + typedef enum { RMAP_RIP, RMAP_RIPNG, @@ -91,10 +113,10 @@ struct route_map_rule_cmd { const char *str; /* Function for value set or match. */ - route_map_result_t (*func_apply)(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object); + enum route_map_cmd_result_t (*func_apply)(void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object); /* Compile argument and return result as void *. */ void *(*func_compile)(const char *); diff --git a/lib/typesafe.h b/lib/typesafe.h index 0a4ed69e4e..ee244c78ae 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -434,7 +434,7 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \ struct ssort_item *sitem = h->sh.first; \ int cmpval = 0; \ while (sitem && (cmpval = cmpfn_nuq( \ - container_of(sitem, type, field.si), item) < 0)) \ + container_of(sitem, type, field.si), item)) < 0) \ sitem = sitem->next; \ return container_of_null(sitem, type, field.si); \ } \ @@ -444,7 +444,7 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \ struct ssort_item *prev = NULL, *sitem = h->sh.first; \ int cmpval = 0; \ while (sitem && (cmpval = cmpfn_nuq( \ - container_of(sitem, type, field.si), item) < 0)) \ + container_of(sitem, type, field.si), item)) < 0) \ sitem = (prev = sitem)->next; \ return container_of_null(prev, type, field.si); \ } \ @@ -499,7 +499,7 @@ macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item) \ struct ssort_item *sitem = h->sh.first; \ int cmpval = 0; \ while (sitem && (cmpval = cmpfn( \ - container_of(sitem, type, field.si), item) < 0)) \ + container_of(sitem, type, field.si), item)) < 0) \ sitem = sitem->next; \ if (!sitem || cmpval > 0) \ return NULL; \ diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 946bbf8cc9..33b9f71b5f 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1018,7 +1018,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, unsigned int nexthop_num, struct in6_addr *nexthop, route_tag_t tag) { - int ret; + route_map_result_t ret; struct ospf6_route troute; struct ospf6_external_info tinfo; struct ospf6_route *route, *match; @@ -1355,7 +1355,7 @@ static void ospf6_redistribute_show_config(struct vty *vty) /* Routemap Functions */ -static route_map_result_t +static enum route_map_cmd_result_t ospf6_routemap_rule_match_address_prefixlist(void *rule, const struct prefix *prefix, route_map_object_t type, @@ -1395,7 +1395,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = { /* `match interface IFNAME' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t +static enum route_map_cmd_result_t ospf6_routemap_rule_match_interface(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1433,10 +1433,9 @@ struct route_map_rule_cmd ospf6_routemap_rule_match_interface_cmd = { ospf6_routemap_rule_match_interface_free}; /* Match function for matching route tags */ -static route_map_result_t ospf6_routemap_rule_match_tag(void *rule, - const struct prefix *p, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +ospf6_routemap_rule_match_tag(void *rule, const struct prefix *p, + route_map_object_t type, void *object) { route_tag_t *tag = rule; struct ospf6_route *route = object; @@ -1453,7 +1452,7 @@ static struct route_map_rule_cmd ospf6_routemap_rule_match_tag_cmd = { route_map_rule_tag_free, }; -static route_map_result_t +static enum route_map_cmd_result_t ospf6_routemap_rule_set_metric_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1489,7 +1488,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = { ospf6_routemap_rule_set_metric_type_free, }; -static route_map_result_t +static enum route_map_cmd_result_t ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1524,7 +1523,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = { ospf6_routemap_rule_set_metric_free, }; -static route_map_result_t +static enum route_map_cmd_result_t ospf6_routemap_rule_set_forwarding(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1562,10 +1561,9 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = { ospf6_routemap_rule_set_forwarding_free, }; -static route_map_result_t ospf6_routemap_rule_set_tag(void *rule, - const struct prefix *p, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +ospf6_routemap_rule_set_tag(void *rule, const struct prefix *p, + route_map_object_t type, void *object) { route_tag_t *tag = rule; struct ospf6_route *route = object; diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index bb7e97bf7b..1669c817e6 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -126,10 +126,9 @@ static void ospf_route_map_event(const char *name) /* `match ip netxthop ' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_nexthop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_nexthop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; struct external_info *ei = object; @@ -171,7 +170,7 @@ struct route_map_rule_cmd route_match_ip_nexthop_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -212,7 +211,7 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* `match ip next-hop type <blackhole>' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -221,7 +220,7 @@ route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, if (type == RMAP_OSPF && prefix->family == AF_INET) { ei = (struct external_info *)object; if (!ei) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; if (ei->nexthop.s_addr == INADDR_ANY && !ei->ifindex) return RMAP_MATCH; @@ -247,10 +246,9 @@ static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = { /* `match ip address IP_ACCESS_LIST' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; /* struct prefix_ipv4 match; */ @@ -286,7 +284,7 @@ struct route_map_rule_cmd route_match_ip_address_cmd = { route_match_ip_address_free}; /* `match ip address prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -322,10 +320,9 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* `match interface IFNAME' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_interface(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_interface(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct interface *ifp; struct external_info *ei; @@ -361,9 +358,9 @@ struct route_map_rule_cmd route_match_interface_cmd = { route_match_interface_free}; /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, - const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_match_tag(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { route_tag_t *tag; struct external_info *ei; @@ -392,10 +389,9 @@ struct ospf_metric { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_metric(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct ospf_metric *metric; struct external_info *ei; @@ -473,10 +469,9 @@ struct route_map_rule_cmd route_set_metric_cmd = { /* `set metric-type TYPE' */ /* Set metric-type to attribute. */ -static route_map_result_t route_set_metric_type(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_metric_type(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { uint32_t *metric_type; struct external_info *ei; @@ -523,8 +518,9 @@ struct route_map_rule_cmd route_set_metric_type_cmd = { route_set_metric_type_free, }; -static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, + void *object) { route_tag_t *tag; struct external_info *ei; diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index c178e367d3..951402f47f 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -943,7 +943,7 @@ int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei, /* apply route-map if needed */ red = ospf_redist_lookup(ospf, type, instance); if (red && ROUTEMAP_NAME(red)) { - int ret; + route_map_result_t ret; ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, RMAP_OSPF, ei); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index b1c55c1f43..1c66007fbb 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -190,8 +190,6 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp, sg.grp = msg->im_dst; if (!(PIM_I_am_DR(pim_ifp))) { - struct channel_oil *c_oil; - if (PIM_DEBUG_MROUTE_DETAIL) zlog_debug("%s: Interface is not the DR blackholing incoming traffic for %s", __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); @@ -206,10 +204,10 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp, * that I see no way to get rid of. Just noting * this for future reference. */ - c_oil = pim_channel_oil_add(pim_ifp->pim, &sg, - pim_ifp->mroute_vif_index, - __PRETTY_FUNCTION__); - pim_mroute_add(c_oil, __PRETTY_FUNCTION__); + up = pim_upstream_find_or_add( + &sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE, + __PRETTY_FUNCTION__); + pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__); return 0; } @@ -238,7 +236,8 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp, vif_index = pim_if_find_vifindex_by_ifindex( pim_ifp->pim, up->rpf.source_nexthop.interface->ifindex); - up->channel_oil->oil.mfcc_parent = vif_index; + pim_channel_oil_change_iif(pim_ifp->pim, up->channel_oil, + vif_index, __PRETTY_FUNCTION__); } pim_register_join(up); @@ -453,7 +452,6 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, struct pim_upstream *up; struct prefix_sg star_g; struct prefix_sg sg; - struct channel_oil *oil; pim_ifp = ifp->info; @@ -517,11 +515,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, up->upstream_register); up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; } - if (!up->channel_oil) - up->channel_oil = pim_channel_oil_add( - pim_ifp->pim, &sg, - pim_ifp->mroute_vif_index, - __PRETTY_FUNCTION__); + pim_upstream_inherited_olist(pim_ifp->pim, up); if (!up->channel_oil->installed) pim_mroute_add(up->channel_oil, @@ -546,10 +540,6 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, } pim_ifp = ifp->info; - oil = pim_channel_oil_add(pim_ifp->pim, &sg, pim_ifp->mroute_vif_index, - __PRETTY_FUNCTION__); - if (!oil->installed) - pim_mroute_add(oil, __PRETTY_FUNCTION__); if (pim_if_connected_to_source(ifp, sg.src)) { up = pim_upstream_add(pim_ifp->pim, &sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, @@ -564,13 +554,18 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); pim_upstream_keep_alive_timer_start( up, pim_ifp->pim->keep_alive_time); - up->channel_oil = oil; up->channel_oil->cc.pktcnt++; pim_register_join(up); pim_upstream_inherited_olist(pim_ifp->pim, up); // Send the packet to the RP pim_mroute_msg_wholepkt(fd, ifp, buf); + } else { + up = pim_upstream_add(pim_ifp->pim, &sg, ifp, + PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE, + __PRETTY_FUNCTION__, NULL); + if (!up->channel_oil->installed) + pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__); } return 0; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index d4fc03e20c..d142934916 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -146,6 +146,43 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim, return c_oil; } +void pim_channel_oil_change_iif(struct pim_instance *pim, + struct channel_oil *c_oil, + int input_vif_index, + const char *name) +{ + int old_vif_index = c_oil->oil.mfcc_parent; + struct prefix_sg sg = {.src = c_oil->oil.mfcc_mcastgrp, + .grp = c_oil->oil.mfcc_origin}; + + if (c_oil->oil.mfcc_parent == input_vif_index) { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug("%s(%s): Existing channel oil %pSG4 already using %d as IIF", + __PRETTY_FUNCTION__, name, &sg, + input_vif_index); + + return; + } + + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug("%s(%s): Changing channel oil %pSG4 IIF from %d to %d installed: %d", + __PRETTY_FUNCTION__, name, &sg, + c_oil->oil.mfcc_parent, input_vif_index, + c_oil->installed); + + c_oil->oil.mfcc_parent = input_vif_index; + if (c_oil->installed) { + if (input_vif_index == MAXVIFS) + pim_mroute_del(c_oil, name); + else + pim_mroute_add(c_oil, name); + } else + if (old_vif_index == MAXVIFS) + pim_mroute_add(c_oil, name); + + return; +} + struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, struct prefix_sg *sg, int input_vif_index, const char *name) @@ -164,7 +201,8 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, c_oil->oil.mfcc_parent, input_vif_index); } - c_oil->oil.mfcc_parent = input_vif_index; + pim_channel_oil_change_iif(pim, c_oil, input_vif_index, + name); ++c_oil->oil_ref_count; /* channel might be present prior to upstream */ c_oil->up = pim_upstream_find(pim, sg); diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 485299196d..319a1c91a3 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -114,6 +114,9 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim, struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, struct prefix_sg *sg, int input_vif_index, const char *name); +void pim_channel_oil_change_iif(struct pim_instance *pim, + struct channel_oil *c_oil, int input_vif_index, + const char *name); void pim_channel_oil_del(struct channel_oil *c_oil, const char *name); int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif, diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 7d263e99e3..357ad6ba46 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -307,11 +307,11 @@ void pim_upstream_rpf_clear(struct pim_instance *pim, struct pim_upstream *up) { if (up->rpf.source_nexthop.interface) { - if (up->channel_oil) { - up->channel_oil->oil.mfcc_parent = MAXVIFS; - pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__); + if (up->channel_oil) + pim_channel_oil_change_iif(pim, up->channel_oil, + MAXVIFS, + __PRETTY_FUNCTION__); - } pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED); up->rpf.source_nexthop.interface = NULL; up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 62c3216e86..e3138360c8 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -138,7 +138,9 @@ int pim_static_add(struct pim_instance *pim, struct interface *iif, } else { /* input interface changed */ s_route->iif = iif_index; - s_route->c_oil.oil.mfcc_parent = iif_index; + pim_channel_oil_change_iif(pim, &s_route->c_oil, + iif_index, + __PRETTY_FUNCTION__); #ifdef PIM_ENFORCE_LOOPFREE_MFC /* check to make sure the new input was not an diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 50df2fdbf9..c0651561ac 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -716,7 +716,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, up->join_state = PIM_UPSTREAM_NOTJOINED; up->reg_state = PIM_REG_NOINFO; up->state_transition = pim_time_monotonic_sec(); - up->channel_oil = NULL; + up->channel_oil = + pim_channel_oil_add(pim, &up->sg, MAXVIFS, __PRETTY_FUNCTION__); up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; up->rpf.source_nexthop.interface = NULL; @@ -736,52 +737,34 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, if (up->sg.src.s_addr != INADDR_ANY) wheel_add_item(pim->upstream_sg_wheel, up); - if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)) { + if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags) + || PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)) { pim_upstream_fill_static_iif(up, incoming); pim_ifp = up->rpf.source_nexthop.interface->info; assert(pim_ifp); - up->channel_oil = pim_channel_oil_add(pim, &up->sg, - pim_ifp->mroute_vif_index, - __PRETTY_FUNCTION__); - } else if (up->upstream_addr.s_addr == INADDR_ANY) { - /* Create a dummmy channel oil with incoming ineterface MAXVIFS, - * since RP is not configured - */ - up->channel_oil = pim_channel_oil_add(pim, &up->sg, MAXVIFS, - __PRETTY_FUNCTION__); - - } else { + pim_channel_oil_change_iif(pim, up->channel_oil, + pim_ifp->mroute_vif_index, + __PRETTY_FUNCTION__); + + if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)) + pim_upstream_keep_alive_timer_start( + up, pim->keep_alive_time); + } else if (up->upstream_addr.s_addr != INADDR_ANY) { rpf_result = pim_rpf_update(pim, up, NULL); if (rpf_result == PIM_RPF_FAILURE) { if (PIM_DEBUG_TRACE) zlog_debug( "%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, up->sg_str); - /* Create a dummmy channel oil with incoming ineterface - * MAXVIFS, since RP is not reachable - */ - up->channel_oil = pim_channel_oil_add( - pim, &up->sg, MAXVIFS, __PRETTY_FUNCTION__); } if (up->rpf.source_nexthop.interface) { pim_ifp = up->rpf.source_nexthop.interface->info; if (pim_ifp) - up->channel_oil = pim_channel_oil_add( - pim, &up->sg, pim_ifp->mroute_vif_index, - __PRETTY_FUNCTION__); - else { - /* - * Yeah this should not happen - * but let's be sure that we are not - * doing something stupid, all paths - * through upstream creation will - * create a channel oil - */ - up->channel_oil = pim_channel_oil_add( - pim, &up->sg, MAXVIFS, + pim_channel_oil_change_iif( + pim, up->channel_oil, + pim_ifp->mroute_vif_index, __PRETTY_FUNCTION__); - } } } @@ -1201,6 +1184,13 @@ struct pim_upstream *pim_upstream_keep_alive_timer_proc( if (!pim_upstream_del(pim, up, __PRETTY_FUNCTION__)) return NULL; } + if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)) { + PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(up->flags); + + if (!pim_upstream_del(pim, up, __PRETTY_FUNCTION__)) + return NULL; + } + /* upstream reference would have been added to track the local * membership if it is LHR. We have to clear it when KAT expires. * Otherwise would result in stale entry with uncleared ref count. @@ -1526,22 +1516,14 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim, struct pim_upstream *up) { struct interface *ifp; - struct pim_interface *pim_ifp = NULL; struct pim_ifchannel *ch, *starch; struct pim_upstream *starup = up->parent; int output_intf = 0; - if (up->rpf.source_nexthop.interface) - pim_ifp = up->rpf.source_nexthop.interface->info; - else { + if (!up->rpf.source_nexthop.interface) if (PIM_DEBUG_TRACE) zlog_debug("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str); - } - if (pim_ifp && !up->channel_oil) - up->channel_oil = pim_channel_oil_add(pim, &up->sg, - pim_ifp->mroute_vif_index, - __PRETTY_FUNCTION__); FOR_ALL_INTERFACES (pim->vrf, ifp) { if (!ifp->info) diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 02ae998290..c6c9291eed 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -74,6 +74,13 @@ * blackholing the traffic pulled down to the LHR. */ #define PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF (1 << 17) +/* + * We are creating a non-joined upstream data structure + * for this S,G as that we want to have a channel oil + * associated with an upstream + */ +#define PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE (1 << 19) + #define PIM_UPSTREAM_FLAG_ALL 0xFFFFFFFF #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) @@ -95,6 +102,7 @@ #define PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN(flags) ((flags) & (PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG | PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)) #define PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN) #define PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF) +#define PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(flags) ((flags) &PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE) #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) @@ -133,6 +141,7 @@ #define PIM_UPSTREAM_FLAG_UNSET_SRC_VXLAN_TERM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM) #define PIM_UPSTREAM_FLAG_UNSET_MLAG_VXLAN(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN) #define PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF) +#define PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE) enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED, diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 675e81f5a1..b0db23f54a 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -601,7 +601,6 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index) { struct in_addr vif_source; int input_iface_vif_index; - int old_vif_index; pim_rp_set_upstream_addr(c_oil->pim, &vif_source, c_oil->oil.mfcc_origin, @@ -701,33 +700,9 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index) } /* update iif vif_index */ - old_vif_index = c_oil->oil.mfcc_parent; - c_oil->oil.mfcc_parent = input_iface_vif_index; - - /* update kernel multicast forwarding cache (MFC) */ - if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { - if (PIM_DEBUG_MROUTE) { - /* just log warning */ - struct interface *old_iif = pim_if_find_by_vif_index( - c_oil->pim, old_vif_index); - struct interface *new_iif = pim_if_find_by_vif_index( - c_oil->pim, input_iface_vif_index); - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, - source_str, sizeof(source_str)); - pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, - group_str, sizeof(group_str)); - zlog_debug( - "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, source_str, - group_str, - old_iif ? old_iif->name : "<old_iif?>", - c_oil->oil.mfcc_parent, - new_iif ? new_iif->name : "<new_iif?>", - input_iface_vif_index); - } - } + pim_channel_oil_change_iif(c_oil->pim, c_oil, input_iface_vif_index, + __PRETTY_FUNCTION__); + pim_mroute_add(c_oil, __PRETTY_FUNCTION__); } void pim_scan_oil(struct pim_instance *pim) @@ -1256,14 +1231,15 @@ void pim_forward_start(struct pim_ifchannel *ch) __FILE__, __PRETTY_FUNCTION__, source_str); } - up->channel_oil = pim_channel_oil_add( - pim, &up->sg, MAXVIFS, __PRETTY_FUNCTION__); + pim_channel_oil_change_iif(pim, up->channel_oil, + MAXVIFS, + __PRETTY_FUNCTION__); } else - up->channel_oil = pim_channel_oil_add( - pim, &up->sg, input_iface_vif_index, - __PRETTY_FUNCTION__); + pim_channel_oil_change_iif(pim, up->channel_oil, + input_iface_vif_index, + __PRETTY_FUNCTION__); if (PIM_DEBUG_TRACE) { struct interface *in_intf = pim_if_find_by_vif_index( @@ -1274,10 +1250,6 @@ void pim_forward_start(struct pim_ifchannel *ch) in_intf ? in_intf->name : "Unknown", input_iface_vif_index, up->sg_str); } - - up->channel_oil = - pim_channel_oil_add(pim, &up->sg, input_iface_vif_index, - __PRETTY_FUNCTION__); } if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 85d83c61dc..459188fefd 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -42,10 +42,9 @@ struct rip_metric_modifier { /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_metric(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_metric(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { uint32_t *metric; uint32_t check; @@ -95,10 +94,9 @@ struct route_map_rule_cmd route_match_metric_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_interface(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_interface(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct rip_info *rinfo; struct interface *ifp; @@ -143,10 +141,9 @@ struct route_map_rule_cmd route_match_interface_cmd = { /* `match ip next-hop IP_ACCESS_LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_next_hop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_next_hop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; struct rip_info *rinfo; @@ -190,7 +187,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -233,7 +230,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* `match ip next-hop type <blackhole>' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -242,7 +239,7 @@ route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, if (type == RMAP_RIP && prefix->family == AF_INET) { rinfo = (struct rip_info *)object; if (!rinfo) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; if (rinfo->nh.type == NEXTHOP_TYPE_BLACKHOLE) return RMAP_MATCH; @@ -269,10 +266,9 @@ static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = { /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; @@ -308,7 +304,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -343,8 +339,9 @@ static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_match_tag(void *rule, const struct prefix *p, route_map_object_t type, + void *object) { route_tag_t *tag; struct rip_info *rinfo; @@ -373,10 +370,9 @@ static struct route_map_rule_cmd route_match_tag_cmd = { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_metric(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { if (type == RMAP_RIP) { struct rip_metric_modifier *mod; @@ -472,10 +468,10 @@ static struct route_map_rule_cmd route_set_metric_cmd = { /* `set ip next-hop IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_ip_nexthop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t route_set_ip_nexthop(void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object) { struct in_addr *address; struct rip_info *rinfo; @@ -525,8 +521,9 @@ static struct route_map_rule_cmd route_set_ip_nexthop_cmd = { /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, + void *object) { route_tag_t *tag; struct rip_info *rinfo; diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index 0604e272cd..d27ec76a56 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -38,10 +38,9 @@ struct rip_metric_modifier { /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_metric(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_metric(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { uint32_t *metric; struct ripng_info *rinfo; @@ -86,10 +85,9 @@ static struct route_map_rule_cmd route_match_metric_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_interface(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_interface(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct ripng_info *rinfo; struct interface *ifp; @@ -129,9 +127,10 @@ static struct route_map_rule_cmd route_match_interface_cmd = { /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_tag(void *rule, - const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t route_match_tag(void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object) { route_tag_t *tag; struct ripng_info *rinfo; @@ -159,10 +158,9 @@ static struct route_map_rule_cmd route_match_tag_cmd = { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_metric(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { if (type == RMAP_RIPNG) { struct rip_metric_modifier *mod; @@ -256,10 +254,9 @@ static struct route_map_rule_cmd route_set_metric_cmd = { /* `set ipv6 next-hop local IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_ipv6_nexthop_local(void *rule, - const struct prefix *p, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, + route_map_object_t type, void *object) { struct in6_addr *address; struct ripng_info *rinfo; @@ -310,9 +307,9 @@ static struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = { /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t route_set_tag(void *rule, - const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, + void *object) { route_tag_t *tag; struct ripng_info *rinfo; diff --git a/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py b/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py index abd6b396d1..2b9c411ff2 100755 --- a/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py +++ b/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py @@ -218,11 +218,8 @@ def test_next_hop_attribute(request): # Verifying RIB routes dut = "r1" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) - try: - assert result is True - except AssertionError: - logger.info("Expected behaviour: %s", result) + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) + assert result is not True # Configure next-hop-self to bgp neighbor input_dict_1 = { diff --git a/tests/topotests/bgp-prefix-list-topo1/test_prefix_lists.py b/tests/topotests/bgp-prefix-list-topo1/test_prefix_lists.py index 25a346f20d..d3892e9d07 100755 --- a/tests/topotests/bgp-prefix-list-topo1/test_prefix_lists.py +++ b/tests/topotests/bgp-prefix-list-topo1/test_prefix_lists.py @@ -385,7 +385,7 @@ def test_ip_prefix_lists_out_permit(request): assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) write_test_footer(tc_name) @@ -496,7 +496,7 @@ def test_ip_prefix_lists_in_deny_and_permit_any(request): # Verifying RIB routes dut = "r3" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -713,7 +713,7 @@ def test_ip_prefix_lists_out_deny_and_permit_any(request): # Verifying RIB routes dut = "r4" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -858,7 +858,7 @@ def test_modify_prefix_lists_in_permit_to_deny(request): # Verifying RIB routes dut = "r3" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -971,7 +971,7 @@ def test_modify_prefix_lists_in_deny_to_permit(request): # Verifying RIB routes dut = "r3" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -1151,7 +1151,7 @@ def test_modify_prefix_lists_out_permit_to_deny(request): # Verifying RIB routes dut = "r4" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -1264,7 +1264,7 @@ def test_modify_prefix_lists_out_deny_to_permit(request): # Verifying RIB routes dut = "r4" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -1438,7 +1438,7 @@ def test_ip_prefix_lists_implicit_deny(request): # Verifying RIB routes dut = "r4" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict_1, protocol=protocol) + result = verify_rib(tgen, "ipv4", dut, input_dict_1, protocol=protocol, expected=False) assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py index db53c1aacd..0279e482ff 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py @@ -14,12 +14,12 @@ if ret != False and found != None: luCommand('ce1', 'vtysh -c "sharp remove routes 10.0.0.0 {}"'.format(num),'.','none','Removing {} routes'.format(num)) luCommand('ce2', 'vtysh -c "sharp remove routes 10.0.0.0 {}"'.format(num),'.','none','Removing {} routes'.format(num)) for rtr in rtrs: - luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep Display',' 10 route', 'wait', 'BGP routes removed', wait) + luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep Display',' 10 route', 'wait', 'BGP routes removed', wait, wait_time=10) luCommand(rtr, 'vtysh -c "show bgp ipv4 uni"','.', 'none', 'BGP routes post remove') for rtr in rtrs: - luCommand(rtr, 'ip route show | grep -c \\^10\\.','^0$', 'wait', 'Linux routes removed', wait) + luCommand(rtr, 'ip route show | grep -c \\^10\\.','^0$', 'wait', 'Linux routes removed', wait, wait_time=10) luCommand(rtr, 'ip route show','.', 'none', 'Linux routes post remove') rtrs = ['r1', 'r3', 'r4'] for rtr in rtrs: - luCommand(rtr, 'ip route show vrf {}-cust1 | grep -c \\^10\\.'.format(rtr),'^0$','wait','VRF route removed',wait) + luCommand(rtr, 'ip route show vrf {}-cust1 | grep -c \\^10\\.'.format(rtr),'^0$','wait','VRF route removed',wait, wait_time=10) #done diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py index 3619cdf84f..21543ab78e 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py @@ -36,10 +36,10 @@ if doSharp == True: luCommand('ce2', 'vtysh -c "sharp install routes 10.0.0.0 nexthop 99.0.0.2 {}"'.format(num),'','pass','Adding {} routes'.format(num)) rtrs = ['ce1', 'ce2', 'ce3'] for rtr in rtrs: - luCommand(rtr, 'vtysh -c "show bgp ipv4 uni 10.{}.{}.{}"'.format(b,c,d), 'Last update:', 'wait', 'RXed last route, 10.{}.{}.{}'.format(b,c,d), wait) - luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep -c 10\\.\\*/32', str(num), 'wait', 'See all sharp routes in BGP', wait) - luCommand('r1', 'vtysh -c "show bgp vrf r1-cust1 ipv4 uni 10.{}.{}.{}"'.format(b,c,d),'99.0.0.1','wait','RXed -> 10.{}.{}.{} from CE1'.format(b,c,d), wait) - luCommand('r3', 'vtysh -c "show bgp vrf r3-cust1 ipv4 uni 10.{}.{}.{}"'.format(b,c,d),'99.0.0.2','wait','RXed -> 10.{}.{}.{} from CE2'.format(b,c,d), wait) + luCommand(rtr, 'vtysh -c "show bgp ipv4 uni 10.{}.{}.{}"'.format(b,c,d), 'Last update:', 'wait', 'RXed last route, 10.{}.{}.{}'.format(b,c,d), wait, wait_time=10) + luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep -c 10\\.\\*/32', str(num), 'wait', 'See all sharp routes in BGP', wait, wait_time=10) + luCommand('r1', 'vtysh -c "show bgp vrf r1-cust1 ipv4 uni 10.{}.{}.{}"'.format(b,c,d),'99.0.0.1','wait','RXed -> 10.{}.{}.{} from CE1'.format(b,c,d), wait, wait_time=10) + luCommand('r3', 'vtysh -c "show bgp vrf r3-cust1 ipv4 uni 10.{}.{}.{}"'.format(b,c,d),'99.0.0.2','wait','RXed -> 10.{}.{}.{} from CE2'.format(b,c,d), wait, wait_time=10) luCommand('r1', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'99.0.0.1','wait','see VPN safi -> 10.{}.{}.{} from CE1'.format(b,c,d)) luCommand('r3', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'99.0.0.2','wait','see VPN safi -> 10.{}.{}.{} from CE2'.format(b,c,d)) luCommand('r3', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'1.1.1.1','wait','see VPN safi -> 10.{}.{}.{} from CE1'.format(b,c,d)) @@ -48,13 +48,13 @@ if doSharp == True: luCommand('r4', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'3.3.3.3','wait','see VPN safi -> 10.{}.{}.{} from CE2'.format(b,c,d)) rtrs = ['ce1', 'ce2', 'ce3'] for rtr in rtrs: - luCommand(rtr, 'ip route get 10.{}.{}.{}'.format(b,c,d),'dev','wait','Route to 10.{}.{}.{} available'.format(b,c,d), wait) - luCommand(rtr, 'ip route show | grep -c \\^10\\.', str(num), 'wait', 'See {} linux routes'.format(num), wait) + luCommand(rtr, 'ip route get 10.{}.{}.{}'.format(b,c,d),'dev','wait','Route to 10.{}.{}.{} available'.format(b,c,d), wait, wait_time=10) + luCommand(rtr, 'ip route show | grep -c \\^10\\.', str(num), 'wait', 'See {} linux routes'.format(num), wait, wait_time=10) rtrs = ['r1', 'r3', 'r4'] for rtr in rtrs: - luCommand(rtr, 'ip route get vrf {}-cust1 10.{}.{}.{}'.format(rtr,b,c,d),'dev','wait','VRF route available',wait) - luCommand(rtr, 'ip route show vrf {}-cust1 | grep -c \\^10\\.'.format(rtr), str(num), 'wait','See {} linux routes'.format(num), wait) + luCommand(rtr, 'ip route get vrf {}-cust1 10.{}.{}.{}'.format(rtr,b,c,d),'dev','wait','VRF route available',wait, wait_time=10) + luCommand(rtr, 'ip route show vrf {}-cust1 | grep -c \\^10\\.'.format(rtr), str(num), 'wait','See {} linux routes'.format(num), wait, wait_time=10) rtrs = ['ce1', 'ce2', 'ce3', 'r1', 'r2', 'r3', 'r4'] for rtr in rtrs: ret = luCommand(rtr, 'vtysh -c "show memory"', 'zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)', 'none', 'collect bgpd memory stats') diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 628c198e1a..75880cfd28 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -30,6 +30,9 @@ import traceback import socket import ipaddr +from lib import topotest + +from functools import partial from lib.topolog import logger, logger_config from lib.topogen import TopoRouter @@ -1089,7 +1092,7 @@ def create_route_maps(tgen, input_dict, build=False): ############################################# # Verification APIs ############################################# -def verify_rib(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None): +def _verify_rib(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None): """ Data will be read from input_dict or input JSON file, API will generate same prefixes, which were redistributed by either create_static_routes() or @@ -1258,6 +1261,26 @@ def verify_rib(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None): return True +def verify_rib(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None, expected=True): + """ + Wrapper function for `_verify_rib` that tries multiple time to get results. + + When the expected result is `False` we actually should expect for an string instead. + """ + + # Use currying to hide the parameters and create a test function. + test_func = partial(_verify_rib, tgen, addr_type, dut, input_dict, next_hop, protocol) + + # Call the test function and expect it to return True, otherwise try it again. + if expected is True: + _, result = topotest.run_and_expect(test_func, True, count=20, wait=6) + else: + _, result = topotest.run_and_expect_type(test_func, str, count=20, wait=6) + + # Return as normal. + return result + + def verify_admin_distance_for_static_routes(tgen, input_dict): """ API to verify admin distance for static routes as defined in input_dict/ diff --git a/tests/topotests/lib/lutil.py b/tests/topotests/lib/lutil.py index d3a275d118..7c89ada013 100755 --- a/tests/topotests/lib/lutil.py +++ b/tests/topotests/lib/lutil.py @@ -22,6 +22,7 @@ import sys import time import datetime import json +import math from topolog import logger from mininet.net import Mininet @@ -242,20 +243,27 @@ Total %-4d %-4d %d\n\ return js return ret - def wait(self, target, command, regexp, op, result, wait, returnJson): - self.log('%s:%s WAIT:%s:%s:%s:%s:%s:%s:' % \ - (self.l_filename, self.l_line, target, command, regexp, op, result,wait)) + def wait(self, target, command, regexp, op, result, wait, returnJson, wait_time=0.5): + self.log('%s:%s WAIT:%s:%s:%s:%s:%s:%s:%s:' % \ + (self.l_filename, self.l_line, target, command, regexp, op, result,wait,wait_time)) found = False n = 0 startt = time.time() - delta = time.time() - startt - while delta < wait and found is False: + + # Calculate the amount of `sleep`s we are going to peform. + wait_count = int(math.ceil(wait / wait_time)) + 1 + + while wait_count > 0: + n += 1 found = self.command(target, command, regexp, op, result, returnJson) - n+=1 - delta = time.time() - startt - self.log('\tFound: %s n: %s delta: %s and wait: %s' % (found, n, delta, wait)) - if delta < wait and found is False: - time.sleep (0.5) + if found is not False: + break + + wait_count -= 1 + if wait_count > 0: + time.sleep(wait_time) + + delta = time.time() - startt self.log('Done after %d loops, time=%s, Found=%s' % (n, delta, found)) found = self.command(target, command, regexp, 'pass', '%s +%4.2f secs' % (result, delta), returnJson) return found @@ -281,11 +289,11 @@ def luStart(baseScriptDir='.', baseLogDir='.', net='', LUtil.l_dotall_experiment = False LUtil.l_dotall_experiment = True -def luCommand(target, command, regexp='.', op='none', result='', time=10, returnJson=False): +def luCommand(target, command, regexp='.', op='none', result='', time=10, returnJson=False, wait_time=0.5): if op != 'wait': return LUtil.command(target, command, regexp, op, result, returnJson) else: - return LUtil.wait(target, command, regexp, op, result, time, returnJson) + return LUtil.wait(target, command, regexp, op, result, time, returnJson, wait_time) def luLast(usenl=False): if usenl: diff --git a/tests/topotests/lib/test/test_run_and_expect.py b/tests/topotests/lib/test/test_run_and_expect.py new file mode 100755 index 0000000000..3c22c20e7b --- /dev/null +++ b/tests/topotests/lib/test/test_run_and_expect.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +# +# test_run_and_expect.py +# Tests for library function: run_and_expect(_type)(). +# +# Copyright (c) 2019 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +Tests for the `run_and_expect(_type)()` functions. +""" + +import os +import sys +import pytest + +# Save the Current Working Directory to find lib files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, '../../')) + +# pylint: disable=C0413 +from lib.topotest import run_and_expect_type + +def test_run_and_expect_type(): + "Test basic `run_and_expect_type` functionality." + + def return_true(): + "Test function that returns `True`." + return True + + # Test value success. + success, value = run_and_expect_type(return_true, bool, count=1, wait=0, avalue=True) + assert success is True + assert value is True + + # Test value failure. + success, value = run_and_expect_type(return_true, bool, count=1, wait=0, avalue=False) + assert success is False + assert value is True + + # Test type success. + success, value = run_and_expect_type(return_true, bool, count=1, wait=0) + assert success is True + assert value is True + + # Test type failure. + success, value = run_and_expect_type(return_true, str, count=1, wait=0) + assert success is False + assert value is True + + # Test type failure, return correct type. + success, value = run_and_expect_type(return_true, str, count=1, wait=0, avalue=True) + assert success is False + assert value is True + + +if __name__ == '__main__': + sys.exit(pytest.main()) diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 867f9f2f03..9e1d344687 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -252,6 +252,54 @@ def run_and_expect(func, what, count=20, wait=3): return (False, result) +def run_and_expect_type(func, etype, count=20, wait=3, avalue=None): + """ + Run `func` and compare the result with `etype`. Do it for `count` times + waiting `wait` seconds between tries. By default it tries 20 times with + 3 seconds delay between tries. + + This function is used when you want to test the return type and, + optionally, the return value. + + Returns (True, func-return) on success or + (False, func-return) on failure. + """ + start_time = time.time() + func_name = "<unknown>" + if func.__class__ == functools.partial: + func_name = func.func.__name__ + else: + func_name = func.__name__ + + logger.info( + "'{}' polling started (interval {} secs, maximum wait {} secs)".format( + func_name, wait, int(wait * count))) + + while count > 0: + result = func() + if not isinstance(result, etype): + logger.debug("Expected result type '{}' got '{}' instead".format(etype, type(result))) + time.sleep(wait) + count -= 1 + continue + + if etype != type(None) and avalue != None and result != avalue: + logger.debug("Expected value '{}' got '{}' instead".format(avalue, result)) + time.sleep(wait) + count -= 1 + continue + + end_time = time.time() + logger.info("'{}' succeeded after {:.2f} seconds".format( + func_name, end_time - start_time)) + return (True, result) + + end_time = time.time() + logger.error("'{}' failed after {:.2f} seconds".format( + func_name, end_time - start_time)) + return (False, result) + + def int2dpid(dpid): "Converting Integer to DPID" diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 23e8f3000d..e182c77c78 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -393,8 +393,10 @@ end # is not the main router bgp block, but enabling multi-instance oneline_ctx_keywords = ("access-list ", "agentx", + "allow-external-route-update", "bgp ", "debug ", + "domainname ", "dump ", "enable ", "frr ", diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c index c15c250bdf..dbfcbe945e 100644 --- a/vrrpd/vrrp_zebra.c +++ b/vrrpd/vrrp_zebra.c @@ -113,6 +113,8 @@ static int vrrp_zebra_if_del(int command, struct zclient *zclient, vrrp_if_del(ifp); + if_set_index(ifp, IFINDEX_INTERNAL); + return 0; } @@ -208,8 +210,6 @@ static int vrrp_zebra_if_address_del(int command, struct zclient *client, vrrp_if_address_del(c->ifp); - if_set_index(c->ifp, IFINDEX_INTERNAL); - return 0; } diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 053848bfc3..7a07dab121 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1927,7 +1927,7 @@ DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit", return rpki_exit(self, vty, argc, argv); } -DEFUNSH(VTYSH_PIMD|VTYSH_ZEBRA, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf", +DEFUNSH(VTYSH_VRF, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf", "Exit from VRF configuration mode\n") { if (vty->node == VRF_NODE) @@ -2211,7 +2211,7 @@ DEFUNSH(VTYSH_PBRD | VTYSH_SHARPD, vtysh_exit_nexthop_group, vtysh_exit_nexthop_ return vtysh_exit(vty); } -DEFUNSH(VTYSH_VRF, vtysh_quit_nexthop_group, vtysh_quit_nexthop_group_cmd, +DEFUNSH(VTYSH_PBRD | VTYSH_SHARPD, vtysh_quit_nexthop_group, vtysh_quit_nexthop_group_cmd, "quit", "Exit current mode and down to previous mode\n") { return vtysh_exit_nexthop_group(self, vty, argc, argv); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index d56579ff4f..0280cde238 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -574,7 +574,7 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *newre; struct route_entry *same; struct prefix p; - route_map_result_t ret = RMAP_MATCH; + route_map_result_t ret = RMAP_PERMITMATCH; afi_t afi; afi = family2afi(rn->p.family); @@ -583,7 +583,7 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, afi, re->type, re->instance, &rn->p, re->ng.nexthop, zvrf->vrf->vrf_id, re->tag, rmap_name); - if (ret != RMAP_MATCH) { + if (ret != RMAP_PERMITMATCH) { UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED); zebra_del_import_table_entry(zvrf, rn, re); return 0; diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 4a88296051..ea42f4dd5d 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -339,7 +339,7 @@ static unsigned nexthop_active_check(struct route_node *rn, struct nexthop *nexthop) { struct interface *ifp; - route_map_result_t ret = RMAP_MATCH; + route_map_result_t ret = RMAP_PERMITMATCH; int family; char buf[SRCDEST2STR_BUFFER]; const struct prefix *p, *src_p; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index afe59b9593..b523d54012 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1364,6 +1364,7 @@ static void zebra_rib_fixup_system(struct route_node *rn) continue; SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); + UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); for (ALL_NEXTHOPS(re->ng, nhop)) { if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE)) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 6f65f8ab7a..04069207cb 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -403,7 +403,7 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf, { int at_least_one = 0; struct nexthop *nexthop; - int ret; + route_map_result_t ret; if (prn && re) { for (nexthop = re->ng.nexthop; nexthop; @@ -465,6 +465,7 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi, RNODE_FOREACH_RE (rn, re) { if (!CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) && CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) + && !CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) && (re->type != ZEBRA_ROUTE_BGP)) break; } @@ -679,6 +680,14 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, continue; } + if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED)) { + if (IS_ZEBRA_DEBUG_NHT_DETAILED) + zlog_debug( + "\tRoute Entry %s queued", + zebra_route_string(re->type)); + continue; + } + /* Just being SELECTED isn't quite enough - must * have an installed nexthop to be useful. */ diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 2f7d50541e..cee2c8980f 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -136,9 +136,9 @@ static int zebra_route_match_delete(struct vty *vty, const char *command, /* 'match tag TAG' * Match function return 1 if match is success else return 0 */ -static route_map_result_t route_match_tag(void *rule, - const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_match_tag(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { route_tag_t *tag; struct nh_rmap_obj *nh_data; @@ -162,10 +162,9 @@ static struct route_map_rule_cmd route_match_tag_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_interface(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_interface(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct nh_rmap_obj *nh_data; char *ifname = rule; @@ -1025,10 +1024,9 @@ DEFPY (show_ipv6_protocol_nht, /* `match ip next-hop IP_ACCESS_LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t route_match_ip_next_hop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_next_hop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; struct nh_rmap_obj *nh_data; @@ -1037,7 +1035,7 @@ static route_map_result_t route_match_ip_next_hop(void *rule, if (type == RMAP_ZEBRA) { nh_data = object; if (!nh_data) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; switch (nh_data->nexthop->type) { case NEXTHOP_TYPE_IFINDEX: @@ -1083,7 +1081,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1094,7 +1092,7 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, if (type == RMAP_ZEBRA) { nh_data = (struct nh_rmap_obj *)object; if (!nh_data) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; switch (nh_data->nexthop->type) { case NEXTHOP_TYPE_IFINDEX: @@ -1139,10 +1137,9 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_address(afi_t afi, void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_address(afi_t afi, void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { struct access_list *alist; @@ -1158,19 +1155,16 @@ static route_map_result_t route_match_address(afi_t afi, void *rule, return RMAP_NOMATCH; } -static route_map_result_t route_match_ip_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_ip_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { return route_match_address(AFI_IP, rule, prefix, type, object); } -static route_map_result_t route_match_ipv6_address(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) - +static enum route_map_cmd_result_t +route_match_ipv6_address(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) { return route_match_address(AFI_IP6, rule, prefix, type, object); } @@ -1200,7 +1194,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object, afi_t afi) { @@ -1218,7 +1212,7 @@ route_match_address_prefix_list(void *rule, const struct prefix *prefix, return RMAP_NOMATCH; } -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1241,7 +1235,7 @@ static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { route_match_address_prefix_list_compile, route_match_address_prefix_list_free}; -static route_map_result_t +static enum route_map_cmd_result_t route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1256,7 +1250,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { /* `match ipv6 next-hop type <TYPE>' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1265,7 +1259,7 @@ route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, if (type == RMAP_ZEBRA && prefix->family == AF_INET6) { nh_data = (struct nh_rmap_obj *)object; if (!nh_data) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) return RMAP_MATCH; @@ -1290,7 +1284,7 @@ struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = { /* `match ip address prefix-len PREFIXLEN' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_address_prefix_len(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1341,7 +1335,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd = { /* `match ip nexthop prefix-len PREFIXLEN' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1352,7 +1346,7 @@ route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix, if (type == RMAP_ZEBRA) { nh_data = (struct nh_rmap_obj *)object; if (!nh_data || !nh_data->nexthop) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; switch (nh_data->nexthop->type) { case NEXTHOP_TYPE_IFINDEX: @@ -1381,7 +1375,7 @@ static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = { /* `match ip next-hop type <blackhole>' */ -static route_map_result_t +static enum route_map_cmd_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1390,7 +1384,7 @@ route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, if (type == RMAP_ZEBRA && prefix->family == AF_INET) { nh_data = (struct nh_rmap_obj *)object; if (!nh_data) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) return RMAP_MATCH; @@ -1415,10 +1409,9 @@ static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = { /* `match source-protocol PROTOCOL' */ -static route_map_result_t route_match_source_protocol(void *rule, - const struct prefix *p, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_source_protocol(void *rule, const struct prefix *p, + route_map_object_t type, void *object) { uint32_t *rib_type = (uint32_t *)rule; struct nh_rmap_obj *nh_data; @@ -1426,7 +1419,7 @@ static route_map_result_t route_match_source_protocol(void *rule, if (type == RMAP_ZEBRA) { nh_data = (struct nh_rmap_obj *)object; if (!nh_data) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH : RMAP_NOMATCH); @@ -1457,10 +1450,9 @@ static struct route_map_rule_cmd route_match_source_protocol_cmd = { route_match_source_protocol_compile, route_match_source_protocol_free}; /* `source-instance` */ -static route_map_result_t route_match_source_instance(void *rule, - const struct prefix *p, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_match_source_instance(void *rule, const struct prefix *p, + route_map_object_t type, void *object) { uint8_t *instance = (uint8_t *)rule; struct nh_rmap_obj *nh_data; @@ -1470,7 +1462,7 @@ static route_map_result_t route_match_source_instance(void *rule, nh_data = (struct nh_rmap_obj *)object; if (!nh_data) - return RMAP_DENYMATCH; + return RMAP_NOMATCH; return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH; } @@ -1500,8 +1492,9 @@ static struct route_map_rule_cmd route_match_source_instance_cmd = { /* `set src A.B.C.D' */ /* Set src. */ -static route_map_result_t route_set_src(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +static enum route_map_cmd_result_t +route_set_src(void *rule, const struct prefix *prefix, route_map_object_t type, + void *object) { struct nh_rmap_obj *nh_data; @@ -1767,7 +1760,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance, struct zebra_vrf *zvrf, route_tag_t tag) { struct route_map *rmap = NULL; - route_map_result_t ret = RMAP_MATCH; + route_map_result_t ret = RMAP_PERMITMATCH; struct nh_rmap_obj nh_obj; nh_obj.nexthop = nexthop; @@ -1839,7 +1832,7 @@ route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto, struct nexthop *nexthop) { struct route_map *rmap = NULL; - route_map_result_t ret = RMAP_MATCH; + route_map_result_t ret = RMAP_PERMITMATCH; struct nh_rmap_obj nh_obj; nh_obj.nexthop = nexthop; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 74baabbf24..4d18045fb3 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -2383,7 +2383,7 @@ DEFUN (show_pbr_iptable, DEFPY (clear_evpn_dup_addr, clear_evpn_dup_addr_cmd, - "clear evpn dup-addr vni <all$vni_all |" CMD_VNI_RANGE"$vni [mac M:A:C$mac_val | ip <A.B.C.D|X:X::X:X>]>", + "clear evpn dup-addr vni <all$vni_all |" CMD_VNI_RANGE"$vni [mac X:X:X:X:X:X | ip <A.B.C.D|X:X::X:X>]>", CLEAR_STR "EVPN\n" "Duplicate address \n" @@ -2398,16 +2398,14 @@ DEFPY (clear_evpn_dup_addr, { struct zebra_vrf *zvrf; struct ipaddr host_ip = {.ipa_type = IPADDR_NONE }; - struct ethaddr mac_addr; int ret = CMD_SUCCESS; zvrf = zebra_vrf_get_evpn(); if (vni_str) { - if (mac_val) { - prefix_str2mac(mac_val, &mac_addr); + if (mac) { ret = zebra_vxlan_clear_dup_detect_vni_mac(vty, zvrf, vni, - &mac_addr); + &mac->eth_addr); } else if (ip) { if (sockunion_family(ip) == AF_INET) { host_ip.ipa_type = IPADDR_V4; |
