From 5c7368624c637033c9151c1f1e80eda4d28c4d34 Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Thu, 18 Jun 2020 12:41:16 -0700 Subject: [PATCH] ADD L3 VNI EVPN Support for SONiC, Send RMAC and VLAN along with prefix to fpmsyncd. --- .../0007-Add-support-of-bgp-l3vni-evpn.patch | 233 ++++++++++++++++++ src/sonic-frr/patch/series | 1 + 2 files changed, 234 insertions(+) create mode 100644 src/sonic-frr/patch/0007-Add-support-of-bgp-l3vni-evpn.patch diff --git a/src/sonic-frr/patch/0007-Add-support-of-bgp-l3vni-evpn.patch b/src/sonic-frr/patch/0007-Add-support-of-bgp-l3vni-evpn.patch new file mode 100644 index 000000000000..f7cb61cbe3d1 --- /dev/null +++ b/src/sonic-frr/patch/0007-Add-support-of-bgp-l3vni-evpn.patch @@ -0,0 +1,233 @@ +diff --git a/lib/nexthop.h b/lib/nexthop.h +index 9dd5fc6fd..3161373d8 100644 +--- a/lib/nexthop.h ++++ b/lib/nexthop.h +@@ -83,6 +83,7 @@ struct nexthop { + #define NEXTHOP_FLAG_MATCHED (1 << 4) /* Already matched vs a nexthop */ + #define NEXTHOP_FLAG_DUPLICATE (1 << 5) /* nexthop duplicates another active one */ + #define NEXTHOP_FLAG_RNH_FILTERED (1 << 6) /* rmap filtered, used by rnh */ ++#define NEXTHOP_FLAG_EVPN_RVTEP (1 << 7) /* EVPN remote vtep nexthop */ + #define NEXTHOP_IS_ACTIVE(flags) \ + (CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \ + && !CHECK_FLAG(flags, NEXTHOP_FLAG_DUPLICATE)) +@@ -95,6 +96,8 @@ struct nexthop { + union g_addr src; + union g_addr rmap_src; /* Src is set via routemap */ + ++ struct ethaddr rmac; ++ + /* Nexthops obtained by recursive resolution. + * + * If the nexthop struct needs to be resolved recursively, +diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c +index 29ee5c1be..cc376d43e 100644 +--- a/zebra/zapi_msg.c ++++ b/zebra/zapi_msg.c +@@ -1492,12 +1492,15 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) + */ + if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { + vtep_ip.ipa_type = IPADDR_V4; ++ SET_FLAG(nexthop->flags, ++ NEXTHOP_FLAG_EVPN_RVTEP); + memcpy(&(vtep_ip.ipaddr_v4), + &(api_nh->gate.ipv4), + sizeof(struct in_addr)); + zebra_vxlan_evpn_vrf_route_add( + api_nh->vrf_id, &api_nh->rmac, + &vtep_ip, &api.prefix); ++ memcpy(&nexthop->rmac, &api_nh->rmac, ETH_ALEN); + } + break; + case NEXTHOP_TYPE_IPV6: +@@ -1516,11 +1519,14 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) + */ + if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { + vtep_ip.ipa_type = IPADDR_V6; ++ SET_FLAG(nexthop->flags, ++ NEXTHOP_FLAG_EVPN_RVTEP); + memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6), + sizeof(struct in6_addr)); + zebra_vxlan_evpn_vrf_route_add( + api_nh->vrf_id, &api_nh->rmac, + &vtep_ip, &api.prefix); ++ memcpy(&nexthop->rmac, &api_nh->rmac, ETH_ALEN); + } + break; + case NEXTHOP_TYPE_BLACKHOLE: +diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c +index f347d3955..e925c5b85 100644 +--- a/zebra/zebra_fpm_netlink.c ++++ b/zebra/zebra_fpm_netlink.c +@@ -134,10 +134,14 @@ static const char *fpm_nh_encap_type_to_str(enum fpm_nh_encap_type_t encap_type) + + struct vxlan_encap_info_t { + vni_t vni; ++ struct ethaddr rmac; ++ int vlan; + }; + + enum vxlan_encap_info_type_t { + VXLAN_VNI = 0, ++ VXLAN_RMAC = 1, ++ VXLAN_VLAN = 2, + }; + + struct fpm_nh_encap_info_t { +@@ -243,6 +247,16 @@ static int netlink_route_info_add_nh(netlink_route_info_t *ri, + + /* Add VNI to VxLAN encap info */ + nhi.encap_info.vxlan_encap.vni = zl3vni->vni; ++ char buf[ETHER_ADDR_STRLEN]; ++ memcpy(&nhi.encap_info.vxlan_encap.rmac, &nexthop->rmac, ETH_ALEN); ++ int vid = vni_from_zl3vni(zl3vni); ++ nhi.encap_info.vxlan_encap.vlan = vid; ++ zfpm_debug("%s: NEWROUTE:%s/%d, Gateway:%s RMAC:%s VLAN:%d", __FUNCTION__, ++ prefix_addr_to_a(ri->prefix), ri->prefix->prefixlen, ++ addr_to_a(ri->af, &nhi.gateway), ++ prefix_mac2str(&nhi.encap_info.vxlan_encap.rmac, buf, sizeof(buf)), ++ vid); ++ + } + } + +@@ -445,10 +459,23 @@ static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf, + break; + case FPM_NH_ENCAP_VXLAN: + vxlan = &nhi->encap_info.vxlan_encap; ++ ++ char buf[ETHER_ADDR_STRLEN]; ++ zfpm_debug("%s: VNI:%d RMAC:%s VLAN:%d", __FUNCTION__, ++ vxlan->vni, prefix_mac2str(&vxlan->rmac, buf, sizeof(buf)), ++ vxlan->vlan); ++ + nest = addattr_nest(&req->n, in_buf_len, + RTA_ENCAP); + addattr32(&req->n, in_buf_len, VXLAN_VNI, + vxlan->vni); ++ ++ addattr_l(&req->n, in_buf_len, VXLAN_RMAC, ++ &vxlan->rmac, sizeof(vxlan->rmac)); ++ ++ addattr32(&req->n, in_buf_len, VXLAN_VLAN, ++ vxlan->vlan); ++ + addattr_nest_end(&req->n, nest); + break; + case FPM_NH_ENCAP_MAX: +@@ -465,12 +492,22 @@ static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf, + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + struct rtnexthop *rtnh; ++ size_t maxnhlen = sizeof(*rtnh) + RTA_LENGTH(af_addr_size(AF_INET6)) /* Gateway */ ++ + RTA_LENGTH(sizeof(uint16_t)) /* Encapsulation type */ ++ + RTA_LENGTH(sizeof(uint32_t)); /* VxLAN VNI */ ++ unsigned short temp_len; + ++ memset(buf, 0, sizeof(buf)); + rta->rta_type = RTA_MULTIPATH; + rta->rta_len = RTA_LENGTH(0); + rtnh = RTA_DATA(rta); + + for (nexthop_num = 0; nexthop_num < ri->num_nhs; nexthop_num++) { ++ if(in_buf_len < (rta->rta_len + maxnhlen)){ ++ //Cannot accomodate more NHs -> Log Error and break ++ zlog_err("netlink_route_info_encode: Ignore Nexthops that exceed the netlink buffer !!"); ++ break; ++ } + nhi = &ri->nhs[nexthop_num]; + + rtnh->rtnh_len = sizeof(*rtnh); +@@ -491,20 +528,34 @@ static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf, + + encap = nhi->encap_info.encap_type; + if (encap > FPM_NH_ENCAP_NONE) { ++ temp_len = rta->rta_len; + rta_addattr_l(rta, sizeof(buf), RTA_ENCAP_TYPE, + &encap, sizeof(uint16_t)); +- rtnh->rtnh_len += sizeof(struct rtattr) + +- sizeof(uint16_t); ++ rtnh->rtnh_len += rta->rta_len - temp_len; ++ + switch (encap) { + case FPM_NH_ENCAP_NONE: + break; + case FPM_NH_ENCAP_VXLAN: ++ temp_len = rta->rta_len; + vxlan = &nhi->encap_info.vxlan_encap; ++ ++ char rmac_buf[ETHER_ADDR_STRLEN]; ++ zfpm_debug("%s: Multi VNI:%d RMAC:%s VLAN:%d", __FUNCTION__, ++ vxlan->vni, prefix_mac2str(&vxlan->rmac, rmac_buf, sizeof(rmac_buf)), ++ vxlan->vlan); ++ + nest = rta_nest(rta, sizeof(buf), RTA_ENCAP); + rta_addattr_l(rta, sizeof(buf), VXLAN_VNI, + &vxlan->vni, sizeof(uint32_t)); ++ ++ rta_addattr_l(rta, sizeof(buf), VXLAN_RMAC, ++ &vxlan->rmac, sizeof(vxlan->rmac)); ++ ++ rta_addattr_l(rta, sizeof(buf), VXLAN_VLAN, ++ &vxlan->vlan, sizeof(uint32_t)); + nest_len = rta_nest_end(rta, nest); +- rtnh->rtnh_len += nest_len; ++ rtnh->rtnh_len += rta->rta_len - temp_len; + break; + case FPM_NH_ENCAP_MAX: + break; +diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c +index ee2956d3e..b2b9f333d 100644 +--- a/zebra/zebra_nhg.c ++++ b/zebra/zebra_nhg.c +@@ -149,6 +149,10 @@ static int nexthop_active(afi_t afi, struct route_entry *re, + nexthop->resolved = NULL; + re->nexthop_mtu = 0; + ++ /* Next hops (remote VTEPs) for EVPN routes are fully resolved. */ ++ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP)) ++ return 1; ++ + /* + * If the kernel has sent us a route, then + * by golly gee whiz it's a good route. +diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c +index bb8b61e7e..9377a6e76 100644 +--- a/zebra/zebra_vxlan.c ++++ b/zebra/zebra_vxlan.c +@@ -3886,6 +3886,36 @@ static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp) + } + } + ++/* ++ * * Get VLAN info from L3VNI ++ * */ ++int vni_from_zl3vni(zebra_l3vni_t *zl3vni) ++{ ++ const struct zebra_if *zif = NULL, *br_zif = NULL; ++ const struct zebra_l2info_vxlan *vxl = NULL; ++ const struct interface *br_ifp; ++ vlanid_t vid; ++ ++ zif = zl3vni->vxlan_if->info; ++ if (!zif) ++ return -1; ++ ++ br_ifp = zif->brslave_info.br_if; ++ if (br_ifp == NULL) ++ return -1; ++ ++ vxl = &zif->l2info.vxl; ++ ++ br_zif = (const struct zebra_if *)br_ifp->info; ++ ++ if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) ++ vid = vxl->access_vlan; ++ else ++ vid = 0; ++ ++ return vid; ++} ++ + /* + * Hash function for VNI. + */ diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index 13619c87ff65..b2005ead6158 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -4,3 +4,4 @@ 0004-Allow-BGP-attr-NEXT_HOP-to-be-0.0.0.0-due-to-allevia.patch 0005-nexthops-compare-vrf-only-if-ip-type.patch 0006-changes-for-making-snmp-socket-non-blocking.patch +0007-Add-support-of-bgp-l3vni-evpn.patch