From 2ee0dd7291aba5668671eaef7fc9f831767d469b Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Tue, 12 Jan 2021 08:46:01 -0800 Subject: [PATCH] [FPMSYNCD] Evpn/Vxlan related changes to support FRR7.5(#1585) 1) With FRR7.5 upgrade Netlink Msg from FRR has NLA_F_NESTED flag set in RTA_TYPE while sending VNI and RMAC. 2) In the new patch to keep it in line with FRR upstreaming, we are not sending the VLAN ID from FRR as it can be extracted from ifindex inside the nexthop information. --- fpmsyncd/fpmlink.cpp | 12 +++++++++ fpmsyncd/routesync.cpp | 59 ++++++++++++++++++++++++++++++------------ fpmsyncd/routesync.h | 4 +-- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index 01ebf2fbec4..d51b3b482ae 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -18,6 +18,18 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, { tb[rta->rta_type] = rta; } + else + { + /* FRR 7.5 is sending RTA_ENCAP with NLA_F_NESTED bit set*/ + if (rta->rta_type & NLA_F_NESTED) + { + int rta_type = rta->rta_type & ~NLA_F_NESTED; + if (rta_type <= max) + { + tb[rta_type] = rta; + } + } + } rta = RTA_NEXT(rta, len); } } diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index d6f85747937..8b61fbaa1c2 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -31,7 +31,6 @@ using namespace swss; #define VXLAN_VNI 0 #define VXLAN_RMAC 1 -#define VXLAN_VLAN 2 #define NH_ENCAP_VXLAN 100 @@ -93,7 +92,7 @@ void RouteSync::parseRtAttrNested(struct rtattr **tb, int max, * * Return: void. */ -void RouteSync::parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan) +void RouteSync::parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rmac) { struct rtattr *tb_encap[3] = {0}; char mac_buf[MAX_ADDR_SIZE+1]; @@ -102,10 +101,9 @@ void RouteSync::parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rma parseRtAttrNested(tb_encap, 3, tb); encap_value = *(uint32_t *)RTA_DATA(tb_encap[VXLAN_VNI]); memcpy(&mac_buf, RTA_DATA(tb_encap[VXLAN_RMAC]), MAX_ADDR_SIZE); - vlan = *(uint32_t *)RTA_DATA(tb_encap[VXLAN_VLAN]); - SWSS_LOG_INFO("Rx MAC %s VNI %d Vlan %d", - prefixMac2Str(mac_buf, mac_val, ETHER_ADDR_STRLEN), encap_value, vlan); + SWSS_LOG_INFO("Rx MAC %s VNI %d", + prefixMac2Str(mac_buf, mac_val, ETHER_ADDR_STRLEN), encap_value); rmac = mac_val; return; @@ -125,9 +123,8 @@ void RouteSync::getEvpnNextHopSep(string& nexthops, string& vni_list, void RouteSync::getEvpnNextHopGwIf(char *gwaddr, int vni_value, string& nexthops, string& vni_list, string& mac_list, string& intf_list, - string rmac, unsigned int vid) + string rmac, string vlan_id) { - string vlan_id = "Vlan" + to_string(vid); nexthops+= gwaddr; vni_list+= to_string(vni_value); mac_list+=rmac; @@ -148,7 +145,10 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, int gw_af; struct in6_addr ipv6_address; string rmac; - uint32_t vlan = 0; + string vlan; + int index; + char if_name[IFNAMSIZ] = "0"; + char ifname_unknown[IFNAMSIZ] = "unknown"; if (tb[RTA_GATEWAY]) gate = RTA_DATA(tb[RTA_GATEWAY]); @@ -189,6 +189,19 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, inet_ntop(gw_af, gateaddr, nexthopaddr, MAX_ADDR_SIZE); + if (tb[RTA_OIF]) + { + index = *(int *)RTA_DATA(tb[RTA_OIF]); + + /* If we cannot get the interface name */ + if (!getIfName(index, if_name, IFNAMSIZ)) + { + strcpy(if_name, ifname_unknown); + } + + vlan = if_name; + } + if (tb[RTA_ENCAP_TYPE]) { encap = *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE]); @@ -197,12 +210,12 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE] && (*(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE]) == NH_ENCAP_VXLAN)) { - parseEncap(tb[RTA_ENCAP], encap_value, rmac, vlan); + parseEncap(tb[RTA_ENCAP], encap_value, rmac); } - SWSS_LOG_DEBUG("Rx MsgType:%d Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%d", h->nlmsg_type, - nexthopaddr, encap, encap_value, rmac.c_str(), vlan); + SWSS_LOG_DEBUG("Rx MsgType:%d Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%s", h->nlmsg_type, + nexthopaddr, encap, encap_value, rmac.c_str(), vlan.c_str()); - if (encap_value == 0 || vlan == 0 || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) + if (encap_value == 0 || !(vlan.compare(ifname_unknown)) || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) { return false; } @@ -270,6 +283,20 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, inet_ntop(gw_af, gateaddr, nexthopaddr, MAX_ADDR_SIZE); + + if (rtnh->rtnh_ifindex) + { + index = rtnh->rtnh_ifindex; + + /* If we cannot get the interface name */ + if (!getIfName(index, if_name, IFNAMSIZ)) + { + strcpy(if_name, ifname_unknown); + } + + vlan = if_name; + } + if (subtb[RTA_ENCAP_TYPE]) { encap = *(uint16_t *)RTA_DATA(subtb[RTA_ENCAP_TYPE]); @@ -278,12 +305,12 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, if (subtb[RTA_ENCAP] && subtb[RTA_ENCAP_TYPE] && (*(uint16_t *)RTA_DATA(subtb[RTA_ENCAP_TYPE]) == NH_ENCAP_VXLAN)) { - parseEncap(subtb[RTA_ENCAP], encap_value, rmac, vlan); + parseEncap(subtb[RTA_ENCAP], encap_value, rmac); } - SWSS_LOG_DEBUG("Multipath Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%d", - nexthopaddr, encap, encap_value, rmac.c_str(), vlan); + SWSS_LOG_DEBUG("Multipath Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%s", + nexthopaddr, encap, encap_value, rmac.c_str(), vlan.c_str()); - if (encap_value == 0 || vlan == 0 || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) + if (encap_value == 0 || !(vlan.compare(ifname_unknown)) || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) { return false; } diff --git a/fpmsyncd/routesync.h b/fpmsyncd/routesync.h index b122a85b66f..71a20f9d666 100644 --- a/fpmsyncd/routesync.h +++ b/fpmsyncd/routesync.h @@ -41,7 +41,7 @@ class RouteSync : public NetMsg /* Handle regular route (include VRF route) */ void onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf); - void parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan); + void parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rmac); void parseRtAttrNested(struct rtattr **tb, int max, struct rtattr *rta); @@ -64,7 +64,7 @@ class RouteSync : public NetMsg void getEvpnNextHopGwIf(char *gwaddr, int vni_value, string& nexthops, string& vni_list, string& mac_list, string& intf_list, - string rmac, unsigned int vid); + string rmac, string vlan_id); bool getEvpnNextHop(struct nlmsghdr *h, int received_bytes, struct rtattr *tb[], string& nexthops, string& vni_list, string& mac_list,