From 31e1a1033d95a14d24bd87cb4bec480067c01a89 Mon Sep 17 00:00:00 2001 From: Stephen Worley Date: Thu, 1 Apr 2021 11:43:23 -0400 Subject: [PATCH] bgpd: send L3VNI as route labels to zebra Add functionality to always send the L3VNI to zebra as a label on the route. It will be zebra's job to determine how to use it (i.e. via Single Vxlan Device or not). The l3VNI according to rfc should always be the second for a type2 route and be the only one available for a type5. Hence, we can just grab the last label in the stack here and add it onto the route. Signed-off-by: Stephen Worley --- bgpd/bgp_zebra.c | 65 +++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 95e80ba1bb..fc2df44ac6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1310,8 +1310,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, struct bgp_path_info local_info; struct bgp_path_info *mpinfo_cp = &local_info; route_tag_t tag; - mpls_label_t label; struct bgp_sid_info *sid_info; + mpls_label_t *labels; + uint32_t num_labels = 0; + mpls_label_t nh_label; int nh_othervrf = 0; bool nh_updated = false; bool do_wt_ecmp; @@ -1404,6 +1406,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) { uint32_t nh_weight; bool is_evpn; + bool is_parent_evpn; if (valid_nh_count >= multipath_num) break; @@ -1469,13 +1472,13 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, BGP_ORIGINAL_UPDATE(bgp_orig, mpinfo, bgp); - if (nh_family == AF_INET) { - is_evpn = is_route_parent_evpn(mpinfo); + is_parent_evpn = is_route_parent_evpn(mpinfo); + if (nh_family == AF_INET) { nh_updated = update_ipv4nh_for_route_install( nh_othervrf, bgp_orig, &mpinfo_cp->attr->nexthop, mpinfo_cp->attr, - is_evpn, api_nh); + is_parent_evpn, api_nh); } else { ifindex_t ifindex = IFINDEX_INTERNAL; struct in6_addr *nexthop; @@ -1483,19 +1486,20 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, nexthop = bgp_path_info_to_ipv6_nexthop(mpinfo_cp, &ifindex); - is_evpn = is_route_parent_evpn(mpinfo); - if (!nexthop) nh_updated = update_ipv4nh_for_route_install( nh_othervrf, bgp_orig, &mpinfo_cp->attr->nexthop, - mpinfo_cp->attr, is_evpn, api_nh); + mpinfo_cp->attr, is_parent_evpn, + api_nh); else nh_updated = update_ipv6nh_for_route_install( nh_othervrf, bgp_orig, nexthop, ifindex, - mpinfo, info, is_evpn, api_nh); + mpinfo, info, is_parent_evpn, api_nh); } + is_evpn = !!CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN); + /* Did we get proper nexthop info to update zebra? */ if (!nh_updated) continue; @@ -1509,16 +1513,32 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, || mpinfo->peer->sort == BGP_PEER_CONFED)) allow_recursion = true; - if (mpinfo->extra && - bgp_is_valid_label(&mpinfo->extra->label[0]) && - !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) { - mpls_lse_decode(mpinfo->extra->label[0], &label, &ttl, - &exp, &bos); + if (mpinfo->extra) { + labels = mpinfo->extra->label; + num_labels = mpinfo->extra->num_labels; + } - SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL); + if (labels && (num_labels > 0) && + (is_evpn || bgp_is_valid_label(&labels[0]))) { + enum lsp_types_t nh_label_type = ZEBRA_LSP_NONE; + if (is_evpn) { + /* + * L3VNI is always last label. Type5 will only + * have one label, Type2 will have two. + */ + nh_label = labels[num_labels - 1]; + nh_label_type = ZEBRA_LSP_EVPN; + + } else if (bgp_is_valid_label(&labels[0])) { + mpls_lse_decode(labels[0], &nh_label, &ttl, + &exp, &bos); + } + + SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL); api_nh->label_num = 1; - api_nh->labels[0] = label; + api_nh->label_type = nh_label_type; + api_nh->labels[0] = nh_label; } if (is_evpn @@ -1529,27 +1549,26 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, api_nh->weight = nh_weight; - if (mpinfo->extra && - bgp_is_valid_label(&mpinfo->extra->label[0]) && - !sid_zero(&mpinfo->extra->sid[0].sid) && - !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) { + if (mpinfo->extra && !is_evpn && + bgp_is_valid_label(&labels[0]) && + !sid_zero(&mpinfo->extra->sid[0].sid)) { sid_info = &mpinfo->extra->sid[0]; memcpy(&api_nh->seg6_segs, &sid_info->sid, sizeof(api_nh->seg6_segs)); if (sid_info->transposition_len != 0) { - mpls_lse_decode(mpinfo->extra->label[0], &label, - &ttl, &exp, &bos); + mpls_lse_decode(labels[0], &nh_label, &ttl, + &exp, &bos); - if (label < MPLS_LABEL_UNRESERVED_MIN) { + if (nh_label < MPLS_LABEL_UNRESERVED_MIN) { if (bgp_debug_zebra(&api.prefix)) zlog_debug( "skip invalid SRv6 routes: transposition scheme is used, but label is too small"); continue; } - transpose_sid(&api_nh->seg6_segs, label, + transpose_sid(&api_nh->seg6_segs, nh_label, sid_info->transposition_offset, sid_info->transposition_len); } -- 2.39.5