diff options
40 files changed, 735 insertions, 203 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 6596e7cfa2..e5ad5e2338 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1890,6 +1890,16 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args) /* Check if this is a Gateway MAC-IP advertisement */ attr->default_gw = bgp_attr_default_gw(attr); + /* Handle scenario where router flag ecommunity is not + * set but default gw ext community is present. + * Use default gateway, set and propogate R-bit. + */ + if (attr->default_gw) + attr->router_flag = 1; + + /* Check EVPN Neighbor advertisement flags, R-bit */ + bgp_attr_evpn_na_flag(attr, &attr->router_flag); + /* Extract the Rmac, if any */ bgp_attr_rmac(attr, &attr->rmac); diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index f17c2a68e4..883b129136 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -185,6 +185,9 @@ struct attr { /* Flag for default gateway extended community in EVPN */ uint8_t default_gw; + /* NA router flag (R-bit) support in EVPN */ + uint8_t router_flag; + /* route tag */ route_tag_t tag; diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c index 14ff01ada5..88e520fdc5 100644 --- a/bgpd/bgp_attr_evpn.c +++ b/bgpd/bgp_attr_evpn.c @@ -210,6 +210,39 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky) return 0; } +/* + * return true if attr contains router flag extended community + */ +void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag) +{ + struct ecommunity *ecom; + int i; + uint8_t val; + + ecom = attr->ecommunity; + if (!ecom || !ecom->size) + return; + + /* If there is a evpn na extendd community set router_flag */ + for (i = 0; i < ecom->size; i++) { + uint8_t *pnt; + uint8_t type, sub_type; + + pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); + type = *pnt++; + sub_type = *pnt++; + + if (type == ECOMMUNITY_ENCODE_EVPN && + sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) { + val = *pnt++; + if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) { + *router_flag = 1; + break; + } + } + } +} + /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst) diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h index 7454b81b96..b036702151 100644 --- a/bgpd/bgp_attr_evpn.h +++ b/bgpd/bgp_attr_evpn.h @@ -65,4 +65,6 @@ extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky); extern uint8_t bgp_attr_default_gw(struct attr *attr); +extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag); + #endif /* _QUAGGA_BGP_ATTR_EVPN_H */ diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 2f59308d65..c71f371a97 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -48,8 +48,11 @@ #define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02 #define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03 #define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d +#define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08 #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01 +#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01 +#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02 /* Low-order octet of the Extended Communities type field for OPAQUE types */ #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index a026df59a0..73f225784c 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -730,10 +730,13 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, struct ecommunity ecom_sticky; struct ecommunity ecom_default_gw; struct ecommunity ecom_rmac; + struct ecommunity ecom_na; struct ecommunity_val eval; struct ecommunity_val eval_sticky; struct ecommunity_val eval_default_gw; struct ecommunity_val eval_rmac; + struct ecommunity_val eval_na; + bgp_encap_types tnl_type; struct listnode *node, *nnode; struct ecommunity *ecom; @@ -798,6 +801,15 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, ecommunity_merge(attr->ecommunity, &ecom_default_gw); } + if (attr->router_flag) { + memset(&ecom_na, 0, sizeof(ecom_na)); + encode_na_flag_extcomm(&eval_na, attr->router_flag); + ecom_na.size = 1; + ecom_na.val = (uint8_t *)eval_na.val; + attr->ecommunity = ecommunity_merge(attr->ecommunity, + &ecom_na); + } + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); } @@ -1089,6 +1101,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, { struct bgp_info *old_select, *new_select; struct bgp_info_pair old_and_new; + struct prefix_evpn *evp; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; int ret = 0; @@ -1100,6 +1113,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, old_select = old_and_new.old; new_select = old_and_new.new; + evp = (struct prefix_evpn *)&rn->p; /* If the best path hasn't changed - see if there is still something to * update * to zebra RIB. @@ -1115,6 +1129,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); if (old_select->attr->default_gw) SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + if (is_evpn_prefix_ipaddr_v6(evp) && + old_select->attr->router_flag) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); + ret = evpn_zebra_install( bgp, vpn, (struct prefix_evpn *)&rn->p, old_select->attr->nexthop, flags); @@ -1148,6 +1166,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); if (new_select->attr->default_gw) SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + if (is_evpn_prefix_ipaddr_v6(evp) && + new_select->attr->router_flag) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); + ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, new_select->attr->nexthop, flags); /* If an old best existed and it was a "local" route, the only @@ -1695,6 +1717,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0; attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0; + attr.router_flag = CHECK_FLAG(flags, + ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? 1 : 0; /* PMSI is only needed for type-3 routes */ if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) @@ -1993,11 +2017,13 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr_sticky, 0, 1, &ri, 0); - else if (evpn_route_is_def_gw(bgp, rn)) + else if (evpn_route_is_def_gw(bgp, rn)) { + if (is_evpn_prefix_ipaddr_v6(evp)) + attr_def_gw.router_flag = 1; update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr_def_gw, 0, 1, &ri, 0); - else + } else update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, 0, 1, &ri, 0); } diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index bf6a24dea6..8d71c3123e 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -311,6 +311,16 @@ static inline void encode_mac_mobility_extcomm(int static_mac, uint32_t seq, eval->val[7] = seq & 0xff; } +static inline void encode_na_flag_extcomm(struct ecommunity_val *eval, + uint8_t na_flag) +{ + memset(eval, 0, sizeof(*eval)); + eval->val[0] = ECOMMUNITY_ENCODE_EVPN; + eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ND; + if (na_flag) + eval->val[2] |= ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG; +} + static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp, struct prefix *ip) { @@ -328,7 +338,7 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp, } } -static inline int is_evpn_prefix_default(struct prefix *evp) +static inline int is_evpn_prefix_default(const struct prefix *evp) { if (evp->family != AF_EVPN) return 0; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index f9f5142cd0..903018b2a2 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -234,7 +234,8 @@ struct bgp_match_peer_compiled { /* Compares the peer specified in the 'match peer' clause with the peer received in bgp_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, struct prefix *prefix, +static route_map_result_t route_match_peer(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -334,7 +335,7 @@ struct route_map_rule_cmd route_match_peer_cmd = {"peer", route_match_peer, /* 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -374,7 +375,7 @@ struct route_map_rule_cmd route_match_ip_address_cmd = { /* 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -421,7 +422,7 @@ struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_route_source(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -430,7 +431,7 @@ static route_map_result_t route_match_ip_route_source(void *rule, struct peer *peer; struct prefix_ipv4 p; - if (type == RMAP_BGP && prefix->family == AF_INET) { + if (type == RMAP_BGP && pfx->family == AF_INET) { bgp_info = object; peer = bgp_info->peer; @@ -473,7 +474,7 @@ struct route_map_rule_cmd route_match_ip_route_source_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -508,7 +509,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 -route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -550,7 +551,8 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { /* `match ip route-source prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_route_source_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_route_source_prefix_list(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -599,7 +601,7 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = { /* Match function should return 1 if match is success else 0 */ static route_map_result_t route_match_evpn_default_route(void *rule, - struct prefix *p, + const struct prefix *p, route_map_object_t type, void *object) { @@ -618,7 +620,7 @@ 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -667,7 +669,8 @@ struct route_map_rule_cmd route_match_mac_address_cmd = { /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t route_match_vni(void *rule, struct prefix *prefix, +static route_map_result_t route_match_vni(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { vni_t vni = 0; @@ -722,7 +725,7 @@ 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, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -731,7 +734,7 @@ static route_map_result_t route_match_evpn_route_type(void *rule, if (type == RMAP_BGP) { route_type = *((uint8_t *)rule); - if (route_type == prefix->u.prefix_evpn.route_type) + if (route_type == pfx->u.prefix_evpn.route_type) return RMAP_MATCH; } @@ -770,7 +773,7 @@ struct route_map_rule_cmd route_match_evpn_route_type_cmd = { /* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_local_pref(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -829,7 +832,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_match_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -852,7 +856,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_match_aspath(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -901,7 +906,7 @@ struct rmap_community { /* Match function for community match. */ static route_map_result_t route_match_community(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -969,7 +974,7 @@ struct route_map_rule_cmd route_match_community_cmd = { /* Match function for lcommunity match. */ static route_map_result_t route_match_lcommunity(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1030,7 +1035,7 @@ struct route_map_rule_cmd route_match_lcommunity_cmd = { /* Match function for extcommunity match. */ static route_map_result_t route_match_ecommunity(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1072,7 +1077,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_match_origin(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1120,7 +1126,7 @@ struct route_map_rule_cmd route_match_origin_cmd = { /* match probability { */ static route_map_result_t route_match_probability(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1175,7 +1181,7 @@ struct route_map_rule_cmd route_match_probability_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_interface(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1221,7 +1227,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -1254,7 +1261,7 @@ struct rmap_ip_nexthop_set { }; static route_map_result_t route_set_ip_nexthop(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1362,7 +1369,7 @@ struct route_map_rule_cmd route_set_ip_nexthop_cmd = { /* Set local preference. */ static route_map_result_t route_set_local_pref(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1396,7 +1403,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_set_weight(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1424,7 +1432,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1457,7 +1466,7 @@ struct route_map_rule_cmd route_set_metric_cmd = { /* For AS path prepend mechanism. */ static route_map_result_t route_set_aspath_prepend(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1520,7 +1529,7 @@ struct route_map_rule_cmd route_set_aspath_prepend_cmd = { * 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, - struct prefix *dummy, + const struct prefix *dummy, route_map_object_t type, void *object) { @@ -1554,7 +1563,8 @@ struct rmap_com_set { }; /* For community set mechanism. */ -static route_map_result_t route_set_community(void *rule, struct prefix *prefix, +static route_map_result_t route_set_community(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1670,7 +1680,7 @@ struct rmap_lcom_set { /* For lcommunity set mechanism. */ static route_map_result_t route_set_lcommunity(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1783,7 +1793,7 @@ struct route_map_rule_cmd route_set_lcommunity_cmd = { /* For large community set mechanism. */ static route_map_result_t route_set_lcommunity_delete(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -1866,10 +1876,11 @@ 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, - struct prefix *prefix, - route_map_object_t type, - void *object) +static route_map_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; @@ -1950,7 +1961,7 @@ struct route_map_rule_cmd route_set_community_delete_cmd = { /* For community set mechanism. Used by _rt and _soo. */ static route_map_result_t route_set_ecommunity(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2037,7 +2048,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_set_origin(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2087,7 +2099,7 @@ struct route_map_rule_cmd route_set_origin_cmd = { /* For atomic aggregate set. */ static route_map_result_t route_set_atomic_aggregate(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -2127,7 +2139,7 @@ struct aggregator { }; static route_map_result_t route_set_aggregator_as(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2180,7 +2192,8 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = { }; /* Set tag to object. object must be pointer to struct bgp_info */ -static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, +static route_map_result_t route_set_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -2205,7 +2218,7 @@ static struct route_map_rule_cmd route_set_tag_cmd = { /* Set label-index to object. object must be pointer to struct bgp_info */ static route_map_result_t route_set_label_index(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2239,7 +2252,7 @@ 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2275,7 +2288,7 @@ 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2327,7 +2340,7 @@ struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = { /* `match ipv6 address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -2363,7 +2376,7 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ipv6_nexthop_global(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -2423,7 +2436,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = { /* Set next-hop preference value. */ static route_map_result_t -route_set_ipv6_nexthop_prefer_global(void *rule, struct prefix *prefix, +route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct bgp_info *bgp_info; @@ -2477,7 +2490,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ipv6_nexthop_local(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -2540,7 +2553,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ipv6_nexthop_peer(void *rule, - struct prefix *prefix, + const struct prefix *pfx, route_map_object_t type, void *object) { @@ -2619,7 +2632,7 @@ 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2659,7 +2672,7 @@ 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -2715,7 +2728,7 @@ struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = { /* For origin set. */ static route_map_result_t route_set_originator_id(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { diff --git a/doc/Makefile.am b/doc/Makefile.am index 62cb3c2edb..19aab63ea3 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -193,6 +193,7 @@ EXTRA_DIST = frr-sphinx.mk \ developer/workflow.rst \ developer/zebra.rst \ user/babeld.rst \ + user/ldpd.rst \ user/basic.rst \ user/bgp.rst \ user/bugs.rst \ diff --git a/doc/extra/spelling_wordlist.txt b/doc/extra/spelling_wordlist.txt index 4c9455e8e9..2944592962 100644 --- a/doc/extra/spelling_wordlist.txt +++ b/doc/extra/spelling_wordlist.txt @@ -83,6 +83,7 @@ IPv isis isisd lan +ldpd le libc libcap diff --git a/doc/user/index.rst b/doc/user/index.rst index a8109fe479..746cc1c32d 100644 --- a/doc/user/index.rst +++ b/doc/user/index.rst @@ -41,6 +41,7 @@ Protocols zebra bgp babeld + ldpd eigrpd isisd nhrpd diff --git a/doc/user/ldpd.rst b/doc/user/ldpd.rst new file mode 100644 index 0000000000..8d88ef176b --- /dev/null +++ b/doc/user/ldpd.rst @@ -0,0 +1,309 @@ +.. _ldp: + +*** +LDP +*** + +The *ldpd* daemon is a standardised protocol that permits exchanging MPLS label +information between MPLS devices. The LDP protocol creates peering between +devices, so as to exchange that label information. This information is stored in +MPLS table of *zebra*, and it injects that MPLS information in the underlying +system (Linux kernel or OpenBSD system for instance). +*ldpd* provides necessary options to create a Layer 2 VPN across MPLS network. +For instance, it is possible to interconnect several sites that share the same +broadcast domain. + +FRR implements LDP as described in :rfc:`5036`; other LDP standard are the +following ones: :rfc:`6720`, :rfc:`6667`, :rfc:`5919`, :rfc:`5561`, :rfc:`7552`, +:rfc:`4447`. +Because MPLS is already available, FRR also supports :rfc:`3031`. + +Running Ldpd +============ + +The *ldpd* daemon can be invoked with any of the common +options (:ref:`common-invocation-options`). + +The *zebra* daemon must be running before *ldpd* is invoked. + +Configuration of *ldpd* is done in its configuration file +:file:`ldpd.conf`. + + +.. _understanding-ldp: + +Understanding LDP principles +============================ + +Let's first introduce some definitions that permit understand better the LDP +protocol: + +- `LSR` : Labeled Switch Router. Networking devices handling labels used to + forward traffic between and through them. + +- `LER` : Labeled Edge Router. A Labeled edge router is located at the edge of + an MPLS network, generally between an IP network and an MPLS network. + + +``LDP`` aims at sharing label information across devices. It tries to establish +peering with remote LDP capable devices, first by discovering using UDP port 646 +, then by peering using TCP port 646. Once the TCP session is established, the +label information is shared, through label advertisements. + +There are different methods to send label advertisement modes. The +implementation actually supports the following : Liberal Label Retention + +Downstream Unsolicited + Independent Control. +The other advertising modes are depicted below, and compared with the current +implementation. + +- Liberal label retention versus conservative mode + In liberal mode, every label sent by every LSR is stored in the MPLS table. + In conservative mode, only the label that was sent by the best next hop + (determined by the IGP metric) for that particular FEC is stored in the MPLS + table. + +- Independent LSP Control versus ordered LSP Control + MPLS has two ways of binding labels to FEC’s; either through ordered LSP + control, or independent LSP control. + Ordered LSP control only binds a label to a FEC if it is the egress LSR, or + the router received a label binding for a FEC from the next hop router. In + this mode, an MPLS router will create a label binding for each FEC and + distribute it to its neighbors so long as he has a entry in the RIB for the + destination. + In the other mode, label bindings are made without any dependencies on another + router advertising a label for a particular FEC. Each router makes it own + independent decision to create a label for each FEC. + By default IOS uses Independent LSP Control, while Juniper implements the + Ordered Control. Both modes are interoperable, the difference is that Ordered + Control prevent blackholing during the LDP convergence process, at cost of + slowing down the convergence itself + +- unsolicited downstream versus downstream on demand + Downstream on demand label distribution is where an LSR must explicitly + request that a label be sent from its downstream router for a particular FEC. + Unsolicited label distribution is where a label is sent from the downstream + router without the original router requesting it. + +.. _configuring-ldpd: + +.. _ldp-configuration: + +LDP Configuration +=================== + +.. index:: [no] mpls ldp +.. clicmd:: [no] mpls ldp + + Enable or disable LDP daemon + +.. index:: [no] router-id A.B.C.D +.. clicmd:: [no] router-id A.B.C.D + + The following command located under MPLS router node configures the MPLS + router-id of the local device. + +.. index:: [no] address-family [ipv4 | ipv6] +.. clicmd:: [no] address-family [ipv4 | ipv6] + + Configure LDP for IPv4 or IPv6 address-family. Located under MPLS route node, + this subnode permits configuring the LDP neighbors. + +.. index:: [no] interface IFACE +.. clicmd:: [no] interface IFACE + + Located under MPLS address-family node, use this command to enable or disable + LDP discovery per interface. IFACE stands for the interface name where LDP is + enabled. By default it is disabled. Once this command executed, the + address-family interface node is configured. + +.. index:: [no] discovery transport-address A.B.C.D | A:B::C:D +.. clicmd:: [no] discovery transport-address A.B.C.D | A:B::C:D + + Located under mpls address-family interface node, use this command to set + the IPv4 or IPv6 transport-address used by the LDP protocol to talk on this + interface. + +.. index:: [no] neighbor A.B.C.D password PASSWORD +.. clicmd:: [no] neighbor A.B.C.D password PASSWORD + + The following command located under MPLS router node configures the router + of a LDP device. This device, if found, will have to comply with the + configured password. PASSWORD is a clear text password wit its digest sent + through the network. + +.. index:: [no] neighbor A.B.C.D holdtime HOLDTIME +.. clicmd:: [no] neighbor A.B.C.D holdtime HOLDTIME + + The following command located under MPLS router node configures the holdtime + value in seconds of the LDP neighbor ID. Configuring it triggers a keepalive + mechanism. That value can be configured between 15 and 65535 seconds. After + this time of non response, the LDP established session will be considered as + set to down. By default, no holdtime is configured for the LDP devices. + +.. index:: [no] discovery hello holdtime HOLDTIME +.. clicmd:: [no] discovery hello holdtime HOLDTIME + +.. index:: [no] discovery hello interval INTERVAL +.. clicmd:: [no] discovery hello interval INTERVAL + + INTERVAL value ranges from 1 to 65535 seconds. Default value is 5 seconds. + This is the value between each hello timer message sent. + HOLDTIME value ranges from 1 to 65535 seconds. Default value is 15 seconds. + That value is added as a TLV in the LDP messages. + +.. _show-ldp-information: + +Show LDP Information +==================== + +These commands dump various parts of *ldpd*. + +.. index:: show mpls ldp neighbor [A.B.C.D] +.. clicmd:: show mpls ldp neighbor [A.B.C.D] + + This command dumps the various neighbors discovered. Below example shows that + local machine has an operation neighbor with ID set to 1.1.1.1. + + :: + + west-vm# show mpls ldp neighbor + AF ID State Remote Address Uptime + ipv4 1.1.1.1 OPERATIONAL 1.1.1.1 00:01:37 + west-vm# + +.. index:: show mpls ldp neighbor [A.B.C.D] capabilities +.. clicmd:: show mpls ldp neighbor [A.B.C.D] capabilities + +.. index:: show mpls ldp neighbor [A.B.C.D] detail +.. clicmd:: show mpls ldp neighbor [A.B.C.D] detail + + Above commands dump other neighbor information. + +.. index:: show mpls ldp discovery [detail] +.. clicmd:: show mpls ldp discovery [detail] + +.. index:: show mpls ldp ipv4 discovery [detail] +.. clicmd:: show mpls ldp ipv4 discovery [detail] + +.. index:: show mpls ldp ipv6 discovery [detail] +.. clicmd:: show mpls ldp ipv6 discovery [detail] + + Above commands dump discovery information. + +.. index:: show mpls ldp ipv4 interface +.. clicmd:: show mpls ldp ipv4 interface + +.. index:: show mpls ldp ipv6 interface +.. clicmd:: show mpls ldp ipv6 interface + + Above command dumps the IPv4 or IPv6 interface per where LDP is enabled. + Below output illustrates what is dumped for IPv4. + + :: + + west-vm# show mpls ldp ipv4 interface + AF Interface State Uptime Hello Timers ac + ipv4 eth1 ACTIVE 00:08:35 5/15 0 + ipv4 eth3 ACTIVE 00:08:35 5/15 1 + + +.. index:: show mpls ldp ipv4|ipv6 binding +.. clicmd:: show mpls ldp ipv4|ipv6 binding + + Above command dumps the binding obtained through MPLS exchanges with LDP. + + :: + + west-vm# show mpls ldp ipv4 binding + AF Destination Nexthop Local Label Remote Label In Use + ipv4 1.1.1.1/32 1.1.1.1 16 imp-null yes + ipv4 2.2.2.2/32 1.1.1.1 imp-null 16 no + ipv4 10.0.2.0/24 1.1.1.1 imp-null imp-null no + ipv4 10.115.0.0/24 1.1.1.1 imp-null 17 no + ipv4 10.135.0.0/24 1.1.1.1 imp-null imp-null no + ipv4 10.200.0.0/24 1.1.1.1 17 imp-null yes + west-vm# + +LDP debugging commands +======================== + +.. index:: + simple: debug mpls ldp KIND + simple: no debug mpls ldp KIND + +.. clicmd:: [no] debug mpls ldp KIND + + Enable or disable debugging messages of a given kind. ``KIND`` can + be one of: + + - ``discovery`` + - ``errors`` + - ``event`` + - ``labels`` + - ``messages`` + - ``zebra`` + +LDP Example Configuration +========================= + +Below configuration gives a typical MPLS configuration of a device located in a +MPLS backbone. LDP is enabled on two interfaces and will attempt to peer with +two neighbors with router-id set to either 1.1.1.1 or 3.3.3.3. + +.. code-block:: frr + + mpls ldp + router-id 2.2.2.2 + neighbor 1.1.1.1 password test + neighbor 3.3.3.3 password test + ! + address-family ipv4 + discovery transport-address 2.2.2.2 + ! + interface eth1 + ! + interface eth3 + ! + exit-address-family + ! + + +Deploying LDP across a backbone generally is done in a full mesh configuration +topology. LDP is typically deployed with an IGP like OSPF, that helps discover +the remote IPs. Below example is an OSPF configuration extract that goes with +LDP configuration + +.. code-block:: frr + + router ospf + ospf router-id 2.2.2.2 + network 0.0.0.0/0 area 0 + ! + + +Below output shows the routing entry on the LER side. The OSPF routing entry +(10.200.0.0) is associated with Label entry (17), and shows that MPLS push action +that traffic to that destination will be applied. + +:: + + north-vm# show ip route + Codes: K - kernel route, C - connected, S - static, R - RIP, + O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP, + T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP, + F - PBR, + > - selected route, * - FIB route + + O>* 1.1.1.1/32 [110/120] via 10.115.0.1, eth2, label 16, 00:00:15 + O>* 2.2.2.2/32 [110/20] via 10.115.0.1, eth2, label implicit-null, 00:00:15 + O 3.3.3.3/32 [110/10] via 0.0.0.0, loopback1 onlink, 00:01:19 + C>* 3.3.3.3/32 is directly connected, loopback1, 00:01:29 + O>* 10.0.2.0/24 [110/11] via 10.115.0.1, eth2, label implicit-null, 00:00:15 + O 10.100.0.0/24 [110/10] is directly connected, eth1, 00:00:32 + C>* 10.100.0.0/24 is directly connected, eth1, 00:00:32 + O 10.115.0.0/24 [110/10] is directly connected, eth2, 00:00:25 + C>* 10.115.0.0/24 is directly connected, eth2, 00:00:32 + O>* 10.135.0.0/24 [110/110] via 10.115.0.1, eth2, label implicit-null, 00:00:15 + O>* 10.200.0.0/24 [110/210] via 10.115.0.1, eth2, label 17, 00:00:15 + north-vm# + diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index d92207d57c..3c2cf7b3fc 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -50,7 +50,7 @@ #include "isis_routemap.h" static route_map_result_t route_match_ip_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -83,7 +83,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* ------------------------------------------------------------*/ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -116,7 +116,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* ------------------------------------------------------------*/ static route_map_result_t route_match_ipv6_address(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -149,7 +149,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_cmd = { /* ------------------------------------------------------------*/ static route_map_result_t -route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -181,7 +181,8 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { /* ------------------------------------------------------------*/ -static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index 6c86582960..d77a3e7e93 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -861,6 +861,7 @@ ldp_vty_init (void) install_element(LDP_IPV6_NODE, &ldp_label_remote_accept_cmd); install_element(LDP_IPV6_NODE, &ldp_ttl_security_disable_cmd); install_element(LDP_IPV6_NODE, &ldp_interface_cmd); + install_element(LDP_IPV6_NODE, &no_ldp_interface_cmd); install_element(LDP_IPV6_NODE, &ldp_session_holdtime_cmd); install_element(LDP_IPV6_NODE, &ldp_neighbor_ipv6_targeted_cmd); install_element(LDP_IPV6_NODE, &ldp_exit_address_family_cmd); diff --git a/lib/filter.c b/lib/filter.c index 670c65374a..0528b0f2ad 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -157,7 +157,7 @@ static const char *filter_type_str(struct filter *filter) } /* If filter match to the prefix then return 1. */ -static int filter_match_cisco(struct filter *mfilter, struct prefix *p) +static int filter_match_cisco(struct filter *mfilter, const struct prefix *p) { struct filter_cisco *filter; struct in_addr mask; @@ -181,7 +181,7 @@ static int filter_match_cisco(struct filter *mfilter, struct prefix *p) } /* If filter match to the prefix then return 1. */ -static int filter_match_zebra(struct filter *mfilter, struct prefix *p) +static int filter_match_zebra(struct filter *mfilter, const struct prefix *p) { struct filter_zebra *filter = NULL; @@ -372,10 +372,11 @@ static struct access_list *access_list_get(afi_t afi, const char *name) } /* Apply access list to object (which should be struct prefix *). */ -enum filter_type access_list_apply(struct access_list *access, void *object) +enum filter_type access_list_apply(struct access_list *access, + const void *object) { struct filter *filter; - struct prefix *p = (struct prefix *)object; + const struct prefix *p = (const struct prefix *)object; if (access == NULL) return FILTER_DENY; diff --git a/lib/filter.h b/lib/filter.h index c02516409b..97854b1e97 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -59,6 +59,7 @@ extern void access_list_reset(void); extern void access_list_add_hook(void (*func)(struct access_list *)); extern void access_list_delete_hook(void (*func)(struct access_list *)); extern struct access_list *access_list_lookup(afi_t, const char *); -extern enum filter_type access_list_apply(struct access_list *, void *); +extern enum filter_type access_list_apply(struct access_list *access, + const void *object); #endif /* _ZEBRA_FILTER_H */ diff --git a/lib/plist.c b/lib/plist.c index 056b737f54..2b666f256f 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -656,7 +656,7 @@ static const char *prefix_list_type_str(struct prefix_list_entry *pentry) } static int prefix_list_entry_match(struct prefix_list_entry *pentry, - struct prefix *p) + const struct prefix *p) { int ret; @@ -683,14 +683,15 @@ static int prefix_list_entry_match(struct prefix_list_entry *pentry, return 1; } -enum prefix_list_type prefix_list_apply_which_prefix(struct prefix_list *plist, - struct prefix **which, - void *object) +enum prefix_list_type prefix_list_apply_which_prefix( + struct prefix_list *plist, + const struct prefix **which, + const void *object) { struct prefix_list_entry *pentry, *pbest = NULL; - struct prefix *p = (struct prefix *)object; - uint8_t *byte = p->u.val; + const struct prefix *p = (const struct prefix *)object; + const uint8_t *byte = p->u.val; size_t depth; size_t validbits = p->prefixlen; struct pltrie_table *table; diff --git a/lib/plist.h b/lib/plist.h index 67e345a485..fecbe0e2ce 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -61,8 +61,9 @@ extern struct prefix_list *prefix_list_lookup(afi_t, const char *); * If it is a empty plist return a NULL pointer. */ extern enum prefix_list_type -prefix_list_apply_which_prefix(struct prefix_list *plist, struct prefix **which, - void *object); +prefix_list_apply_which_prefix(struct prefix_list *plist, + const struct prefix **which, + const void *object); #define prefix_list_apply(A, B) prefix_list_apply_which_prefix((A), NULL, (B)) extern struct prefix_list *prefix_bgp_orf_lookup(afi_t, const char *); diff --git a/lib/routemap.c b/lib/routemap.c index 056c793454..6c4585365a 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -1387,7 +1387,7 @@ int route_map_delete_set(struct route_map_index *index, const char *set_name, static route_map_result_t route_map_apply_match(struct route_map_rule_list *match_list, - struct prefix *prefix, route_map_object_t type, + const struct prefix *prefix, route_map_object_t type, void *object) { route_map_result_t ret = RMAP_NOMATCH; @@ -1417,7 +1417,8 @@ route_map_apply_match(struct route_map_rule_list *match_list, } /* Apply route map to the object. */ -route_map_result_t route_map_apply(struct route_map *map, struct prefix *prefix, +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; diff --git a/lib/routemap.h b/lib/routemap.h index 0aeba7e1f6..0f7c391f84 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -87,8 +87,10 @@ struct route_map_rule_cmd { const char *str; /* Function for value set or match. */ - route_map_result_t (*func_apply)(void *, struct prefix *, - route_map_object_t, void *); + route_map_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 *); @@ -208,7 +210,7 @@ extern struct route_map *route_map_lookup_by_name(const char *name); /* Apply route map to the object. */ extern route_map_result_t route_map_apply(struct route_map *map, - struct prefix *, + const struct prefix *prefix, route_map_object_t object_type, void *object); diff --git a/lib/zclient.h b/lib/zclient.h index 10a1723010..49419b3df3 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -448,6 +448,8 @@ enum zapi_iptable_notify_owner { /* Zebra MAC types */ #define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/ #define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/ +#define ZEBRA_MACIP_TYPE_ROUTER_FLAG 0x04 /* Router Flag - proxy NA */ +#define ZEBRA_MACIP_TYPE_OVERRIDE_FLAG 0x08 /* Override Flag */ struct zclient_options { bool receive_notify; diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index a723396507..e6bd3faf40 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1345,7 +1345,8 @@ static void ospf6_redistribute_show_config(struct vty *vty) /* Routemap Functions */ static route_map_result_t -ospf6_routemap_rule_match_address_prefixlist(void *rule, struct prefix *prefix, +ospf6_routemap_rule_match_address_prefixlist(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1384,7 +1385,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t -ospf6_routemap_rule_match_interface(void *rule, struct prefix *prefix, +ospf6_routemap_rule_match_interface(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct interface *ifp; @@ -1422,7 +1423,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_match_interface_cmd = { /* Match function for matching route tags */ static route_map_result_t ospf6_routemap_rule_match_tag(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -1442,7 +1443,7 @@ static struct route_map_rule_cmd ospf6_routemap_rule_match_tag_cmd = { }; static route_map_result_t -ospf6_routemap_rule_set_metric_type(void *rule, struct prefix *prefix, +ospf6_routemap_rule_set_metric_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { char *metric_type = rule; @@ -1478,7 +1479,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = { }; static route_map_result_t -ospf6_routemap_rule_set_metric(void *rule, struct prefix *prefix, +ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { char *metric = rule; @@ -1513,7 +1514,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = { }; static route_map_result_t -ospf6_routemap_rule_set_forwarding(void *rule, struct prefix *prefix, +ospf6_routemap_rule_set_forwarding(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { char *forwarding = rule; @@ -1551,7 +1552,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = { }; static route_map_result_t ospf6_routemap_rule_set_tag(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index f3271acfa2..c5ec1db336 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -118,7 +118,7 @@ static void ospf_route_map_event(route_map_event_t 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -163,7 +163,7 @@ struct route_map_rule_cmd route_match_ip_nexthop_cmd = { /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -205,7 +205,7 @@ 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -244,7 +244,7 @@ struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -280,7 +280,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_interface(void *rule, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -318,7 +318,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -348,7 +349,8 @@ struct ospf_metric { /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -427,7 +429,7 @@ 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -476,7 +478,7 @@ 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, struct prefix *prefix, +static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index cc39b09043..c1623ec15e 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -194,7 +194,7 @@ static int pim_rp_prefix_list_used(struct pim_instance *pim, const char *plist) */ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim, struct in_addr rp, - struct prefix *group) + const struct prefix *group) { struct listnode *node; struct rp_info *rp_info; @@ -212,13 +212,13 @@ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim, * Given a group, return the rp_info for that group */ static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, - struct prefix *group) + const struct prefix *group) { struct listnode *node; struct rp_info *best = NULL; struct rp_info *rp_info; struct prefix_list *plist; - struct prefix *p, *bp; + const struct prefix *p, *bp; struct route_node *rn; bp = NULL; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 38a29b72af..b947ca0625 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -868,6 +868,7 @@ void igmp_source_forward_reevaluate_all(struct pim_instance *pim) void igmp_source_forward_start(struct pim_instance *pim, struct igmp_source *source) { + struct pim_interface *pim_oif; struct igmp_group *group; struct prefix_sg sg; int result; @@ -893,10 +894,20 @@ void igmp_source_forward_start(struct pim_instance *pim, } group = source->source_group; + pim_oif = group->group_igmp_sock->interface->info; + if (!pim_oif) { + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: multicast not enabled on oif=%s ?", + __PRETTY_FUNCTION__, + source->source_group->group_igmp_sock + ->interface->name); + } + return; + } if (!source->source_channel_oil) { struct in_addr vif_source; - struct pim_interface *pim_oif; struct prefix nht_p, src, grp; struct pim_nexthop_cache out_pnc; struct pim_nexthop nexthop; @@ -983,19 +994,6 @@ void igmp_source_forward_start(struct pim_instance *pim, source and receiver attached to the same interface. See TODO T22. */ - pim_oif = - source->source_group->group_igmp_sock->interface->info; - if (!pim_oif) { - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug( - "%s: multicast not enabled on oif=%s ?", - __PRETTY_FUNCTION__, - source->source_group->group_igmp_sock - ->interface->name); - } - return; - } - if (input_iface_vif_index == pim_oif->mroute_vif_index) { /* ignore request for looped MFC entry */ if (PIM_DEBUG_IGMP_TRACE) { @@ -1036,12 +1034,15 @@ void igmp_source_forward_start(struct pim_instance *pim, return; } + if (!(PIM_I_am_DR(pim_oif))) + return; + /* Feed IGMPv3-gathered local membership information into PIM per-interface (S,G) state. */ if (!pim_ifchannel_local_membership_add( - group->group_igmp_sock->interface, &sg)) { + group->group_igmp_sock->interface, &sg)) { if (PIM_DEBUG_MROUTE) zlog_warn("%s: Failure to add local membership for %s", __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 2c02324876..88473c164e 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -58,7 +58,8 @@ static void rip_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, +static route_map_result_t route_match_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -111,7 +112,7 @@ 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -159,7 +160,7 @@ struct route_map_rule_cmd route_match_interface_cmd = { /* 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -206,7 +207,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 -route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -251,7 +252,7 @@ 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -290,7 +291,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -324,7 +325,7 @@ 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, +static route_map_result_t route_match_tag(void *rule, const struct prefix *p, route_map_object_t type, void *object) { route_tag_t *tag; @@ -354,7 +355,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -453,7 +455,7 @@ static struct route_map_rule_cmd route_set_metric_cmd = { /* 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -505,7 +507,7 @@ 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, +static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index e9a38d137b..a18332516e 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -38,7 +38,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_match_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -86,7 +87,7 @@ 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -128,7 +129,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -157,7 +159,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_set_metric(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -254,7 +257,7 @@ static struct route_map_rule_cmd route_set_metric_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static route_map_result_t route_set_ipv6_nexthop_local(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -307,7 +310,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_set_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 208fb116e6..a9f183ed7b 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -403,7 +403,7 @@ end self.save_contexts(ctx_keys, current_context_lines) new_ctx = True - elif line == "end": + elif line in ["end", "exit-vrf"]: self.save_contexts(ctx_keys, current_context_lines) log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 56bff0d3f6..8943b434d7 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -891,8 +891,12 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) zns = zebra_ns_lookup(ns_id); ifa = NLMSG_DATA(h); - if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) + if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) { + zlog_warn( + "Invalid address family: %d received from kernel interface addr change: %d", + ifa->ifa_family, h->nlmsg_type); return 0; + } if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) return 0; @@ -1114,6 +1118,14 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) return 0; } + if (!(ifi->ifi_family == AF_UNSPEC || ifi->ifi_family == AF_BRIDGE + || ifi->ifi_family == AF_INET6)) { + zlog_warn( + "Invalid address family: %d received from kernel link change: %d", + ifi->ifi_family, h->nlmsg_type); + return 0; + } + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); if (len < 0) { zlog_err("%s: Message received from netlink is of a broken size %d %zu", diff --git a/zebra/rt.h b/zebra/rt.h index 57e62e4f6e..e40bae3a3e 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -122,7 +122,7 @@ extern int kernel_del_mac(struct interface *ifp, vlanid_t vid, int local); extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac); + struct ethaddr *mac, uint8_t flags); extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip); /* diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 485abc3f12..4fe42f2ebc 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -387,8 +387,15 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, memcpy(&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; - src_p.prefixlen = - 0; // Forces debug below to not display anything + if (rtm->rtm_src_len != 0) { + char buf[PREFIX_STRLEN]; + zlog_warn("unsupported IPv4 sourcedest route (dest %s vrf %u)", + prefix2str(&p, buf, sizeof(buf)), vrf_id); + return 0; + } + + /* Force debug below to not display anything for source */ + src_p.prefixlen = 0; } else if (rtm->rtm_family == AF_INET6) { p.family = AF_INET6; memcpy(&p.u.prefix6, dest, 16); @@ -399,14 +406,6 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, src_p.prefixlen = rtm->rtm_src_len; } - if (rtm->rtm_src_len != 0) { - char buf[PREFIX_STRLEN]; - zlog_warn( - "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", - prefix2str(&p, buf, sizeof(buf)), vrf_id); - return 0; - } - /* * For ZEBRA_ROUTE_KERNEL types: * @@ -492,7 +491,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, nh.vrf_id = nh_vrf_id; rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, - NULL, &nh, table, metric, mtu, distance, tag); + &src_p, &nh, table, metric, mtu, distance, tag); } else { /* This is a multipath route */ @@ -591,8 +590,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, if (re->nexthop_num == 0) XFREE(MTYPE_RE, re); else - rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, - re); + rib_add_multipath(afi, SAFI_UNICAST, &p, + &src_p, re); } } else { if (!tb[RTA_MULTIPATH]) { @@ -624,12 +623,12 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, if (gate) memcpy(&nh.gate, gate, sz); rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, - &p, NULL, &nh, table, metric, true); + &p, &src_p, &nh, table, metric, true); } else { /* XXX: need to compare the entire list of nexthops * here for NLM_F_APPEND stupidity */ rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, - &p, NULL, NULL, table, metric, true); + &p, &src_p, NULL, table, metric, true); } } @@ -740,6 +739,15 @@ int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) return 0; } + if (!(rtm->rtm_family == AF_INET || rtm->rtm_family == AF_INET6 + || rtm->rtm_family == AF_ETHERNET + || rtm->rtm_family == AF_MPLS)) { + zlog_warn( + "Invalid address family: %d received from kernel route change: %d", + rtm->rtm_family, h->nlmsg_type); + return 0; + } + /* Connected route. */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s %s %s proto %s NS %u", @@ -2151,6 +2159,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) char buf2[INET6_ADDRSTRLEN]; int mac_present = 0; uint8_t ext_learned; + uint8_t router_flag; ndm = NLMSG_DATA(h); @@ -2241,6 +2250,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) } ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0; + router_flag = (ndm->ndm_flags & NTF_ROUTER) ? 1 : 0; if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( @@ -2263,7 +2273,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (ndm->ndm_state & NUD_VALID) return zebra_vxlan_handle_kernel_neigh_update( ifp, link_if, &ip, &mac, ndm->ndm_state, - ext_learned); + ext_learned, router_flag); return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip); } @@ -2386,12 +2396,19 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id) if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6) return netlink_ipneigh_change(h, len, ns_id); + else { + zlog_warn( + "Invalid address family: %d received from kernel neighbor change: %d", + ndm->ndm_family, h->nlmsg_type); + return 0; + } return 0; } static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac, uint32_t flags, int cmd) + struct ethaddr *mac, uint8_t flags, + uint16_t state, int cmd) { struct { struct nlmsghdr n; @@ -2414,11 +2431,10 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; - req.ndm.ndm_state = flags; + req.ndm.ndm_state = state; req.ndm.ndm_ifindex = ifp->ifindex; req.ndm.ndm_type = RTN_UNICAST; - req.ndm.ndm_flags = NTF_EXT_LEARNED; - + req.ndm.ndm_flags = flags; ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); @@ -2426,12 +2442,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s", + zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x", nl_msg_type_to_str(cmd), nl_family_to_str(req.ndm.ndm_family), ifp->name, ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)), mac ? prefix_mac2str(mac, buf2, sizeof(buf2)) - : "null"); + : "null", flags); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); @@ -2452,14 +2468,15 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, } int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac) + struct ethaddr *mac, uint8_t flags) { - return netlink_neigh_update2(ifp, ip, mac, NUD_NOARP, RTM_NEWNEIGH); + return netlink_neigh_update2(ifp, ip, mac, flags, + NUD_NOARP, RTM_NEWNEIGH); } int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) { - return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH); + return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH); } /* diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index cba0376300..346699198f 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -88,7 +88,8 @@ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, #endif /* Interface between zebra message and rtm message. */ -static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm_ipv4(int cmd, const struct prefix *p, + struct route_entry *re) { struct sockaddr_in *mask = NULL; @@ -272,7 +273,8 @@ static int sin6_masklen(struct in6_addr mask) #endif /* SIN6_LEN */ /* Interface between zebra message and rtm message. */ -static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm_ipv6(int cmd, const struct prefix *p, + struct route_entry *re) { struct sockaddr_in6 *mask; struct sockaddr_in6 sin_dest, sin_mask, sin_gate; @@ -374,7 +376,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) return 0; /*XXX*/ } -static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm(int cmd, const struct prefix *p, struct route_entry *re) { switch (PREFIX_FAMILY(p)) { case AF_INET: @@ -460,7 +462,7 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, } int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac) + struct ethaddr *mac, uint8_t flags) { return 0; } diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index c7a8517e17..d683e92bcc 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -204,8 +204,12 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) } frh = NLMSG_DATA(h); - if (frh->family != AF_INET && frh->family != AF_INET6) + if (frh->family != AF_INET && frh->family != AF_INET6) { + zlog_warn( + "Invalid address family: %d received from kernel rule change: %d", + frh->family, h->nlmsg_type); return 0; + } if (frh->action != FR_ACT_TO_TBL) return 0; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 9bf6bfa22f..71d48632c1 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2331,7 +2331,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, if (!re) return 0; - assert(!src_p || afi == AFI_IP6); + assert(!src_p || !src_p->prefixlen || afi == AFI_IP6); /* Lookup table. */ table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table); @@ -2421,7 +2421,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, char buf2[INET6_ADDRSTRLEN]; rib_dest_t *dest; - assert(!src_p || afi == AFI_IP6); + assert(!src_p || !src_p->prefixlen || afi == AFI_IP6); /* Lookup table. */ table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index bf6718164f..0b48e87b1b 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -137,7 +137,8 @@ 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, struct prefix *prefix, +static route_map_result_t route_match_tag(void *rule, + const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; @@ -163,7 +164,7 @@ 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, - struct prefix *prefix, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -879,7 +880,7 @@ DEFUN (show_ipv6_protocol_nht, /* 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -937,7 +938,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 -route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -993,7 +994,7 @@ 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, + const struct prefix *prefix, route_map_object_t type, void *object) { @@ -1032,7 +1033,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; @@ -1068,7 +1069,7 @@ static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { /* `match ip address prefix-len PREFIXLEN' */ static route_map_result_t -route_match_address_prefix_len(void *rule, struct prefix *prefix, +route_match_address_prefix_len(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { uint32_t *prefixlen = (uint32_t *)rule; @@ -1122,7 +1123,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 -route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix, +route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { uint32_t *prefixlen = (uint32_t *)rule; @@ -1162,7 +1163,7 @@ static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = { /* `match source-protocol PROTOCOL' */ static route_map_result_t route_match_source_protocol(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -1204,7 +1205,7 @@ static struct route_map_rule_cmd route_match_source_protocol_cmd = { /* `source-instance` */ static route_map_result_t route_match_source_instance(void *rule, - struct prefix *prefix, + const struct prefix *p, route_map_object_t type, void *object) { @@ -1246,7 +1247,7 @@ 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, struct prefix *prefix, +static route_map_result_t route_set_src(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct nh_rmap_obj *nh_data; @@ -1359,8 +1360,7 @@ route_map_result_t zebra_route_map_check(int family, int rib_type, rmap = route_map_lookup_by_name( proto_rm[family][ZEBRA_ROUTE_MAX]); if (rmap) { - ret = route_map_apply(rmap, (struct prefix *)p, - RMAP_ZEBRA, &nh_obj); + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); } return (ret); @@ -1385,7 +1385,8 @@ void zebra_del_import_table_route_map(afi_t afi, uint32_t table) route_map_result_t zebra_import_table_route_map_check(int family, int re_type, uint8_t instance, - struct prefix *p, struct nexthop *nexthop, + const struct prefix *p, + struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name) { @@ -1410,7 +1411,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance, } route_map_result_t zebra_nht_route_map_check(int family, int client_proto, - struct prefix *p, + const struct prefix *p, struct route_entry *re, struct nexthop *nexthop) { @@ -1430,11 +1431,10 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto, if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX]) rmap = route_map_lookup_by_name( nht_rm[family][ZEBRA_ROUTE_MAX]); - if (rmap) { + if (rmap) ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); - } - return (ret); + return ret; } static void zebra_route_map_mark_update(const char *rmap_name) diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index 688c8b7203..d33487d7af 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -35,7 +35,8 @@ extern void zebra_route_map_write_delay_timer(struct vty *); extern route_map_result_t zebra_import_table_route_map_check(int family, int rib_type, uint8_t instance, - struct prefix *p, struct nexthop *nexthop, + const struct prefix *p, + struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name); extern route_map_result_t @@ -43,7 +44,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance, const struct prefix *p, struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag); extern route_map_result_t -zebra_nht_route_map_check(int family, int client_proto, struct prefix *p, +zebra_nht_route_map_check(int family, int client_proto, const struct prefix *p, struct route_entry *, struct nexthop *nexthop); diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 8a37e1df22..8ee47d2f1b 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1198,7 +1198,8 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, break; } - if (re->vrf_id != nexthop->vrf_id) { + if ((re->vrf_id != nexthop->vrf_id) + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); @@ -1415,7 +1416,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, break; } - if (nexthop->vrf_id != re->vrf_id) { + if ((nexthop->vrf_id != re->vrf_id) + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); @@ -1569,7 +1571,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, break; } - if (nexthop->vrf_id != re->vrf_id) { + if ((nexthop->vrf_id != re->vrf_id) + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); if (vrf) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 59f0cf52f0..06d1b3618c 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -33,6 +33,9 @@ #include "jhash.h" #include "vlan.h" #include "vxlan.h" +#ifdef GNU_LINUX +#include <linux/neighbour.h> +#endif #include "zebra/rib.h" #include "zebra/rt.h" @@ -282,6 +285,7 @@ static void zvni_find_neigh_addr_width(struct hash_backet *backet, void *ctxt) ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf); if (width > wctx->addr_width) wctx->addr_width = width; + } /* @@ -327,6 +331,10 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json) else json_object_boolean_true_add(json, "defaultGateway"); } + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) { + if (!json) + vty_out(vty, " Router"); + } if (json == NULL) vty_out(vty, "\n"); } @@ -432,11 +440,11 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, return; } num_neigh = hashcount(zvni->neigh_table); - if (json == NULL) + if (json == NULL) { vty_out(vty, "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", zvni->vni, num_neigh); - else { + } else { json_vni = json_object_new_object(); json_object_int_add(json_vni, "numArpNd", num_neigh); snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni); @@ -458,9 +466,10 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, wctx.json = json_vni; hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); - if (json == NULL) + if (json == NULL) { vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", "Type", "MAC", "Remote VTEP"); + } hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); if (json) @@ -581,6 +590,9 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) vty_out(vty, " Default-gateway Mac "); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)) + vty_out(vty, " Remote-gateway Mac "); + vty_out(vty, "\n"); /* print all the associated neigh */ vty_out(vty, " Neighbors:\n"); @@ -1553,6 +1565,9 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW)) SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + /* Set router flag (R-bit) based on local neigh entry add */ + if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG)) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, ZEBRA_MACIP_ADD); @@ -1576,6 +1591,8 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) struct zebra_if *zif; struct zebra_l2info_vxlan *vxl; struct interface *vlan_if; + uint8_t flags; + int ret = 0; if (!(n->flags & ZEBRA_NEIGH_REMOTE)) return 0; @@ -1588,8 +1605,13 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); if (!vlan_if) return -1; - - return kernel_add_neigh(vlan_if, &n->ip, &n->emac); +#ifdef GNU_LINUX + flags = NTF_EXT_LEARNED; + if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) + flags |= NTF_ROUTER; + ret = kernel_add_neigh(vlan_if, &n->ip, &n->emac, flags); +#endif + return ret; } /* @@ -1811,6 +1833,9 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, /* Set "local" forwarding info. */ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW); + /* Set Router flag (R-bit) */ + if (ip->ipa_type == IPADDR_V6) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); memcpy(&n->emac, macaddr, ETH_ALEN); n->ifindex = ifp->ifindex; @@ -1820,10 +1845,10 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP", + "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x", ifp->name, ifp->ifindex, zvni->vni, prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(ip, buf2, sizeof(buf2))); + ipaddr2str(ip, buf2, sizeof(buf2)), n->flags); zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags); @@ -1966,7 +1991,8 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet, static int zvni_local_neigh_update(zebra_vni_t *zvni, struct interface *ifp, struct ipaddr *ip, - struct ethaddr *macaddr) + struct ethaddr *macaddr, + uint8_t router_flag) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -2084,15 +2110,19 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, return 0; } + /*Set router flag (R-bit) */ + if (router_flag) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + /* Inform BGP. */ if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u", + zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni); + zvni->vni, n->flags); ZEBRA_NEIGH_SET_ACTIVE(n); - return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0); + return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags); } static int zvni_remote_neigh_update(zebra_vni_t *zvni, @@ -2534,7 +2564,8 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) return -1; vxl = &zif->l2info.vxl; - sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0; + sticky = CHECK_FLAG(mac->flags, + (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)) ? 1 : 0; return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr, mac->fwd_info.r_vtep_ip, sticky); @@ -3362,14 +3393,22 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) */ static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) { + uint8_t flags; + int ret = 0; + if (!is_l3vni_oper_up(zl3vni)) return -1; if (!(n->flags & ZEBRA_NEIGH_REMOTE) || !(n->flags & ZEBRA_NEIGH_REMOTE_NH)) return 0; - - return kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac); +#ifdef GNU_LINUX + flags = NTF_EXT_LEARNED; + if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) + flags |= NTF_ROUTER; + ret = kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac, flags); +#endif + return ret; } /* @@ -4513,9 +4552,11 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); wctx.zvni = zvni; wctx.vty = vty; + wctx.addr_width = 15; wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; wctx.r_vtep_ip = vtep_ip; wctx.json = json; + hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); if (use_json) { @@ -4944,7 +4985,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, struct ipaddr *ip, struct ethaddr *macaddr, uint16_t state, - uint8_t ext_learned) + uint8_t ext_learned, + uint8_t router_flag) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -4975,7 +5017,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, /* Is this about a local neighbor or a remote one? */ if (!ext_learned) - return zvni_local_neigh_update(zvni, ifp, ip, macaddr); + return zvni_local_neigh_update(zvni, ifp, ip, macaddr, + router_flag); return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state); } @@ -5152,6 +5195,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; uint8_t sticky = 0; + u_char remote_gw = 0; uint8_t flags = 0; struct interface *ifp = NULL; struct zebra_if *zif = NULL; @@ -5193,6 +5237,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) /* Get flags - sticky mac and/or gateway mac */ STREAM_GETC(s, flags); sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); + remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); l++; if (IS_ZEBRA_DEBUG_VXLAN) @@ -5266,6 +5311,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0) != sticky + || (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? 1 : 0) + != remote_gw || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)) update_mac = 1; @@ -5297,6 +5344,11 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) else UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + if (remote_gw) + SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); + zvni_process_neigh_on_remote_mac_add(zvni, mac); /* Install the entry. */ @@ -5353,6 +5405,10 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) n->r_vtep_ip = vtep_ip; SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + /* Set router flag (R-bit) to this Neighbor entry */ + if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + /* Install the entry. */ zvni_neigh_install(zvni, n); } diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 34d1152751..2732ef72ed 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -124,7 +124,8 @@ extern int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if); extern int zebra_vxlan_handle_kernel_neigh_update( struct interface *ifp, struct interface *link_if, struct ipaddr *ip, - struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned); + struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned, + uint8_t router_flag); extern int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp, struct interface *link_if, struct ipaddr *ip); diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index fa7075f2de..e86967041b 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -247,6 +247,8 @@ struct zebra_mac_t_ { #define ZEBRA_MAC_STICKY 0x08 /* Static MAC */ #define ZEBRA_MAC_REMOTE_RMAC 0x10 /* remote router mac */ #define ZEBRA_MAC_DEF_GW 0x20 +/* remote VTEP advertised MAC as default GW */ +#define ZEBRA_MAC_REMOTE_DEF_GW 0x40 /* Local or remote info. */ union { @@ -329,6 +331,7 @@ struct zebra_neigh_t_ { #define ZEBRA_NEIGH_REMOTE 0x02 #define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */ #define ZEBRA_NEIGH_DEF_GW 0x08 +#define ZEBRA_NEIGH_ROUTER_FLAG 0x10 enum zebra_neigh_state state; |
