From 1730a6cb4dc5cb777ea0e3f5a0d2b073f6b04d37 Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Thu, 18 Jun 2020 14:12:40 -0700 Subject: [PATCH 01/24] [FPMSYNCD] EVPN Type5 prefix handling in FPMSYNCD. --- fpmsyncd/fpmlink.cpp | 93 +++++++- fpmsyncd/fpmlink.h | 2 + fpmsyncd/fpmsyncd.cpp | 2 + fpmsyncd/routesync.cpp | 485 +++++++++++++++++++++++++++++++++++++++++ fpmsyncd/routesync.h | 29 +++ 5 files changed, 610 insertions(+), 1 deletion(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index 464f965221..153493e5fc 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -9,6 +9,81 @@ using namespace swss; using namespace std; +void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, + int len) +{ + while (RTA_OK(rta, len)) { + if (rta->rta_type <= max) + tb[rta->rta_type] = rta; + rta = RTA_NEXT(rta, len); + } +} + +bool FpmLink::isRawProcessing(struct nlmsghdr *h) +{ + int len; + short encap_type = 0; + struct rtmsg *rtm; + struct rtattr *tb[RTA_MAX + 1]; + + rtm = (struct rtmsg *)NLMSG_DATA(h); + + if (h->nlmsg_type != RTM_NEWROUTE + && h->nlmsg_type != RTM_DELROUTE) + return 0; + + len = (int)(h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg))); + if (len < 0) { + return 0; + } + + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); + + if (!tb[RTA_MULTIPATH]) + { + if (tb[RTA_ENCAP_TYPE]) + encap_type = *(short *)RTA_DATA(tb[RTA_ENCAP_TYPE]); + } + else + { + /* This is a multipath route */ + int len; + struct rtnexthop *rtnh = (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + len = (int)RTA_PAYLOAD(tb[RTA_MULTIPATH]); + struct rtattr *subtb[RTA_MAX + 1]; + + for (;;) { + if (len < (int)sizeof(*rtnh) + || rtnh->rtnh_len > len) + break; + if (rtnh->rtnh_len > sizeof(*rtnh)) { + memset(subtb, 0, sizeof(subtb)); + netlink_parse_rtattr(subtb, RTA_MAX, RTNH_DATA(rtnh), + (int)(rtnh->rtnh_len - sizeof(*rtnh))); + if (subtb[RTA_ENCAP_TYPE]) + { + encap_type = *(uint16_t *)RTA_DATA(subtb[RTA_ENCAP_TYPE]); + break; + } + } + + if (rtnh->rtnh_len == 0) + break; + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + } + + SWSS_LOG_INFO("Rx MsgType:%d Encap:%d", h->nlmsg_type, encap_type); + + if (encap_type > 0) + return 1; + + return 0; +} + FpmLink::FpmLink(unsigned short port) : MSG_BATCH_SIZE(256), m_bufSize(FPM_MAX_MSG_LEN * MSG_BATCH_SIZE), @@ -120,12 +195,28 @@ uint64_t FpmLink::readData() if (hdr->msg_type == FPM_MSG_TYPE_NETLINK) { - nl_msg *msg = nlmsg_convert((nlmsghdr *)fpm_msg_data(hdr)); + bool isRaw = false; + + nlmsghdr *nl_hdr = (nlmsghdr *)fpm_msg_data(hdr); + + isRaw = isRawProcessing(nl_hdr); + + nl_msg *msg = nlmsg_convert(nl_hdr); if (msg == NULL) + { throw system_error(make_error_code(errc::bad_message), "Unable to convert nlmsg"); + } nlmsg_set_proto(msg, NETLINK_ROUTE); + + if (isRaw) + { + NetDispatcher::getInstance().onNetlinkMessageRaw(msg); + } + else + { NetDispatcher::getInstance().onNetlinkMessage(msg); + } nlmsg_free(msg); } start += msg_len; diff --git a/fpmsyncd/fpmlink.h b/fpmsyncd/fpmlink.h index 8ef570589f..297a0474f3 100644 --- a/fpmsyncd/fpmlink.h +++ b/fpmsyncd/fpmlink.h @@ -32,6 +32,8 @@ class FpmLink : public Selectable { { }; + bool isRawProcessing(struct nlmsghdr *h); + private: unsigned int m_bufSize; char *m_messageBuffer; diff --git a/fpmsyncd/fpmsyncd.cpp b/fpmsyncd/fpmsyncd.cpp index 59427bf1fa..e54817aca7 100644 --- a/fpmsyncd/fpmsyncd.cpp +++ b/fpmsyncd/fpmsyncd.cpp @@ -56,6 +56,8 @@ int main(int argc, char **argv) NetDispatcher::getInstance().registerMessageHandler(RTM_NEWROUTE, &sync); NetDispatcher::getInstance().registerMessageHandler(RTM_DELROUTE, &sync); + NetDispatcher::getInstance().registerRawMessageHandler(RTM_NEWROUTE, &sync); + NetDispatcher::getInstance().registerRawMessageHandler(RTM_DELROUTE, &sync); while (true) { diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index 2250d26d1a..24b03cd9cc 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -9,7 +9,9 @@ #include "producerstatetable.h" #include "fpmsyncd/fpmlink.h" #include "fpmsyncd/routesync.h" +#include "macaddress.h" #include +#include using namespace std; using namespace swss; @@ -18,6 +20,28 @@ using namespace swss; #define VNET_PREFIX "Vnet" #define VRF_PREFIX "Vrf" +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +#ifndef NDA_RTA +#define NDA_RTA(r) \ + ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#endif + +#define VXLAN_VNI 0 +#define VXLAN_RMAC 1 +#define VXLAN_VLAN 2 +#define NH_ENCAP_VXLAN 100 + + +#define IPV4_MAX_BYTE 4 +#define IPV6_MAX_BYTE 16 +#define IPV4_MAX_BITLEN 32 +#define IPV6_MAX_BITLEN 128 + +#define ETHER_ADDR_STRLEN (3*ETH_ALEN) + RouteSync::RouteSync(RedisPipeline *pipeline) : m_routeTable(pipeline, APP_ROUTE_TABLE_NAME, true), m_vnet_routeTable(pipeline, APP_VNET_RT_TABLE_NAME, true), @@ -30,6 +54,457 @@ RouteSync::RouteSync(RedisPipeline *pipeline) : rtnl_link_alloc_cache(m_nl_sock, AF_UNSPEC, &m_link_cache); } +char *RouteSync::prefix_mac2str(char *mac, char *buf, int size) +{ + char *ptr = buf; + + if (!mac) + return NULL; + if (!buf) + return NULL; + + snprintf(ptr, (ETHER_ADDR_STRLEN), "%02x:%02x:%02x:%02x:%02x:%02x", + (uint8_t)mac[0], (uint8_t)mac[1], + (uint8_t)mac[2], (uint8_t)mac[3], + (uint8_t)mac[4], (uint8_t)mac[5]); + return ptr; +} + +void RouteSync::netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, + int len) +{ + while (RTA_OK(rta, len)) { + if (rta->rta_type <= max) + tb[rta->rta_type] = rta; + rta = RTA_NEXT(rta, len); + } +} + +/** + * netlink_parse_rtattr_nested() - Parses a nested route attribute + * @tb: Pointer to array for storing rtattr in. + * @max: Max number to store. + * @rta: Pointer to rtattr to look for nested items in. + */ +void RouteSync::netlink_parse_rtattr_nested(struct rtattr **tb, int max, + struct rtattr *rta) +{ + netlink_parse_rtattr(tb, max, (struct rtattr *)RTA_DATA(rta), (int)RTA_PAYLOAD(rta)); +} + +/** + * @parse_encap() - Parses encapsulated attributes + * @tb: Pointer to rtattr to look for nested items in. + * @labels: Pointer to store vni in. + * + * Return: void. + */ +void RouteSync::parse_encap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan) +{ + struct rtattr *tb_encap[3] = {0}; + char mac_buf[MAX_ADDR_SIZE+1]; + char mac_val[MAX_ADDR_SIZE+1]; + + netlink_parse_rtattr_nested(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_DEBUG("Rx MAC %s VNI %d Vlan %d", + prefix_mac2str(mac_buf, mac_val, ETHER_ADDR_STRLEN), encap_value, vlan); + rmac = mac_val; + + return; +} +void RouteSync::getEvpnNextHopSep(string& nexthops, string& vni_list, + string& mac_list, string& intf_list) +{ + nexthops += string(","); + vni_list += string(","); + mac_list += string(","); + intf_list += string(","); + + return; +} + +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 vlan_id = "Vlan" + to_string(vid); + nexthops+= gwaddr; + vni_list+= to_string(vni_value); + mac_list+=rmac; + intf_list+=vlan_id; +} + +bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, + struct rtattr *tb[], string& nexthops, + string& vni_list, string& mac_list, + string& intf_list) +{ + void *gate = NULL; + char nexthopaddr[MAX_ADDR_SIZE] = {0}; + char gateaddr[MAX_ADDR_SIZE] = {0}; + uint32_t encap_value = 0; + uint32_t ecmp_count = 0; + uint16_t encap = 0; + int gw_af; + struct in6_addr ipv6_address; + string rmac; + uint32_t vlan = 0; + + if (tb[RTA_GATEWAY]) + gate = RTA_DATA(tb[RTA_GATEWAY]); + + if (h->nlmsg_type == RTM_NEWROUTE) { + if (!tb[RTA_MULTIPATH]) { + gw_af = AF_INET; // default value + if (gate) + { + if (RTA_PAYLOAD(tb[RTA_GATEWAY]) <= IPV4_MAX_BYTE) + { + memcpy(gateaddr, gate, IPV4_MAX_BYTE); + gw_af = AF_INET; + } + else + { + memcpy(ipv6_address.s6_addr, gate, IPV6_MAX_BYTE); + gw_af = AF_INET6; + } + } + + if(gw_af == AF_INET6) + { + if (IN6_IS_ADDR_V4MAPPED(&ipv6_address)) + { + memcpy(gateaddr, (ipv6_address.s6_addr+12), IPV4_MAX_BYTE); + gw_af = AF_INET; + } + else + { + SWSS_LOG_NOTICE("IPv6 tunnel nexthop not supported Nexthop:%s encap:%d encap_value:%d", + inet_ntop(gw_af, ipv6_address.s6_addr, nexthopaddr, MAX_ADDR_SIZE), encap, encap_value); + return false; + } + } + + inet_ntop(gw_af, gateaddr, nexthopaddr, MAX_ADDR_SIZE); + + if (tb[RTA_ENCAP_TYPE]) + encap = *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE]); + + if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE] + && (*(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE]) == NH_ENCAP_VXLAN)) + { + parse_encap(tb[RTA_ENCAP], encap_value, rmac, vlan); + } + SWSS_LOG_NOTICE("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); + + if (encap_value == 0 || vlan == 0 + || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) + return false; + + getEvpnNextHopGwIf(nexthopaddr, encap_value, nexthops, vni_list, mac_list, intf_list, rmac, vlan); + } + else + { + /* This is a multipath route */ + /* Need to add the code for multipath */ + int len; + struct rtattr *subtb[RTA_MAX + 1]; + struct rtnexthop *rtnh = (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + len = (int)RTA_PAYLOAD(tb[RTA_MULTIPATH]); + + for (;;) { + uint16_t encap = 0; + if (len < (int)sizeof(*rtnh) + || rtnh->rtnh_len > len) + break; + gate = 0; + if (rtnh->rtnh_len > sizeof(*rtnh)) { + memset(subtb, 0, sizeof(subtb)); + + netlink_parse_rtattr(subtb, RTA_MAX, RTNH_DATA(rtnh), + (int)(rtnh->rtnh_len - sizeof(*rtnh))); + + if (subtb[RTA_GATEWAY]) + gate = RTA_DATA(subtb[RTA_GATEWAY]); + + if (gate) + { + if (RTA_PAYLOAD(subtb[RTA_GATEWAY]) <= IPV4_MAX_BYTE) + { + memcpy(gateaddr, gate, IPV4_MAX_BYTE); + gw_af = AF_INET; + } + else + { + memcpy(ipv6_address.s6_addr, gate, IPV6_MAX_BYTE); + gw_af = AF_INET6; + } + } + + if(gw_af == AF_INET6) + { + if (IN6_IS_ADDR_V4MAPPED(&ipv6_address)) + { + memcpy(gateaddr, (ipv6_address.s6_addr+12), IPV4_MAX_BYTE); + gw_af = AF_INET; + } + else + { + SWSS_LOG_NOTICE("IPv6 tunnel nexthop not supported Nexthop:%s encap:%d encap_value:%d", + inet_ntop(gw_af, ipv6_address.s6_addr, nexthopaddr, MAX_ADDR_SIZE), encap, encap_value); + return false; + } + } + + inet_ntop(gw_af, gateaddr, nexthopaddr, MAX_ADDR_SIZE); + + if (subtb[RTA_ENCAP_TYPE]) + encap = *(uint16_t *)RTA_DATA(subtb[RTA_ENCAP_TYPE]); + + if (subtb[RTA_ENCAP] && subtb[RTA_ENCAP_TYPE] + && (*(uint16_t *)RTA_DATA(subtb[RTA_ENCAP_TYPE]) == NH_ENCAP_VXLAN)) + { + parse_encap(subtb[RTA_ENCAP], encap_value, rmac, vlan); + } + SWSS_LOG_NOTICE("Multipath Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%d", + nexthopaddr, encap, encap_value, rmac.c_str(), vlan); + + if (encap_value == 0 || vlan == 0 + || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) + return false; + + if(ecmp_count) + { + getEvpnNextHopSep(nexthops, vni_list, mac_list, intf_list); + } + + getEvpnNextHopGwIf(nexthopaddr, encap_value, nexthops, vni_list, mac_list, intf_list, rmac, vlan); + ecmp_count++; + } + + if (rtnh->rtnh_len == 0) + break; + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + } + } + return true; +} + +void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) +{ + struct rtmsg *rtm; + struct rtattr *tb[RTA_MAX + 1]; + void *dest = NULL; + char anyaddr[16] = {0}; + char dstaddr[16] = {0}; + int dst_len = 0; + char buf[MAX_ADDR_SIZE]; + char destipprefix[IFNAMSIZ + MAX_ADDR_SIZE + 2] = {0}; + int nlmsg_type = h->nlmsg_type; + unsigned int vrf_index; + + rtm = (struct rtmsg *)NLMSG_DATA(h); + + /* Parse attributes and extract fields of interest. */ + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); + + if (tb[RTA_DST]) + dest = RTA_DATA(tb[RTA_DST]); + else + dest = anyaddr; + + if (rtm->rtm_family == AF_INET) + { + if (rtm->rtm_dst_len > IPV4_MAX_BITLEN) { + return; + } + memcpy(dstaddr, dest, IPV4_MAX_BYTE); + dst_len = rtm->rtm_dst_len; + } + else if (rtm->rtm_family == AF_INET6) + { + if (rtm->rtm_dst_len > IPV6_MAX_BITLEN) { + return; + } + memcpy(dstaddr, dest, IPV6_MAX_BYTE); + dst_len = rtm->rtm_dst_len; + } + + SWSS_LOG_INFO("Rx MsgType:%d Family:%d Prefix:%s/%d", h->nlmsg_type, rtm->rtm_family, + inet_ntop(rtm->rtm_family, dstaddr, buf, MAX_ADDR_SIZE), dst_len); + + /* Table corresponding to route. */ + if (tb[RTA_TABLE]) + vrf_index = *(int *)RTA_DATA(tb[RTA_TABLE]); + else + vrf_index = rtm->rtm_table; + + if (vrf_index) + { + if (!getIfName(vrf_index, destipprefix, IFNAMSIZ)) + { + SWSS_LOG_ERROR("Fail to get the VRF name (ifindex %u)", vrf_index); + return; + } + /* + * Now vrf device name is required to start with VRF_PREFIX, + * it is difficult to split vrf_name:ipv6_addr. + */ + if (memcmp(destipprefix, VRF_PREFIX, strlen(VRF_PREFIX))) + { + SWSS_LOG_ERROR("Invalid VRF name %s (ifindex %u)", destipprefix, vrf_index); + return; + } + destipprefix[strlen(destipprefix)] = ':'; + } + + /* Full mask route append prefix length, or else resync cannot match. */ + snprintf(destipprefix + strlen(destipprefix), sizeof(destipprefix) - strlen(destipprefix), "%s/%u", + inet_ntop(rtm->rtm_family, dstaddr, buf, MAX_ADDR_SIZE), dst_len); + + SWSS_LOG_NOTICE("Receive route message dest ip prefix: %s Op:%s", + destipprefix, + nlmsg_type == RTM_NEWROUTE ? "add":"del"); + + /* + * Upon arrival of a delete msg we could either push the change right away, + * or we could opt to defer it if we are going through a warm-reboot cycle. + */ + bool warmRestartInProgress = m_warmStartHelper.inProgress(); + + if (nlmsg_type == RTM_DELROUTE) + { + if (!warmRestartInProgress) + { + m_routeTable.del(destipprefix); + return; + } + else + { + SWSS_LOG_INFO("Warm-Restart mode: Receiving delete msg: %s", + destipprefix); + + vector fvVector; + const KeyOpFieldsValuesTuple kfv = std::make_tuple(destipprefix, + DEL_COMMAND, + fvVector); + m_warmStartHelper.insertRefreshMap(kfv); + return; + } + } + else if (nlmsg_type != RTM_NEWROUTE) + { + SWSS_LOG_NOTICE("Unknown message-type: %d for %s", nlmsg_type, destipprefix); + return; + } + + switch (rtm->rtm_type) + { + case RTN_BLACKHOLE: + case RTN_UNREACHABLE: + case RTN_PROHIBIT: + { + SWSS_LOG_ERROR("RTN_BLACKHOLE route not expected (%s)", destipprefix); + return; + } + case RTN_UNICAST: + break; + + case RTN_MULTICAST: + case RTN_BROADCAST: + case RTN_LOCAL: + SWSS_LOG_NOTICE("BUM routes aren't supported yet (%s)", destipprefix); + return; + + default: + return; + } + + /* Get nexthop lists */ + string nexthops; + string vni_list; + string mac_list; + string intf_list; + bool ret; + + ret = getEvpnNextHop(h, len, tb, nexthops, vni_list, mac_list, intf_list); + if (ret == false) + { + SWSS_LOG_NOTICE("EVPN Route issue with RouteTable msg: %s vtep:%s vni:%s mac:%s intf:%s", + destipprefix, nexthops.c_str(), vni_list.c_str(), mac_list.c_str(), intf_list.c_str()); + return; + } + + if (nexthops.empty() || mac_list.empty()) + { + SWSS_LOG_NOTICE("EVPN IP Prefix: %s nexthop or rmac is empty", destipprefix); + return; + } + + vector fvVector; + FieldValueTuple nh("nexthop", nexthops); + FieldValueTuple intf("ifname", intf_list); + FieldValueTuple vni("vni_label", vni_list); + FieldValueTuple mac("router_mac", mac_list); + + fvVector.push_back(nh); + fvVector.push_back(intf); + fvVector.push_back(vni); + fvVector.push_back(mac); + + if (!warmRestartInProgress) + { + m_routeTable.set(destipprefix, fvVector); + SWSS_LOG_NOTICE("RouteTable set msg: %s vtep:%s vni:%s mac:%s intf:%s", + destipprefix, nexthops.c_str(), vni_list.c_str(), mac_list.c_str(), intf_list.c_str()); + } + + /* + * During routing-stack restarting scenarios route-updates will be temporarily + * put on hold by warm-reboot logic. + */ + else + { + SWSS_LOG_INFO("Warm-Restart mode: RouteTable set msg: %s vtep:%s vni:%s mac:%s", + destipprefix, nexthops.c_str(), vni_list.c_str(), mac_list.c_str()); + + const KeyOpFieldsValuesTuple kfv = std::make_tuple(destipprefix, + SET_COMMAND, + fvVector); + m_warmStartHelper.insertRefreshMap(kfv); + } + return; +} + +void RouteSync::onMsgRaw(struct nlmsghdr *h) +{ + int len; + + if ((h->nlmsg_type != RTM_NEWROUTE) + && (h->nlmsg_type != RTM_DELROUTE)) + return; + /* Length validity. */ + len = (int)(h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg))); + if (len < 0) { + SWSS_LOG_INFO("%s: Message received from netlink is of a broken size %d %zu", + __PRETTY_FUNCTION__, h->nlmsg_len, + (size_t)NLMSG_LENGTH(sizeof(struct ndmsg))); + return; + } + onEvpnRouteMsg(h, len); + return; +} + void RouteSync::onMsg(int nlmsg_type, struct nl_object *obj) { struct rtnl_route *route_obj = (struct rtnl_route *)obj; @@ -100,6 +575,12 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) dip = rtnl_route_get_dst(route_obj); nl_addr2str(dip, destipprefix + strlen(destipprefix), MAX_ADDR_SIZE); + + /* Full mask route append prefix length, or else resync cannot match. */ + if (nl_addr_get_prefixlen(dip) == (8 * nl_addr_get_len(dip))) + { + snprintf(destipprefix + strlen(destipprefix), sizeof(destipprefix) - strlen(destipprefix), "/%u", nl_addr_get_prefixlen(dip)); + } SWSS_LOG_DEBUG("Receive new route message dest ip prefix: %s", destipprefix); /* @@ -177,6 +658,10 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) if (!warmRestartInProgress) { + /*Delete vni & router_mac fields to handle route update scenario + * This operation is idempotent and generate only one event to consumer*/ + m_routeTable.hdel(destipprefix, "vni_label"); + m_routeTable.hdel(destipprefix, "router_mac"); m_routeTable.set(destipprefix, fvVector); SWSS_LOG_DEBUG("RouteTable set msg: %s %s %s", destipprefix, nexthops.c_str(), ifnames.c_str()); diff --git a/fpmsyncd/routesync.h b/fpmsyncd/routesync.h index d636ca134a..4943d6e3c2 100644 --- a/fpmsyncd/routesync.h +++ b/fpmsyncd/routesync.h @@ -6,6 +6,7 @@ #include "netmsg.h" #include "warmRestartHelper.h" #include +#include using namespace std; @@ -20,6 +21,7 @@ class RouteSync : public NetMsg virtual void onMsg(int nlmsg_type, struct nl_object *obj); + virtual void onMsgRaw(struct nlmsghdr *obj); WarmStartHelper m_warmStartHelper; private: @@ -35,12 +37,39 @@ class RouteSync : public NetMsg /* Handle regular route (include VRF route) */ void onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf); + /* Parse the Raw netlink msg */ + void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, + int len); + + void parse_encap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan); + + void netlink_parse_rtattr_nested(struct rtattr **tb, int max, + struct rtattr *rta); + + char *prefix_mac2str(char *mac, char *buf, int size); + + + /* Handle prefix route */ + void onEvpnRouteMsg(struct nlmsghdr *h, int len); + /* Handle vnet route */ void onVnetRouteMsg(int nlmsg_type, struct nl_object *obj, string vnet); /* Get interface name based on interface index */ bool getIfName(int if_index, char *if_name, size_t name_len); + void getEvpnNextHopSep(string& nexthops, string& vni_list, + string& mac_list, string& intf_list); + + void getEvpnNextHopGwIf(char *gwaddr, int vni_value, + string& nexthops, string& vni_list, + string& mac_list, string& intf_list, + string rmac, unsigned int vid); + + bool getEvpnNextHop(struct nlmsghdr *h, int received_bytes, struct rtattr *tb[], + string& nexthops, string& vni_list, string& mac_list, + string& intf_list); + /* Get next hop gateway IP addresses */ string getNextHopGw(struct rtnl_route *route_obj); From 8de4b3609fec2fc14b02190d2530c01198e686c2 Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 21 Sep 2020 11:22:46 -0700 Subject: [PATCH 02/24] Update fpmsyncd.cpp --- fpmsyncd/fpmsyncd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpmsyncd/fpmsyncd.cpp b/fpmsyncd/fpmsyncd.cpp index e54817aca7..5e0dfd6a72 100644 --- a/fpmsyncd/fpmsyncd.cpp +++ b/fpmsyncd/fpmsyncd.cpp @@ -57,7 +57,7 @@ int main(int argc, char **argv) NetDispatcher::getInstance().registerMessageHandler(RTM_NEWROUTE, &sync); NetDispatcher::getInstance().registerMessageHandler(RTM_DELROUTE, &sync); NetDispatcher::getInstance().registerRawMessageHandler(RTM_NEWROUTE, &sync); - NetDispatcher::getInstance().registerRawMessageHandler(RTM_DELROUTE, &sync); + NetDispatcher::getInstance().registerRawMessageHandler(RTM_DELROUTE, &sync); while (true) { From cf4ed790563bd0e9194d0bbe7df798163e290737 Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 21 Sep 2020 11:24:52 -0700 Subject: [PATCH 03/24] Update fpmlink.cpp --- fpmsyncd/fpmlink.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index 153493e5fc..703bf68c43 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -12,7 +12,8 @@ using namespace std; void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len) { - while (RTA_OK(rta, len)) { + while (RTA_OK(rta, len)) + { if (rta->rta_type <= max) tb[rta->rta_type] = rta; rta = RTA_NEXT(rta, len); @@ -33,7 +34,8 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) return 0; len = (int)(h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg))); - if (len < 0) { + if (len < 0) + { return 0; } @@ -53,11 +55,13 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) len = (int)RTA_PAYLOAD(tb[RTA_MULTIPATH]); struct rtattr *subtb[RTA_MAX + 1]; - for (;;) { + for (;;) + { if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) break; - if (rtnh->rtnh_len > sizeof(*rtnh)) { + if (rtnh->rtnh_len > sizeof(*rtnh)) + { memset(subtb, 0, sizeof(subtb)); netlink_parse_rtattr(subtb, RTA_MAX, RTNH_DATA(rtnh), (int)(rtnh->rtnh_len - sizeof(*rtnh))); From 8bc8d5d413dc41bc5db5c628f8b46875680add3e Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 21 Sep 2020 11:33:35 -0700 Subject: [PATCH 04/24] Update fpmlink.cpp --- fpmsyncd/fpmlink.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index 703bf68c43..0d4d347117 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -59,7 +59,8 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) { if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) - break; + break; + if (rtnh->rtnh_len > sizeof(*rtnh)) { memset(subtb, 0, sizeof(subtb)); From 2189e1ab12062049a6868addfde5a637e6b4eb6e Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 21 Sep 2020 11:34:50 -0700 Subject: [PATCH 05/24] Update fpmlink.cpp --- fpmsyncd/fpmlink.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index 0d4d347117..d554f9b7f4 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -220,7 +220,7 @@ uint64_t FpmLink::readData() } else { - NetDispatcher::getInstance().onNetlinkMessage(msg); + NetDispatcher::getInstance().onNetlinkMessage(msg); } nlmsg_free(msg); } From 46e7c96b8fe06c0d8de575a28483d6a7320595c0 Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 21 Sep 2020 11:48:18 -0700 Subject: [PATCH 06/24] Update routesync.cpp --- fpmsyncd/routesync.cpp | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index 24b03cd9cc..63188fe25c 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -73,7 +73,8 @@ char *RouteSync::prefix_mac2str(char *mac, char *buf, int size) void RouteSync::netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len) { - while (RTA_OK(rta, len)) { + while (RTA_OK(rta, len)) + { if (rta->rta_type <= max) tb[rta->rta_type] = rta; rta = RTA_NEXT(rta, len); @@ -158,10 +159,12 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, if (tb[RTA_GATEWAY]) gate = RTA_DATA(tb[RTA_GATEWAY]); - if (h->nlmsg_type == RTM_NEWROUTE) { - if (!tb[RTA_MULTIPATH]) { + if (h->nlmsg_type == RTM_NEWROUTE) + { + if (!tb[RTA_MULTIPATH]) + { gw_af = AF_INET; // default value - if (gate) + if (gate) { if (RTA_PAYLOAD(tb[RTA_GATEWAY]) <= IPV4_MAX_BYTE) { @@ -200,7 +203,7 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, { parse_encap(tb[RTA_ENCAP], encap_value, rmac, vlan); } - SWSS_LOG_NOTICE("Rx MsgType:%d Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%d", h->nlmsg_type, + 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); if (encap_value == 0 || vlan == 0 @@ -218,13 +221,16 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, struct rtnexthop *rtnh = (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); len = (int)RTA_PAYLOAD(tb[RTA_MULTIPATH]); - for (;;) { + for (;;) + { uint16_t encap = 0; if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) - break; + break; + gate = 0; - if (rtnh->rtnh_len > sizeof(*rtnh)) { + if (rtnh->rtnh_len > sizeof(*rtnh)) + { memset(subtb, 0, sizeof(subtb)); netlink_parse_rtattr(subtb, RTA_MAX, RTNH_DATA(rtnh), @@ -272,7 +278,7 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, { parse_encap(subtb[RTA_ENCAP], encap_value, rmac, vlan); } - SWSS_LOG_NOTICE("Multipath Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%d", + SWSS_LOG_DEBUG("Multipath Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%d", nexthopaddr, encap, encap_value, rmac.c_str(), vlan); if (encap_value == 0 || vlan == 0 @@ -325,7 +331,8 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) if (rtm->rtm_family == AF_INET) { - if (rtm->rtm_dst_len > IPV4_MAX_BITLEN) { + if (rtm->rtm_dst_len > IPV4_MAX_BITLEN) + { return; } memcpy(dstaddr, dest, IPV4_MAX_BYTE); @@ -333,14 +340,15 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) } else if (rtm->rtm_family == AF_INET6) { - if (rtm->rtm_dst_len > IPV6_MAX_BITLEN) { + if (rtm->rtm_dst_len > IPV6_MAX_BITLEN) + { return; } memcpy(dstaddr, dest, IPV6_MAX_BYTE); dst_len = rtm->rtm_dst_len; } - SWSS_LOG_INFO("Rx MsgType:%d Family:%d Prefix:%s/%d", h->nlmsg_type, rtm->rtm_family, + SWSS_LOG_DEBUG("Rx MsgType:%d Family:%d Prefix:%s/%d", h->nlmsg_type, rtm->rtm_family, inet_ntop(rtm->rtm_family, dstaddr, buf, MAX_ADDR_SIZE), dst_len); /* Table corresponding to route. */ @@ -465,7 +473,7 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) if (!warmRestartInProgress) { m_routeTable.set(destipprefix, fvVector); - SWSS_LOG_NOTICE("RouteTable set msg: %s vtep:%s vni:%s mac:%s intf:%s", + SWSS_LOG_DEBUG("RouteTable set msg: %s vtep:%s vni:%s mac:%s intf:%s", destipprefix, nexthops.c_str(), vni_list.c_str(), mac_list.c_str(), intf_list.c_str()); } @@ -495,7 +503,8 @@ void RouteSync::onMsgRaw(struct nlmsghdr *h) return; /* Length validity. */ len = (int)(h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg))); - if (len < 0) { + if (len < 0) + { SWSS_LOG_INFO("%s: Message received from netlink is of a broken size %d %zu", __PRETTY_FUNCTION__, h->nlmsg_len, (size_t)NLMSG_LENGTH(sizeof(struct ndmsg))); From d94dcdca32f4e5d75506b1cf10a9df47d52a90b9 Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 21 Sep 2020 12:03:00 -0700 Subject: [PATCH 07/24] Update routesync.cpp --- fpmsyncd/routesync.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index 63188fe25c..8f00076abb 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -380,7 +380,7 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) snprintf(destipprefix + strlen(destipprefix), sizeof(destipprefix) - strlen(destipprefix), "%s/%u", inet_ntop(rtm->rtm_family, dstaddr, buf, MAX_ADDR_SIZE), dst_len); - SWSS_LOG_NOTICE("Receive route message dest ip prefix: %s Op:%s", + SWSS_LOG_DEBUG("Receive route message dest ip prefix: %s Op:%s", destipprefix, nlmsg_type == RTM_NEWROUTE ? "add":"del"); From a51d0792cb6d56916942cd9e5d2cd202ee810b4d Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Thu, 24 Sep 2020 11:07:02 -0700 Subject: [PATCH 08/24] Update routesync.cpp This API is delete from common library, so delete the call as well --- fpmsyncd/routesync.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index 8f00076abb..dd216b05d0 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -667,10 +667,6 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) if (!warmRestartInProgress) { - /*Delete vni & router_mac fields to handle route update scenario - * This operation is idempotent and generate only one event to consumer*/ - m_routeTable.hdel(destipprefix, "vni_label"); - m_routeTable.hdel(destipprefix, "router_mac"); m_routeTable.set(destipprefix, fvVector); SWSS_LOG_DEBUG("RouteTable set msg: %s %s %s", destipprefix, nexthops.c_str(), ifnames.c_str()); From 23b06abe6d884a74ab69d7152e5b0e366400ac7a Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 5 Oct 2020 16:20:03 -0700 Subject: [PATCH 09/24] Update fpmlink.cpp --- fpmsyncd/fpmlink.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index d554f9b7f4..e6d4fce54a 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -39,7 +39,7 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) return 0; } - memset(tb, 0, sizeof tb); + memset(tb, 0, sizeof(tb)); netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); if (!tb[RTA_MULTIPATH]) From 9ac6f05d42197c914185108101147f42d5d1f29a Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 5 Oct 2020 16:57:17 -0700 Subject: [PATCH 10/24] Update routesync.cpp Address the review comments --- fpmsyncd/routesync.cpp | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index dd216b05d0..c9d29e1e84 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -70,17 +70,6 @@ char *RouteSync::prefix_mac2str(char *mac, char *buf, int size) return ptr; } -void RouteSync::netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, - int len) -{ - while (RTA_OK(rta, len)) - { - if (rta->rta_type <= max) - tb[rta->rta_type] = rta; - rta = RTA_NEXT(rta, len); - } -} - /** * netlink_parse_rtattr_nested() - Parses a nested route attribute * @tb: Pointer to array for storing rtattr in. @@ -285,13 +274,16 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) return false; - if(ecmp_count) + if(gate) { - getEvpnNextHopSep(nexthops, vni_list, mac_list, intf_list); - } + if(ecmp_count) + { + getEvpnNextHopSep(nexthops, vni_list, mac_list, intf_list); + } - getEvpnNextHopGwIf(nexthopaddr, encap_value, nexthops, vni_list, mac_list, intf_list, rmac, vlan); - ecmp_count++; + getEvpnNextHopGwIf(nexthopaddr, encap_value, nexthops, vni_list, mac_list, intf_list, rmac, vlan); + ecmp_count++; + } } if (rtnh->rtnh_len == 0) @@ -505,7 +497,7 @@ void RouteSync::onMsgRaw(struct nlmsghdr *h) len = (int)(h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg))); if (len < 0) { - SWSS_LOG_INFO("%s: Message received from netlink is of a broken size %d %zu", + SWSS_LOG_ERROR("%s: Message received from netlink is of a broken size %d %zu", __PRETTY_FUNCTION__, h->nlmsg_len, (size_t)NLMSG_LENGTH(sizeof(struct ndmsg))); return; From 8d383bbf4c319af950d6207807ca7da2ef9b630a Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 5 Oct 2020 16:59:40 -0700 Subject: [PATCH 11/24] Update routesync.h Updated based on review comments --- fpmsyncd/routesync.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fpmsyncd/routesync.h b/fpmsyncd/routesync.h index 4943d6e3c2..5c8852ab1e 100644 --- a/fpmsyncd/routesync.h +++ b/fpmsyncd/routesync.h @@ -10,6 +10,10 @@ using namespace std; +/* Parse the Raw netlink msg */ +extern void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, + int len); + namespace swss { class RouteSync : public NetMsg @@ -37,10 +41,6 @@ class RouteSync : public NetMsg /* Handle regular route (include VRF route) */ void onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf); - /* Parse the Raw netlink msg */ - void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, - int len); - void parse_encap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan); void netlink_parse_rtattr_nested(struct rtattr **tb, int max, From 3c29e285c0f0c0b2195bb1b8d013fca92a90d29d Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Mon, 5 Oct 2020 17:03:32 -0700 Subject: [PATCH 12/24] Update routesync.cpp Updated based on the comment --- fpmsyncd/routesync.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index c9d29e1e84..b7d65f844e 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -313,7 +313,7 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) rtm = (struct rtmsg *)NLMSG_DATA(h); /* Parse attributes and extract fields of interest. */ - memset(tb, 0, sizeof tb); + memset(tb, 0, sizeof(tb)); netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); if (tb[RTA_DST]) From fb50f0368c00d7a556aa7ebaf0d6ee4b19b5d97c Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Thu, 8 Oct 2020 14:40:46 -0700 Subject: [PATCH 13/24] Fix all the review comment from Prince --- fpmsyncd/fpmlink.cpp | 33 ++++++++++++++++------ fpmsyncd/routesync.cpp | 63 ++++++++++++++++++++++++++++-------------- fpmsyncd/routesync.h | 6 ++-- 3 files changed, 71 insertions(+), 31 deletions(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index e6d4fce54a..1af2dc8426 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -15,7 +15,9 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, while (RTA_OK(rta, len)) { if (rta->rta_type <= max) + { tb[rta->rta_type] = rta; + } rta = RTA_NEXT(rta, len); } } @@ -29,14 +31,15 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) rtm = (struct rtmsg *)NLMSG_DATA(h); - if (h->nlmsg_type != RTM_NEWROUTE - && h->nlmsg_type != RTM_DELROUTE) - return 0; + if (h->nlmsg_type != RTM_NEWROUTE && h->nlmsg_type != RTM_DELROUTE) + { + return false; + } len = (int)(h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg))); if (len < 0) { - return 0; + return false; } memset(tb, 0, sizeof(tb)); @@ -45,7 +48,9 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) if (!tb[RTA_MULTIPATH]) { if (tb[RTA_ENCAP_TYPE]) + { encap_type = *(short *)RTA_DATA(tb[RTA_ENCAP_TYPE]); + } } else { @@ -57,9 +62,10 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) for (;;) { - if (len < (int)sizeof(*rtnh) - || rtnh->rtnh_len > len) + if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) + { break; + } if (rtnh->rtnh_len > sizeof(*rtnh)) { @@ -74,7 +80,9 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) } if (rtnh->rtnh_len == 0) + { break; + } len -= NLMSG_ALIGN(rtnh->rtnh_len); rtnh = RTNH_NEXT(rtnh); @@ -84,9 +92,11 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) SWSS_LOG_INFO("Rx MsgType:%d Encap:%d", h->nlmsg_type, encap_type); if (encap_type > 0) - return 1; + { + return true; + } - return 0; + return false; } FpmLink::FpmLink(unsigned short port) : @@ -204,6 +214,12 @@ uint64_t FpmLink::readData() nlmsghdr *nl_hdr = (nlmsghdr *)fpm_msg_data(hdr); + /* + * EVPN Type5 Add Routes need to be process in Raw mode as they contain + * RMAC, VLAN and L3VNI information. + * Where as all other route will be using rtnl api to extract information + * from the netlink msg. + * */ isRaw = isRawProcessing(nl_hdr); nl_msg *msg = nlmsg_convert(nl_hdr); @@ -216,6 +232,7 @@ uint64_t FpmLink::readData() if (isRaw) { + /* EVPN Type5 Add route processing */ NetDispatcher::getInstance().onNetlinkMessageRaw(msg); } else diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index b7d65f844e..8891a0f602 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -54,14 +54,18 @@ RouteSync::RouteSync(RedisPipeline *pipeline) : rtnl_link_alloc_cache(m_nl_sock, AF_UNSPEC, &m_link_cache); } -char *RouteSync::prefix_mac2str(char *mac, char *buf, int size) +char *RouteSync::prefixMac2Str(char *mac, char *buf, int size) { char *ptr = buf; if (!mac) + { return NULL; + } if (!buf) + { return NULL; + } snprintf(ptr, (ETHER_ADDR_STRLEN), "%02x:%02x:%02x:%02x:%02x:%02x", (uint8_t)mac[0], (uint8_t)mac[1], @@ -71,41 +75,42 @@ char *RouteSync::prefix_mac2str(char *mac, char *buf, int size) } /** - * netlink_parse_rtattr_nested() - Parses a nested route attribute + * parseRtAttrNested() - Parses a nested route attribute * @tb: Pointer to array for storing rtattr in. * @max: Max number to store. * @rta: Pointer to rtattr to look for nested items in. */ -void RouteSync::netlink_parse_rtattr_nested(struct rtattr **tb, int max, +void RouteSync::parseRtAttrNested(struct rtattr **tb, int max, struct rtattr *rta) { netlink_parse_rtattr(tb, max, (struct rtattr *)RTA_DATA(rta), (int)RTA_PAYLOAD(rta)); } /** - * @parse_encap() - Parses encapsulated attributes + * @parseEncap() - Parses encapsulated attributes * @tb: Pointer to rtattr to look for nested items in. * @labels: Pointer to store vni in. * * Return: void. */ -void RouteSync::parse_encap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan) +void RouteSync::parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan) { struct rtattr *tb_encap[3] = {0}; char mac_buf[MAX_ADDR_SIZE+1]; char mac_val[MAX_ADDR_SIZE+1]; - netlink_parse_rtattr_nested(tb_encap, 3, tb); + 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_DEBUG("Rx MAC %s VNI %d Vlan %d", - prefix_mac2str(mac_buf, mac_val, ETHER_ADDR_STRLEN), encap_value, vlan); + SWSS_LOG_INFO("Rx MAC %s VNI %d Vlan %d", + prefixMac2Str(mac_buf, mac_val, ETHER_ADDR_STRLEN), encap_value, vlan); rmac = mac_val; return; } + void RouteSync::getEvpnNextHopSep(string& nexthops, string& vni_list, string& mac_list, string& intf_list) { @@ -185,19 +190,22 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, inet_ntop(gw_af, gateaddr, nexthopaddr, MAX_ADDR_SIZE); if (tb[RTA_ENCAP_TYPE]) + { encap = *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE]); + } if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE] && (*(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE]) == NH_ENCAP_VXLAN)) { - parse_encap(tb[RTA_ENCAP], encap_value, rmac, vlan); + parseEncap(tb[RTA_ENCAP], encap_value, rmac, vlan); } 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); - if (encap_value == 0 || vlan == 0 - || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) + if (encap_value == 0 || vlan == 0 || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) + { return false; + } getEvpnNextHopGwIf(nexthopaddr, encap_value, nexthops, vni_list, mac_list, intf_list, rmac, vlan); } @@ -213,9 +221,10 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, for (;;) { uint16_t encap = 0; - if (len < (int)sizeof(*rtnh) - || rtnh->rtnh_len > len) + if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) + { break; + } gate = 0; if (rtnh->rtnh_len > sizeof(*rtnh)) @@ -226,7 +235,9 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, (int)(rtnh->rtnh_len - sizeof(*rtnh))); if (subtb[RTA_GATEWAY]) + { gate = RTA_DATA(subtb[RTA_GATEWAY]); + } if (gate) { @@ -260,23 +271,26 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, inet_ntop(gw_af, gateaddr, nexthopaddr, MAX_ADDR_SIZE); if (subtb[RTA_ENCAP_TYPE]) + { encap = *(uint16_t *)RTA_DATA(subtb[RTA_ENCAP_TYPE]); + } if (subtb[RTA_ENCAP] && subtb[RTA_ENCAP_TYPE] && (*(uint16_t *)RTA_DATA(subtb[RTA_ENCAP_TYPE]) == NH_ENCAP_VXLAN)) { - parse_encap(subtb[RTA_ENCAP], encap_value, rmac, vlan); + parseEncap(subtb[RTA_ENCAP], encap_value, rmac, vlan); } SWSS_LOG_DEBUG("Multipath Nexthop:%s encap:%d encap_value:%d rmac:%s vlan:%d", nexthopaddr, encap, encap_value, rmac.c_str(), vlan); - if (encap_value == 0 || vlan == 0 - || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) + if (encap_value == 0 || vlan == 0 || MacAddress(rmac) == MacAddress("00:00:00:00:00:00")) + { return false; + } - if(gate) + if (gate) { - if(ecmp_count) + if (ecmp_count) { getEvpnNextHopSep(nexthops, vni_list, mac_list, intf_list); } @@ -287,7 +301,9 @@ bool RouteSync::getEvpnNextHop(struct nlmsghdr *h, int received_bytes, } if (rtnh->rtnh_len == 0) + { break; + } len -= NLMSG_ALIGN(rtnh->rtnh_len); rtnh = RTNH_NEXT(rtnh); @@ -317,9 +333,13 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); if (tb[RTA_DST]) + { dest = RTA_DATA(tb[RTA_DST]); + } else + { dest = anyaddr; + } if (rtm->rtm_family == AF_INET) { @@ -345,9 +365,13 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) /* Table corresponding to route. */ if (tb[RTA_TABLE]) + { vrf_index = *(int *)RTA_DATA(tb[RTA_TABLE]); + } else + { vrf_index = rtm->rtm_table; + } if (vrf_index) { @@ -372,7 +396,7 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) snprintf(destipprefix + strlen(destipprefix), sizeof(destipprefix) - strlen(destipprefix), "%s/%u", inet_ntop(rtm->rtm_family, dstaddr, buf, MAX_ADDR_SIZE), dst_len); - SWSS_LOG_DEBUG("Receive route message dest ip prefix: %s Op:%s", + SWSS_LOG_INFO("Receive route message dest ip prefix: %s Op:%s", destipprefix, nlmsg_type == RTM_NEWROUTE ? "add":"del"); @@ -404,7 +428,6 @@ void RouteSync::onEvpnRouteMsg(struct nlmsghdr *h, int len) } else if (nlmsg_type != RTM_NEWROUTE) { - SWSS_LOG_NOTICE("Unknown message-type: %d for %s", nlmsg_type, destipprefix); return; } diff --git a/fpmsyncd/routesync.h b/fpmsyncd/routesync.h index 5c8852ab1e..b122a85b66 100644 --- a/fpmsyncd/routesync.h +++ b/fpmsyncd/routesync.h @@ -41,12 +41,12 @@ class RouteSync : public NetMsg /* Handle regular route (include VRF route) */ void onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf); - void parse_encap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan); + void parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rmac, uint32_t &vlan); - void netlink_parse_rtattr_nested(struct rtattr **tb, int max, + void parseRtAttrNested(struct rtattr **tb, int max, struct rtattr *rta); - char *prefix_mac2str(char *mac, char *buf, int size); + char *prefixMac2Str(char *mac, char *buf, int size); /* Handle prefix route */ From 9992702973a9dab6929640a5a685d3266fa394ad Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Thu, 15 Oct 2020 19:29:13 -0700 Subject: [PATCH 14/24] Updated by directly calling the raw message process as per review comment from Qi. --- fpmsyncd/fpmlink.cpp | 5 ++++- fpmsyncd/fpmsyncd.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index 1af2dc8426..1157d4c11c 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -5,10 +5,13 @@ #include "netmsg.h" #include "netdispatcher.h" #include "fpmsyncd/fpmlink.h" +#include "fpmsyncd/routesync.h" using namespace swss; using namespace std; +extern RouteSync *g_routesync; + void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len) { @@ -233,7 +236,7 @@ uint64_t FpmLink::readData() if (isRaw) { /* EVPN Type5 Add route processing */ - NetDispatcher::getInstance().onNetlinkMessageRaw(msg); + g_routesync->onMsgRaw(nl_hdr); } else { diff --git a/fpmsyncd/fpmsyncd.cpp b/fpmsyncd/fpmsyncd.cpp index 5e0dfd6a72..3c112f3573 100644 --- a/fpmsyncd/fpmsyncd.cpp +++ b/fpmsyncd/fpmsyncd.cpp @@ -12,6 +12,7 @@ using namespace std; using namespace swss; +RouteSync *g_routesync = NULL; /* * Default warm-restart timer interval for routing-stack app. To be used only if @@ -50,14 +51,13 @@ int main(int argc, char **argv) DBConnector db("APPL_DB", 0); RedisPipeline pipeline(&db); RouteSync sync(&pipeline); + g_routesync = &sync; DBConnector stateDb("STATE_DB", 0); Table bgpStateTable(&stateDb, STATE_BGP_TABLE_NAME); NetDispatcher::getInstance().registerMessageHandler(RTM_NEWROUTE, &sync); NetDispatcher::getInstance().registerMessageHandler(RTM_DELROUTE, &sync); - NetDispatcher::getInstance().registerRawMessageHandler(RTM_NEWROUTE, &sync); - NetDispatcher::getInstance().registerRawMessageHandler(RTM_DELROUTE, &sync); while (true) { From 95a50d36ee4780f1b2d7e6b1eb3d318bc9642616 Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Thu, 15 Oct 2020 19:33:54 -0700 Subject: [PATCH 15/24] Fix space --- fpmsyncd/fpmlink.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index 1157d4c11c..bf8c0b4022 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -236,7 +236,7 @@ uint64_t FpmLink::readData() if (isRaw) { /* EVPN Type5 Add route processing */ - g_routesync->onMsgRaw(nl_hdr); + g_routesync->onMsgRaw(nl_hdr); } else { From 1cacae79a5e3ede19dfdcfdfaad572769efab8c8 Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Fri, 16 Oct 2020 16:31:01 -0700 Subject: [PATCH 16/24] Updated based on new review comments --- fpmsyncd/fpmlink.cpp | 10 ++++------ fpmsyncd/fpmlink.h | 8 +++++++- fpmsyncd/fpmsyncd.cpp | 5 +---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/fpmsyncd/fpmlink.cpp b/fpmsyncd/fpmlink.cpp index bf8c0b4022..2a2e8b935d 100644 --- a/fpmsyncd/fpmlink.cpp +++ b/fpmsyncd/fpmlink.cpp @@ -5,13 +5,10 @@ #include "netmsg.h" #include "netdispatcher.h" #include "fpmsyncd/fpmlink.h" -#include "fpmsyncd/routesync.h" using namespace swss; using namespace std; -extern RouteSync *g_routesync; - void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len) { @@ -102,13 +99,14 @@ bool FpmLink::isRawProcessing(struct nlmsghdr *h) return false; } -FpmLink::FpmLink(unsigned short port) : +FpmLink::FpmLink(RouteSync *rsync, unsigned short port) : MSG_BATCH_SIZE(256), m_bufSize(FPM_MAX_MSG_LEN * MSG_BATCH_SIZE), m_messageBuffer(NULL), m_pos(0), m_connected(false), - m_server_up(false) + m_server_up(false), + m_routesync(rsync) { struct sockaddr_in addr; int true_val = 1; @@ -236,7 +234,7 @@ uint64_t FpmLink::readData() if (isRaw) { /* EVPN Type5 Add route processing */ - g_routesync->onMsgRaw(nl_hdr); + processRawMsg(nl_hdr); } else { diff --git a/fpmsyncd/fpmlink.h b/fpmsyncd/fpmlink.h index 297a0474f3..6cceef34ea 100644 --- a/fpmsyncd/fpmlink.h +++ b/fpmsyncd/fpmlink.h @@ -13,13 +13,14 @@ #include "selectable.h" #include "fpm/fpm.h" +#include "fpmsyncd/routesync.h" namespace swss { class FpmLink : public Selectable { public: const int MSG_BATCH_SIZE; - FpmLink(unsigned short port = FPM_DEFAULT_PORT); + FpmLink(RouteSync *rsync, unsigned short port = FPM_DEFAULT_PORT); virtual ~FpmLink(); /* Wait for connection (blocking) */ @@ -33,8 +34,13 @@ class FpmLink : public Selectable { }; bool isRawProcessing(struct nlmsghdr *h); + void processRawMsg(struct nlmsghdr *h) + { + m_routesync->onMsgRaw(h); + }; private: + RouteSync *m_routesync; unsigned int m_bufSize; char *m_messageBuffer; unsigned int m_pos; diff --git a/fpmsyncd/fpmsyncd.cpp b/fpmsyncd/fpmsyncd.cpp index 3c112f3573..9f5c9e1a65 100644 --- a/fpmsyncd/fpmsyncd.cpp +++ b/fpmsyncd/fpmsyncd.cpp @@ -12,8 +12,6 @@ using namespace std; using namespace swss; -RouteSync *g_routesync = NULL; - /* * Default warm-restart timer interval for routing-stack app. To be used only if * no explicit value has been defined in configuration. @@ -51,7 +49,6 @@ int main(int argc, char **argv) DBConnector db("APPL_DB", 0); RedisPipeline pipeline(&db); RouteSync sync(&pipeline); - g_routesync = &sync; DBConnector stateDb("STATE_DB", 0); Table bgpStateTable(&stateDb, STATE_BGP_TABLE_NAME); @@ -63,7 +60,7 @@ int main(int argc, char **argv) { try { - FpmLink fpm; + FpmLink fpm(&sync); Select s; SelectableTimer warmStartTimer(timespec{0, 0}); // Before eoiu flags detected, check them periodically. It also stop upon detection of reconciliation done. From 67187a4909eeaa5d97de6aa45e9cd226e866ceec Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Fri, 30 Oct 2020 11:51:13 -0700 Subject: [PATCH 17/24] VS test run might be failing due to this. --- fpmsyncd/routesync.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index e405f06f30..7c92224352 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -599,14 +599,14 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) dip = rtnl_route_get_dst(route_obj); nl_addr2str(dip, destipprefix + strlen(destipprefix), MAX_ADDR_SIZE); - +#if 0 /* Full mask route append prefix length, or else resync cannot match. */ if (nl_addr_get_prefixlen(dip) == (8 * nl_addr_get_len(dip))) { snprintf(destipprefix + strlen(destipprefix), sizeof(destipprefix) - strlen(destipprefix), "/%u", nl_addr_get_prefixlen(dip)); } SWSS_LOG_DEBUG("Receive new route message dest ip prefix: %s", destipprefix); - +#endif /* * Upon arrival of a delete msg we could either push the change right away, * or we could opt to defer it if we are going through a warm-reboot cycle. From b7c6a326d09c7a77f531f6f74b93e31d924a68b3 Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Tue, 3 Nov 2020 13:11:40 -0800 Subject: [PATCH 18/24] Removing un-used code --- fpmsyncd/routesync.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index 7c92224352..bdbbe004f8 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -599,14 +599,7 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) dip = rtnl_route_get_dst(route_obj); nl_addr2str(dip, destipprefix + strlen(destipprefix), MAX_ADDR_SIZE); -#if 0 - /* Full mask route append prefix length, or else resync cannot match. */ - if (nl_addr_get_prefixlen(dip) == (8 * nl_addr_get_len(dip))) - { - snprintf(destipprefix + strlen(destipprefix), sizeof(destipprefix) - strlen(destipprefix), "/%u", nl_addr_get_prefixlen(dip)); - } - SWSS_LOG_DEBUG("Receive new route message dest ip prefix: %s", destipprefix); -#endif + /* * Upon arrival of a delete msg we could either push the change right away, * or we could opt to defer it if we are going through a warm-reboot cycle. From b90c15e28681d9f6d8e6b67fa9a4e40097878962 Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Tue, 28 Apr 2020 14:21:12 -0700 Subject: [PATCH 19/24] [FDBSYNCD] Added support for FDBSYNCD as described in the PR Azure/SONiC#437 --- .gitignore | 1 + Makefile.am | 2 +- configure.ac | 1 + fdbsyncd/Makefile.am | 17 ++ fdbsyncd/fdbsync.cpp | 604 ++++++++++++++++++++++++++++++++++++++++++ fdbsyncd/fdbsync.h | 128 +++++++++ fdbsyncd/fdbsyncd.cpp | 95 +++++++ 7 files changed, 847 insertions(+), 1 deletion(-) create mode 100644 fdbsyncd/Makefile.am create mode 100644 fdbsyncd/fdbsync.cpp create mode 100644 fdbsyncd/fdbsync.h create mode 100644 fdbsyncd/fdbsyncd.cpp diff --git a/.gitignore b/.gitignore index f793ab78d9..d020b57058 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ gearsyncd/gearsyncd mclagsyncd/mclagsyncd natsyncd/natsyncd neighsyncd/neighsyncd +fdbsyncd/fdbsyncd orchagent/orchagent orchagent/orchagent_restart_check orchagent/routeresync diff --git a/Makefile.am b/Makefile.am index f2a71687db..da3dcb319f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = fpmsyncd neighsyncd portsyncd mclagsyncd natsyncd orchagent swssconfig cfgmgr tests gearsyncd +SUBDIRS = fpmsyncd neighsyncd fdbsyncd portsyncd mclagsyncd natsyncd orchagent swssconfig cfgmgr tests gearsyncd if HAVE_LIBTEAM SUBDIRS += teamsyncd tlm_teamd diff --git a/configure.ac b/configure.ac index 11c793201d..d7816b6f17 100644 --- a/configure.ac +++ b/configure.ac @@ -92,6 +92,7 @@ AC_CONFIG_FILES([ fpmsyncd/Makefile neighsyncd/Makefile gearsyncd/Makefile + fdbsyncd/Makefile natsyncd/Makefile portsyncd/Makefile teamsyncd/Makefile diff --git a/fdbsyncd/Makefile.am b/fdbsyncd/Makefile.am new file mode 100644 index 0000000000..9b5228359d --- /dev/null +++ b/fdbsyncd/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/warmrestart -I ../nlapi/include -I ../cfgmgr +NLAPI_LIBS = ../nlapi/libnlapi.a + +bin_PROGRAMS = fdbsyncd + +if DEBUG +DBGFLAGS = -ggdb -DDEBUG +else +DBGFLAGS = -g +endif + +fdbsyncd_SOURCES = fdbsyncd.cpp fdbsync.cpp $(top_srcdir)/warmrestart/warmRestartAssist.cpp + +fdbsyncd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(COV_CFLAGS) +fdbsyncd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(COV_CFLAGS) +fdbsyncd_LDADD = -lnl-3 -lnl-route-3 -lswsscommon $(NLAPI_LIBS) $(COV_LDFLAGS) + diff --git a/fdbsyncd/fdbsync.cpp b/fdbsyncd/fdbsync.cpp new file mode 100644 index 0000000000..578ced048d --- /dev/null +++ b/fdbsyncd/fdbsync.cpp @@ -0,0 +1,604 @@ +#include +#include +#include +#include +#include +#include + +#include "logger.h" +#include "dbconnector.h" +#include "producerstatetable.h" +#include "ipaddress.h" +#include "netmsg.h" +#include "macaddress.h" +#include "exec.h" +#include "shellcmd.h" +#include "fdbsync.h" +#include "warm_restart.h" +#include "nlapi.h" +#include "errno.h" + +using namespace std; +using namespace swss; + +#define VXLAN_BR_IF_NAME_PREFIX "Brvxlan" + +FdbSync::FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb) : + m_fdbTable(pipelineAppDB, APP_VXLAN_FDB_TABLE_NAME), + m_imetTable(pipelineAppDB, APP_EVPN_REMOTE_VNI_TABLE_NAME), + m_stateFdbRestoreTable(stateDb, STATE_EVPN_FDB_RESTORE_TABLE_NAME), + m_fdbStateTable(stateDb, STATE_FDB_TABLE_NAME) +{ + m_AppRestartAssist = new AppRestartAssist(pipelineAppDB, "fdbsyncd", "swss", DEFAULT_FDBSYNC_WARMSTART_TIMER); + if (m_AppRestartAssist) + { + m_AppRestartAssist->registerAppTable(APP_VXLAN_FDB_TABLE_NAME, &m_fdbTable); + m_AppRestartAssist->registerAppTable(APP_EVPN_REMOTE_VNI_TABLE_NAME, &m_imetTable); + } +} + +FdbSync::~FdbSync() +{ + if (m_AppRestartAssist) + { + delete m_AppRestartAssist; + } +} + +// Check if neighbor table is restored in kernel +bool FdbSync::isFdbRestoreDone() +{ + string value; + + m_stateFdbRestoreTable.hget("Flags", "restored", value); + if (value == "true") + { + SWSS_LOG_NOTICE("neighbor table restore to kernel is done"); + return true; + } + return true; +} + +void FdbSync::processStateFdb() +{ + struct fdb_info info; + std::deque entries; + + m_fdbStateTable.pops(entries); + + int count =0 ; + for (auto entry: entries) + { + memset(&info, 0, sizeof(struct fdb_info)); + count++; + std::string key = kfvKey(entry); + std::string op = kfvOp(entry); + + std::size_t delimiter = key.find_first_of(":"); + auto vlan_name = key.substr(0, delimiter); + auto mac_address = key.substr(delimiter+1); + + info.vid = (unsigned int) stoi(vlan_name.substr(4)); + memcpy(info.mac, mac_address.c_str(),mac_address.length()); + + if(op == "SET") + info.op_type = FDB_OPER_ADD ; + else + info.op_type = FDB_OPER_DEL ; + + SWSS_LOG_NOTICE("FDBSYNCD STATE FDB updates key=%s, operation=%s\n", key.c_str(), op.c_str()); + + for (auto i : kfvFieldsValues(entry)) + { + SWSS_LOG_INFO(" FDBSYNCD STATE FDB updates : " + "FvFiels %s, FvValues: %s \n", fvField(i).c_str(), fvValue(i).c_str()); + + if(fvField(i) == "port") + { + memcpy(info.port_name, fvValue(i).c_str(), fvValue(i).length()); + } + + if(fvField(i) == "type") + { + if(fvValue(i) == "dynamic") + info.type = FDB_TYPE_DYNAMIC; + else if (fvValue(i) == "static") + info.type = FDB_TYPE_STATIC; + } + } + macUpdateStateDB(&info); + } +} + +void FdbSync::macAddSrcDB(struct fdb_info *info) +{ + string key = "Vlan" + to_string(info->vid) + ":" + info->mac; + fdbmac[key].port_name = info->port_name; + fdbmac[key].type = info->type; + + return; +} + +bool FdbSync::macCheckSrcDB(struct fdb_info *info) +{ + string key = "Vlan" + to_string(info->vid) + ":" + info->mac; + if (fdbmac.find(key) != fdbmac.end()) + { + SWSS_LOG_NOTICE("DEL_KEY %s ", key.c_str()); + return true; + } + + return false; +} + +void FdbSync::macDelVxlanEntry(string auxkey, struct fdb_info *info) +{ + std::string vtep = m_mac[auxkey].vtep; + + const std::string cmds = std::string("") + + " bridge fdb del " + info->mac + " dev " + + m_mac[auxkey].ifname + " dst " + vtep + " vlan " + to_string(info->vid); + + std::string res; + int ret = swss::exec(cmds, res); + if (ret != 0) + { + SWSS_LOG_INFO("Failed cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + } + + SWSS_LOG_NOTICE("Success cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + + return; +} + +void FdbSync::macUpdateStateDB(struct fdb_info *info) +{ + char *op; + char *type; + string port_name = ""; + string key = "Vlan" + to_string(info->vid) + ":" + info->mac; + short fdb_type; /*dynamic or static*/ + + if (info->op_type == FDB_OPER_ADD) + { + macAddSrcDB(info); + op = "add"; + port_name+= info->port_name; + fdb_type = info->type; + /* Check if this vlan+key is also learned by vxlan neighbor then delete learned on */ + if (m_mac.find(key) != m_mac.end()) + { + op = "replace"; + macDelVxlanEntry(key, info); + SWSS_LOG_INFO("Local learn event deleting from VXLAN table DEL_KEY %s", key.c_str()); + macDelVxlan(key); + } + } + else + { + op = "del"; + if (macCheckSrcDB(info) == false) + { + return; + } + port_name+= fdbmac[key].port_name; + fdb_type = fdbmac[key].type; + fdbmac.erase(key); + } + + if (fdb_type == FDB_TYPE_DYNAMIC) + { + type = "dynamic"; + } + else + { + type = "static"; + } + + const std::string cmds = std::string("") + + " bridge fdb " + op + " " + info->mac + " dev " + + port_name + " master " + type + " vlan " + to_string(info->vid); + + std::string res; + int ret = swss::exec(cmds, res); + + SWSS_LOG_NOTICE("cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + + return; +} + +void FdbSync::macRefreshStateDB(int vlan, string kmac) +{ + string key = "Vlan" + to_string(vlan) + ":" + kmac; + char *type; + string port_name = ""; + + SWSS_LOG_NOTICE("Refreshing Vlan:%d MAC route MAC:%s Key %s", vlan, kmac.c_str(), key.c_str()); + + if (fdbmac.find(key)!=fdbmac.end()) + { + port_name+= fdbmac[key].port_name; + if (port_name.empty()) + { + SWSS_LOG_INFO("Port name not present MAC route Key:%s", key.c_str()); + return; + } + + SWSS_LOG_INFO("Refreshing MAC route MAC:%s Key %s Port %s", kmac.c_str(), key.c_str(), port_name.c_str()); + + if (fdbmac[key].type == FDB_TYPE_DYNAMIC) + { + type = "dynamic"; + } + else + { + type = "static"; + } + + const std::string cmds = std::string("") + + " bridge fdb " + "add" + " " + kmac + " dev " + + port_name + " master " + type + " vlan " + to_string(vlan); + + std::string res; + int ret = swss::exec(cmds, res); + if (ret != 0) + { + SWSS_LOG_INFO("Failed cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + } + + SWSS_LOG_NOTICE("Refreshing cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + } + return; +} + +bool FdbSync::checkImetExit(string key, uint32_t vni) +{ + if (imet_route[key].redist_add_status == true) + { + SWSS_LOG_DEBUG("IMET exist key:%s Vni:%d", key.c_str(), vni); + return false; + } + imet_route[key].vni = vni; + return true; +} + +bool FdbSync::checkDelImet(string key, uint32_t vni) +{ + int ret = true; + + SWSS_LOG_DEBUG("Del IMET key:%s Vni:%d", key.c_str(), vni); + if (imet_route.find(key) != imet_route.end()) + { + SWSS_LOG_DEBUG("IMET found key:%s Vni:%d", key.c_str(), vni); + if (imet_route[key].redist_add_status == false) + { + SWSS_LOG_DEBUG("IMET found key:%s Vni:%d, it should have not happened", key.c_str(), vni); + ret = false; + } + imet_route.erase(key); + } + return ret; +} + +void FdbSync::imetAddRoute(struct in_addr vtep, string vlan_str, uint32_t vni) +{ + string vlan_id = "Vlan" + vlan_str; + string key = vlan_id + ":" + inet_ntoa(vtep); + + if (!checkImetExit(key, vni)) + return; + + SWSS_LOG_NOTICE("%sIMET Add route key:%s vtep:%s %s", + m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "", + key.c_str(), inet_ntoa(vtep), vlan_id.c_str()); + + std::vector fvVector; + FieldValueTuple f("vni", to_string(vni)); + fvVector.push_back(f); + + imet_route[key].redist_add_status = true; + + // If warmstart is in progress, we take all netlink changes into the cache map + if (m_AppRestartAssist->isWarmStartInProgress()) + { + m_AppRestartAssist->insertToMap(APP_EVPN_REMOTE_VNI_TABLE_NAME, key, fvVector, false); + return; + } + + m_imetTable.set(key, fvVector); + return; +} + +void FdbSync::imetDelRoute(struct in_addr vtep, string vlan_str, uint32_t vni) +{ + string vlan_id = "Vlan" + vlan_str; + string key = vlan_id + ":" + inet_ntoa(vtep); + + if (!checkDelImet(key, vni)) + return; + + SWSS_LOG_NOTICE("%sIMET Del route key:%s vtep:%s %s", + m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "", + key.c_str(), inet_ntoa(vtep), vlan_id.c_str()); + + std::vector fvVector; + FieldValueTuple f("vni", to_string(vni)); + fvVector.push_back(f); + + // If warmstart is in progress, we take all netlink changes into the cache map + if (m_AppRestartAssist->isWarmStartInProgress()) + { + m_AppRestartAssist->insertToMap(APP_EVPN_REMOTE_VNI_TABLE_NAME, key, fvVector, true); + return; + } + + m_imetTable.del(key); + return; +} + +void FdbSync::macUpdateVxlanDB(string key) +{ + string vtep = m_mac[key].vtep; + string type; + string vni = to_string(m_mac[key].vni); + + if (m_mac[key].type) + type = "static"; + else + type = "dynamic"; + + std::vector fvVector; + FieldValueTuple rv("remote_vtep", vtep); + FieldValueTuple t("type", type); + FieldValueTuple v("vni", vni); + fvVector.push_back(rv); + fvVector.push_back(t); + fvVector.push_back(v); + + SWSS_LOG_NOTICE("%sVXLAN_FDB_TABLE: ADD_KEY %s vtep:%s type:%s", + m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "" , + key.c_str(), vtep.c_str(), type.c_str()); + + // If warmstart is in progress, we take all netlink changes into the cache map + if (m_AppRestartAssist->isWarmStartInProgress()) + { + m_AppRestartAssist->insertToMap(APP_VXLAN_FDB_TABLE_NAME, key, fvVector, false); + return; + } + + SWSS_LOG_NOTICE("VXLAN_FDB_TABLE: ADD_KEY %s vtep:%s type:%s", key.c_str(), vtep.c_str(), type.c_str()); + m_fdbTable.set(key, fvVector); +} + +void FdbSync::macDelVxlanDB(string key) +{ + string vtep = m_mac[key].vtep; + string type; + string vni = to_string(m_mac[key].vni); + + if (m_mac[key].type) + type = "static"; + else + type = "dynamic"; + + std::vector fvVector; + FieldValueTuple rv("remote_vtep", vtep); + FieldValueTuple t("type", type); + FieldValueTuple v("vni", vni); + fvVector.push_back(rv); + fvVector.push_back(t); + fvVector.push_back(v); + + SWSS_LOG_NOTICE("%sVXLAN_FDB_TABLE: DEL_KEY %s vtep:%s type:%s", + m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "" , + key.c_str(), vtep.c_str(), type.c_str()); + + // If warmstart is in progress, we take all netlink changes into the cache map + if (m_AppRestartAssist->isWarmStartInProgress()) + { + m_AppRestartAssist->insertToMap(APP_VXLAN_FDB_TABLE_NAME, key, fvVector, true); + return; + } + + SWSS_LOG_NOTICE("VXLAN_FDB_TABLE: DEL_KEY %s vtep:%s type:%s", key.c_str(), vtep.c_str(), type.c_str()); + m_fdbTable.del(key); + return; + +} + +void FdbSync::macAddVxlan(string key, struct in_addr vtep, uint32_t type, uint32_t vni, string intf_name) +{ + m_mac[key].vtep = inet_ntoa(vtep); + m_mac[key].type = type; + m_mac[key].vni = vni; + m_mac[key].ifname = intf_name; + + macUpdateVxlanDB(key); + return; +} + +void FdbSync::macDelVxlan(string key) +{ + if (m_mac.find(key) != m_mac.end()) + { + SWSS_LOG_INFO("DEL_KEY %s vtep:%s type:%d", key.c_str(), m_mac[key].vtep.c_str(), m_mac[key].type); + macDelVxlanDB(key); + m_mac.erase(key); + } + return; +} + +void FdbSync::onMsgNbr(int nlmsg_type, struct nl_object *obj) +{ + char macStr[MAX_ADDR_SIZE + 1] = {0}; + struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj; + struct in_addr vtep = {0}; + int vlan = 0, ifindex = 0; + uint32_t vni = 0; + nl_addr *vtep_addr; + string ifname; + string key; + bool delete_key = false; + size_t str_loc = string::npos; + uint32_t type = 0; + bool isNotVxlanLink = false; + string vlan_id = ""; + bool isIntfExist = false; + + if ((nlmsg_type != RTM_NEWNEIGH) && (nlmsg_type != RTM_GETNEIGH) && + (nlmsg_type != RTM_DELNEIGH)) + return; + + /* Only MAC route is to be supported */ + if (rtnl_neigh_get_family(neigh) != AF_BRIDGE) + { + return; + } + ifindex = rtnl_neigh_get_ifindex(neigh); + if (intf_info.find(ifindex) != intf_info.end()) + { + isIntfExist = true; + ifname = intf_info[ifindex].ifname; + } + + nl_addr2str(rtnl_neigh_get_lladdr(neigh), macStr, MAX_ADDR_SIZE); + + if (isIntfExist == false) + { + /* In Normal run kernel should not ageout this mac */ + isNotVxlanLink = true; + + /* When the mac is not learned on the vxlan interface then check if we need to refresh the route */ + if (nlmsg_type != RTM_DELNEIGH) + return; + } + else + { + /* If this is for vnet bridge vxlan interface, then return */ + if (ifname.find(VXLAN_BR_IF_NAME_PREFIX) != string::npos) + return; + + /* VxLan netdevice should be in - format */ + str_loc = ifname.find("-"); + if (str_loc == string::npos) + return; + + vlan_id = "Vlan" + ifname.substr(str_loc+1, std::string::npos); + vni = intf_info[ifindex].vni; + } + + + if (isNotVxlanLink) + { + vlan = rtnl_neigh_get_vlan(neigh); + macRefreshStateDB(vlan, macStr); + return; + } + + vtep_addr = rtnl_neigh_get_dst(neigh); + if (vtep_addr == NULL) + { + return; + } + else + { + /* Currently we only support ipv4 tunnel endpoints */ + vtep.s_addr = *(uint32_t *)nl_addr_get_binary_addr(vtep_addr); + SWSS_LOG_INFO("Tunnel IP %s Int%d", inet_ntoa(vtep), *(uint32_t *)nl_addr_get_binary_addr(vtep_addr)); + } + + int state = rtnl_neigh_get_state(neigh); + if ((nlmsg_type == RTM_DELNEIGH) || (state == NUD_INCOMPLETE) || + (state == NUD_FAILED)) + { + delete_key = true; + } + + if (state & NUD_NOARP) + { + /* This is a static route */ + type = true; + } + + /* Handling IMET routes */ + if (MacAddress(macStr) == MacAddress("00:00:00:00:00:00")) + { + if (vtep.s_addr) + { + string vlan_str = ifname.substr(str_loc+1, string::npos); + + if (!delete_key) + { + imetAddRoute(vtep, vlan_str, vni); + } + else + { + imetDelRoute(vtep, vlan_str, vni); + } + } + return; + } + + key+= vlan_id; + key+= ":"; + key+= macStr; + + if (!delete_key) + { + macAddVxlan(key, vtep, type, vni, ifname); + } + else + { + macDelVxlan(key); + } + return; +} + +void FdbSync::onMsgLink(int nlmsg_type, struct nl_object *obj) +{ + struct rtnl_link *link; + char *ifname = NULL; + char *nil = "NULL"; + int ifindex; + unsigned int vni; + + link = (struct rtnl_link *)obj; + ifname = rtnl_link_get_name(link); + ifindex = rtnl_link_get_ifindex(link); + if (rtnl_link_is_vxlan(link) == 0) + { + return; + } + + if (rtnl_link_vxlan_get_id(link, &vni) != 0) + { + SWSS_LOG_NOTICE("Op:%d VxLAN dev:%s index:%d vni:%d. Not found", nlmsg_type, ifname? ifname: nil, ifindex, vni); + return; + } + SWSS_LOG_INFO("Op:%d VxLAN dev %s index:%d vni:%d", nlmsg_type, ifname? ifname: nil, ifindex, vni); + if (nlmsg_type == RTM_NEWLINK) + { + intf_info[ifindex].vni = vni; + intf_info[ifindex].ifname = ifname; + } + return; +} + +void FdbSync::onMsg(int nlmsg_type, struct nl_object *obj) +{ + if ((nlmsg_type != RTM_NEWLINK) && + (nlmsg_type != RTM_NEWNEIGH) && (nlmsg_type != RTM_DELNEIGH)) + { + SWSS_LOG_DEBUG("netlink: unhandled event: %d", nlmsg_type); + return; + } + if (nlmsg_type == RTM_NEWLINK) + { + onMsgLink(nlmsg_type, obj); + } + else + { + onMsgNbr(nlmsg_type, obj); + } +} + diff --git a/fdbsyncd/fdbsync.h b/fdbsyncd/fdbsync.h new file mode 100644 index 0000000000..09423ca7b5 --- /dev/null +++ b/fdbsyncd/fdbsync.h @@ -0,0 +1,128 @@ +#ifndef __FDBSYNC__ +#define __FDBSYNC__ + +#include +#include +#include "dbconnector.h" +#include "producerstatetable.h" +#include "subscriberstatetable.h" +#include "netmsg.h" +#include "warmRestartAssist.h" + +// The timeout value (in seconds) for fdbsyncd reconcilation logic +#define DEFAULT_FDBSYNC_WARMSTART_TIMER 30 + +namespace swss { + +enum FDB_OP_TYPE { + FDB_OPER_ADD =1, + FDB_OPER_DEL = 2, +}; + +enum FDB_TYPE { + FDB_TYPE_STATIC = 1, + FDB_TYPE_DYNAMIC = 2, +}; + +struct fdb_info +{ + char mac[32]; + unsigned int vid; + char port_name[32]; + short type; /*dynamic or static*/ + short op_type; /*add or del*/ +}; + +class FdbSync : public NetMsg +{ +public: + enum { MAX_ADDR_SIZE = 64 }; + + FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb); + ~FdbSync(); + + virtual void onMsg(int nlmsg_type, struct nl_object *obj); + + bool isFdbRestoreDone(); + + AppRestartAssist *getRestartAssist() + { + return m_AppRestartAssist; + } + + SubscriberStateTable *getFdbStateTable() + { + return &m_fdbStateTable; + } + + void processStateFdb(); + + bool m_reconcileDone = false; + +private: + Table m_stateFdbRestoreTable; + ProducerStateTable m_fdbTable; + ProducerStateTable m_imetTable; + SubscriberStateTable m_fdbStateTable; + AppRestartAssist *m_AppRestartAssist; + + struct fdbmacinfo + { + std::string port_name; + short type;/*dynamic or static*/ + }; + std::unordered_map fdbmac; + + void macDelVxlanEntry(std::string auxkey, struct fdb_info *info); + + void macAddSrcDB(struct fdb_info *info); + + bool macCheckSrcDB(struct fdb_info *info); + + void macUpdateStateDB(struct fdb_info *info); + + void macRefreshStateDB(int vlan, std::string kmac); + + bool checkImetExit(std::string key, uint32_t vni); + + bool checkDelImet(std::string key, uint32_t vni); + + struct macinfo + { + std::string vtep; + unsigned int type; + unsigned int vni; + std::string ifname; + }; + std::unordered_map m_mac; + + struct imetinfo + { + unsigned int vni; + bool redist_add_status; + }; + std::unordered_map imet_route; + + struct intf + { + std::string ifname; + unsigned int vni; + }; + std::unordered_map intf_info; + + std::map m_vlanVniMap; + + void macAddVxlan(std::string key, struct in_addr vtep, uint32_t type, uint32_t vni, std::string intf_name); + void macDelVxlan(std::string auxkey); + void macUpdateVxlanDB(std::string key); + void macDelVxlanDB(std::string key); + void imetAddRoute(struct in_addr vtep, std::string ifname, uint32_t vni); + void imetDelRoute(struct in_addr vtep, std::string ifname, uint32_t vni); + void onMsgNbr(int nlmsg_type, struct nl_object *obj); + void onMsgLink(int nlmsg_type, struct nl_object *obj); +}; + +} + +#endif + diff --git a/fdbsyncd/fdbsyncd.cpp b/fdbsyncd/fdbsyncd.cpp new file mode 100644 index 0000000000..6b4123ea64 --- /dev/null +++ b/fdbsyncd/fdbsyncd.cpp @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include "logger.h" +#include "select.h" +#include "netdispatcher.h" +#include "netlink.h" +#include "fdbsyncd/fdbsync.h" + +using namespace std; +using namespace swss; + +class FdbSync *g_fdbsync; + +int main(int argc, char **argv) +{ + Logger::linkToDbNative("fdbsyncd"); + + DBConnector appDb(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + RedisPipeline pipelineAppDB(&appDb); + DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + DBConnector log_db(LOGLEVEL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + + FdbSync sync(&pipelineAppDB, &stateDb); + g_fdbsync = &sync; + + NetDispatcher::getInstance().registerMessageHandler(RTM_NEWNEIGH, &sync); + NetDispatcher::getInstance().registerMessageHandler(RTM_DELNEIGH, &sync); + NetDispatcher::getInstance().registerMessageHandler(RTM_NEWLINK, &sync); + + while (1) + { + try + { + NetLink netlink; + Select s; + + using namespace std::chrono; + + /* + * If WarmStart is enabled, restore the VXLAN-FDB and VNI + * tables and start a reconcillation timer + */ + if (sync.getRestartAssist()->isWarmStartInProgress()) + { + sync.getRestartAssist()->readTablesToMap(); + SWSS_LOG_NOTICE("Starting ReconcileTimer"); + } + + netlink.registerGroup(RTNLGRP_LINK); + netlink.registerGroup(RTNLGRP_NEIGH); + SWSS_LOG_NOTICE("Listens to link and neigh messages..."); + netlink.dumpRequest(RTM_GETLINK); + netlink.dumpRequest(RTM_GETNEIGH); + + s.addSelectable(&netlink); + s.addSelectable(sync.getFdbStateTable()); + while (true) + { + Selectable *temps; + s.select(&temps); + + if(temps == (Selectable *)sync.getFdbStateTable()) + { + sync.processStateFdb(); + } + else + { + /* + * If warmstart is in progress, we check the reconcile timer, + * if timer expired, we stop the timer and start the reconcile process + */ + if (sync.getRestartAssist()->isWarmStartInProgress()) + { + if (sync.getRestartAssist()->checkReconcileTimer(temps)) + { + sync.m_reconcileDone = true; + sync.getRestartAssist()->stopReconcileTimer(s); + sync.getRestartAssist()->reconcile(); + SWSS_LOG_NOTICE("VXLAN FDB VNI Reconcillation Complete (Timer)"); + } + } + } + } + } + catch (const std::exception& e) + { + cout << "Exception \"" << e.what() << "\" had been thrown in deamon" << endl; + return 0; + } + } + + return 1; +} From 44681f72d7bb62c39b448c2df84b88636163c325 Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Thu, 14 May 2020 10:13:29 -0700 Subject: [PATCH 20/24] Update Makefile.am --- fdbsyncd/Makefile.am | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fdbsyncd/Makefile.am b/fdbsyncd/Makefile.am index 9b5228359d..0ad7d67df4 100644 --- a/fdbsyncd/Makefile.am +++ b/fdbsyncd/Makefile.am @@ -1,5 +1,4 @@ -INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/warmrestart -I ../nlapi/include -I ../cfgmgr -NLAPI_LIBS = ../nlapi/libnlapi.a +INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/warmrestart bin_PROGRAMS = fdbsyncd @@ -13,5 +12,5 @@ fdbsyncd_SOURCES = fdbsyncd.cpp fdbsync.cpp $(top_srcdir)/warmrestart/warmRestar fdbsyncd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(COV_CFLAGS) fdbsyncd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(COV_CFLAGS) -fdbsyncd_LDADD = -lnl-3 -lnl-route-3 -lswsscommon $(NLAPI_LIBS) $(COV_LDFLAGS) +fdbsyncd_LDADD = -lnl-3 -lnl-route-3 -lswsscommon $(COV_LDFLAGS) From 11f717cff22c74a5e588a73e623378eae71d3dcf Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Thu, 14 May 2020 10:14:06 -0700 Subject: [PATCH 21/24] Update fdbsync.cpp --- fdbsyncd/fdbsync.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/fdbsyncd/fdbsync.cpp b/fdbsyncd/fdbsync.cpp index 578ced048d..6a19016400 100644 --- a/fdbsyncd/fdbsync.cpp +++ b/fdbsyncd/fdbsync.cpp @@ -15,7 +15,6 @@ #include "shellcmd.h" #include "fdbsync.h" #include "warm_restart.h" -#include "nlapi.h" #include "errno.h" using namespace std; From 877ec26acf3be0dcda49eb50397400b4d63c0838 Mon Sep 17 00:00:00 2001 From: KISHORE KUNAL <64033340+kishorekunal01@users.noreply.github.com> Date: Tue, 9 Jun 2020 12:33:39 -0700 Subject: [PATCH 22/24] Update fdbsync.cpp --- fdbsyncd/fdbsync.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fdbsyncd/fdbsync.cpp b/fdbsyncd/fdbsync.cpp index 6a19016400..705e58d3ef 100644 --- a/fdbsyncd/fdbsync.cpp +++ b/fdbsyncd/fdbsync.cpp @@ -24,7 +24,7 @@ using namespace swss; FdbSync::FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb) : m_fdbTable(pipelineAppDB, APP_VXLAN_FDB_TABLE_NAME), - m_imetTable(pipelineAppDB, APP_EVPN_REMOTE_VNI_TABLE_NAME), + m_imetTable(pipelineAppDB, APP_VXLAN_REMOTE_VNI_TABLE_NAME), m_stateFdbRestoreTable(stateDb, STATE_EVPN_FDB_RESTORE_TABLE_NAME), m_fdbStateTable(stateDb, STATE_FDB_TABLE_NAME) { @@ -32,7 +32,7 @@ FdbSync::FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb) : if (m_AppRestartAssist) { m_AppRestartAssist->registerAppTable(APP_VXLAN_FDB_TABLE_NAME, &m_fdbTable); - m_AppRestartAssist->registerAppTable(APP_EVPN_REMOTE_VNI_TABLE_NAME, &m_imetTable); + m_AppRestartAssist->registerAppTable(APP_VXLAN_REMOTE_VNI_TABLE_NAME, &m_imetTable); } } @@ -300,7 +300,7 @@ void FdbSync::imetAddRoute(struct in_addr vtep, string vlan_str, uint32_t vni) // If warmstart is in progress, we take all netlink changes into the cache map if (m_AppRestartAssist->isWarmStartInProgress()) { - m_AppRestartAssist->insertToMap(APP_EVPN_REMOTE_VNI_TABLE_NAME, key, fvVector, false); + m_AppRestartAssist->insertToMap(APP_VXLAN_REMOTE_VNI_TABLE_NAME, key, fvVector, false); return; } @@ -327,7 +327,7 @@ void FdbSync::imetDelRoute(struct in_addr vtep, string vlan_str, uint32_t vni) // If warmstart is in progress, we take all netlink changes into the cache map if (m_AppRestartAssist->isWarmStartInProgress()) { - m_AppRestartAssist->insertToMap(APP_EVPN_REMOTE_VNI_TABLE_NAME, key, fvVector, true); + m_AppRestartAssist->insertToMap(APP_VXLAN_REMOTE_VNI_TABLE_NAME, key, fvVector, true); return; } From fa2be2335caa4a6e68ba5ecda59053c67c35934d Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Wed, 18 Nov 2020 21:57:56 -0800 Subject: [PATCH 23/24] All the review comment are address in the changes --- fdbsyncd/fdbsync.cpp | 394 ++++++++++++++++++++++++++---------------- fdbsyncd/fdbsync.h | 69 ++++---- fdbsyncd/fdbsyncd.cpp | 48 +++-- 3 files changed, 314 insertions(+), 197 deletions(-) diff --git a/fdbsyncd/fdbsync.cpp b/fdbsyncd/fdbsync.cpp index 705e58d3ef..5e94845d26 100644 --- a/fdbsyncd/fdbsync.cpp +++ b/fdbsyncd/fdbsync.cpp @@ -12,7 +12,6 @@ #include "netmsg.h" #include "macaddress.h" #include "exec.h" -#include "shellcmd.h" #include "fdbsync.h" #include "warm_restart.h" #include "errno.h" @@ -22,11 +21,12 @@ using namespace swss; #define VXLAN_BR_IF_NAME_PREFIX "Brvxlan" -FdbSync::FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb) : +FdbSync::FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb, DBConnector *config_db) : m_fdbTable(pipelineAppDB, APP_VXLAN_FDB_TABLE_NAME), m_imetTable(pipelineAppDB, APP_VXLAN_REMOTE_VNI_TABLE_NAME), m_stateFdbRestoreTable(stateDb, STATE_EVPN_FDB_RESTORE_TABLE_NAME), - m_fdbStateTable(stateDb, STATE_FDB_TABLE_NAME) + m_fdbStateTable(stateDb, STATE_FDB_TABLE_NAME), + m_cfgEvpnNvoTable(config_db, CFG_VXLAN_EVPN_NVO_TABLE_NAME) { m_AppRestartAssist = new AppRestartAssist(pipelineAppDB, "fdbsyncd", "swss", DEFAULT_FDBSYNC_WARMSTART_TIMER); if (m_AppRestartAssist) @@ -52,23 +52,66 @@ bool FdbSync::isFdbRestoreDone() m_stateFdbRestoreTable.hget("Flags", "restored", value); if (value == "true") { - SWSS_LOG_NOTICE("neighbor table restore to kernel is done"); + SWSS_LOG_INFO("neighbor table restore to kernel is done"); return true; } return true; } +void FdbSync::processCfgEvpnNvo() +{ + std::deque entries; + m_cfgEvpnNvoTable.pops(entries); + bool lastNvoState = m_isEvpnNvoExist; + + for (auto entry: entries) + { + std::string op = kfvOp(entry); + + if (op == SET_COMMAND) + { + m_isEvpnNvoExist = true; + } + else if (op == DEL_COMMAND) + { + m_isEvpnNvoExist = false; + } + + if (lastNvoState != m_isEvpnNvoExist) + { + updateAllLocalMac(); + } + } + return; +} + +void FdbSync::updateAllLocalMac() +{ + for ( auto it = m_fdb_mac.begin(); it != m_fdb_mac.end(); ++it ) + { + if (m_isEvpnNvoExist) + { + /* Add the Local FDB entry into Kernel */ + addLocalMac(it->first, "replace"); + } + else + { + /* Delete the Local FDB entry from Kernel */ + addLocalMac(it->first, "del"); + } + } +} + void FdbSync::processStateFdb() { - struct fdb_info info; + struct m_fdb_info info; std::deque entries; - + m_fdbStateTable.pops(entries); int count =0 ; for (auto entry: entries) { - memset(&info, 0, sizeof(struct fdb_info)); count++; std::string key = kfvKey(entry); std::string op = kfvOp(entry); @@ -77,16 +120,20 @@ void FdbSync::processStateFdb() auto vlan_name = key.substr(0, delimiter); auto mac_address = key.substr(delimiter+1); - info.vid = (unsigned int) stoi(vlan_name.substr(4)); + info.vid = vlan_name; memcpy(info.mac, mac_address.c_str(),mac_address.length()); if(op == "SET") + { info.op_type = FDB_OPER_ADD ; + } else + { info.op_type = FDB_OPER_DEL ; + } + + SWSS_LOG_INFO("FDBSYNCD STATE FDB updates key=%s, operation=%s\n", key.c_str(), op.c_str()); - SWSS_LOG_NOTICE("FDBSYNCD STATE FDB updates key=%s, operation=%s\n", key.c_str(), op.c_str()); - for (auto i : kfvFieldsValues(entry)) { SWSS_LOG_INFO(" FDBSYNCD STATE FDB updates : " @@ -100,43 +147,52 @@ void FdbSync::processStateFdb() if(fvField(i) == "type") { if(fvValue(i) == "dynamic") + { info.type = FDB_TYPE_DYNAMIC; + } else if (fvValue(i) == "static") + { info.type = FDB_TYPE_STATIC; + } } } - macUpdateStateDB(&info); + + if (op != "SET" && macCheckSrcDB(&info) == false) + { + continue; + } + updateLocalMac(&info); } } -void FdbSync::macAddSrcDB(struct fdb_info *info) +void FdbSync::macUpdateCache(struct m_fdb_info *info) { - string key = "Vlan" + to_string(info->vid) + ":" + info->mac; - fdbmac[key].port_name = info->port_name; - fdbmac[key].type = info->type; + string key = info->vid + ":" + info->mac; + m_fdb_mac[key].port_name = info->port_name; + m_fdb_mac[key].type = info->type; return; } -bool FdbSync::macCheckSrcDB(struct fdb_info *info) +bool FdbSync::macCheckSrcDB(struct m_fdb_info *info) { - string key = "Vlan" + to_string(info->vid) + ":" + info->mac; - if (fdbmac.find(key) != fdbmac.end()) + string key = info->vid + ":" + info->mac; + if (m_fdb_mac.find(key) != m_fdb_mac.end()) { - SWSS_LOG_NOTICE("DEL_KEY %s ", key.c_str()); + SWSS_LOG_INFO("DEL_KEY %s ", key.c_str()); return true; } return false; } -void FdbSync::macDelVxlanEntry(string auxkey, struct fdb_info *info) +void FdbSync::macDelVxlanEntry(string auxkey, struct m_fdb_info *info) { std::string vtep = m_mac[auxkey].vtep; const std::string cmds = std::string("") + " bridge fdb del " + info->mac + " dev " - + m_mac[auxkey].ifname + " dst " + vtep + " vlan " + to_string(info->vid); + + m_mac[auxkey].ifname + " dst " + vtep + " vlan " + info->vid.substr(4); std::string res; int ret = swss::exec(cmds, res); @@ -145,29 +201,28 @@ void FdbSync::macDelVxlanEntry(string auxkey, struct fdb_info *info) SWSS_LOG_INFO("Failed cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); } - SWSS_LOG_NOTICE("Success cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + SWSS_LOG_INFO("Success cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); return; } -void FdbSync::macUpdateStateDB(struct fdb_info *info) +void FdbSync::updateLocalMac (struct m_fdb_info *info) { char *op; char *type; string port_name = ""; - string key = "Vlan" + to_string(info->vid) + ":" + info->mac; - short fdb_type; /*dynamic or static*/ + string key = info->vid + ":" + info->mac; + short fdb_type; /*dynamic or static*/ if (info->op_type == FDB_OPER_ADD) { - macAddSrcDB(info); - op = "add"; - port_name+= info->port_name; + macUpdateCache(info); + op = "replace"; + port_name = info->port_name; fdb_type = info->type; /* Check if this vlan+key is also learned by vxlan neighbor then delete learned on */ if (m_mac.find(key) != m_mac.end()) { - op = "replace"; macDelVxlanEntry(key, info); SWSS_LOG_INFO("Local learn event deleting from VXLAN table DEL_KEY %s", key.c_str()); macDelVxlan(key); @@ -176,13 +231,15 @@ void FdbSync::macUpdateStateDB(struct fdb_info *info) else { op = "del"; - if (macCheckSrcDB(info) == false) - { - return; - } - port_name+= fdbmac[key].port_name; - fdb_type = fdbmac[key].type; - fdbmac.erase(key); + port_name = m_fdb_mac[key].port_name; + fdb_type = m_fdb_mac[key].type; + m_fdb_mac.erase(key); + } + + if (!m_isEvpnNvoExist) + { + SWSS_LOG_INFO("Ignore kernel update EVPN NVO is not configured MAC %s", key.c_str()); + return; } if (fdb_type == FDB_TYPE_DYNAMIC) @@ -196,85 +253,138 @@ void FdbSync::macUpdateStateDB(struct fdb_info *info) const std::string cmds = std::string("") + " bridge fdb " + op + " " + info->mac + " dev " - + port_name + " master " + type + " vlan " + to_string(info->vid); + + port_name + " master " + type + " vlan " + info->vid.substr(4); std::string res; int ret = swss::exec(cmds, res); - SWSS_LOG_NOTICE("cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + SWSS_LOG_INFO("cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); return; } +void FdbSync::addLocalMac(string key, string op) +{ + char *type; + string port_name = ""; + string mac = ""; + string vlan = ""; + size_t str_loc = string::npos; + + str_loc = key.find(":"); + if (str_loc == string::npos) + { + SWSS_LOG_ERROR("Local MAC issue with Key:%s", key.c_str()); + return; + } + vlan = key.substr(4, str_loc-4); + mac = key.substr(str_loc+1, std::string::npos); + + SWSS_LOG_INFO("Local route Vlan:%s MAC:%s Key:%s Op:%s", vlan.c_str(), mac.c_str(), key.c_str(), op.c_str()); + + if (m_fdb_mac.find(key)!=m_fdb_mac.end()) + { + port_name = m_fdb_mac[key].port_name; + if (port_name.empty()) + { + SWSS_LOG_INFO("Port name not present MAC route Key:%s", key.c_str()); + return; + } + + if (m_fdb_mac[key].type == FDB_TYPE_DYNAMIC) + { + type = "dynamic"; + } + else + { + type = "static"; + } + + const std::string cmds = std::string("") + + " bridge fdb " + op + " " + mac + " dev " + + port_name + " master " + type + " vlan " + vlan; + + std::string res; + int ret = swss::exec(cmds, res); + if (ret != 0) + { + SWSS_LOG_INFO("Failed cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + } + + SWSS_LOG_INFO("Config triggered cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + } + return; +} + +/* + * This is a special case handling where mac is learned in the ASIC. + * Then MAC is learned in the Kernel, Since this mac is learned in the Kernel + * This MAC will age out, when MAC delete is received from the Kernel. + * If MAC is still present in the state DB cache then fdbsyncd will be + * re-programmed with MAC in the Kernel + */ void FdbSync::macRefreshStateDB(int vlan, string kmac) { string key = "Vlan" + to_string(vlan) + ":" + kmac; char *type; string port_name = ""; - SWSS_LOG_NOTICE("Refreshing Vlan:%d MAC route MAC:%s Key %s", vlan, kmac.c_str(), key.c_str()); + SWSS_LOG_INFO("Refreshing Vlan:%d MAC route MAC:%s Key %s", vlan, kmac.c_str(), key.c_str()); - if (fdbmac.find(key)!=fdbmac.end()) + if (m_fdb_mac.find(key)!=m_fdb_mac.end()) { - port_name+= fdbmac[key].port_name; + port_name = m_fdb_mac[key].port_name; if (port_name.empty()) { SWSS_LOG_INFO("Port name not present MAC route Key:%s", key.c_str()); return; } - SWSS_LOG_INFO("Refreshing MAC route MAC:%s Key %s Port %s", kmac.c_str(), key.c_str(), port_name.c_str()); - - if (fdbmac[key].type == FDB_TYPE_DYNAMIC) - { - type = "dynamic"; - } - else - { - type = "static"; - } + if (m_fdb_mac[key].type == FDB_TYPE_DYNAMIC) + { + type = "dynamic"; + } + else + { + type = "static"; + } - const std::string cmds = std::string("") - + " bridge fdb " + "add" + " " + kmac + " dev " - + port_name + " master " + type + " vlan " + to_string(vlan); + const std::string cmds = std::string("") + + " bridge fdb " + "replace" + " " + kmac + " dev " + + port_name + " master " + type + " vlan " + to_string(vlan); - std::string res; - int ret = swss::exec(cmds, res); - if (ret != 0) - { - SWSS_LOG_INFO("Failed cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); - } + std::string res; + int ret = swss::exec(cmds, res); + if (ret != 0) + { + SWSS_LOG_INFO("Failed cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + } - SWSS_LOG_NOTICE("Refreshing cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); + SWSS_LOG_INFO("Refreshing cmd:%s, res=%s, ret=%d", cmds.c_str(), res.c_str(), ret); } return; } -bool FdbSync::checkImetExit(string key, uint32_t vni) +bool FdbSync::checkImetExist(string key, uint32_t vni) { - if (imet_route[key].redist_add_status == true) + if (m_imet_route.find(key) != m_imet_route.end()) { - SWSS_LOG_DEBUG("IMET exist key:%s Vni:%d", key.c_str(), vni); + SWSS_LOG_INFO("IMET exist key:%s Vni:%d", key.c_str(), vni); return false; } - imet_route[key].vni = vni; + m_imet_route[key].vni = vni; return true; } bool FdbSync::checkDelImet(string key, uint32_t vni) { - int ret = true; + int ret = false; - SWSS_LOG_DEBUG("Del IMET key:%s Vni:%d", key.c_str(), vni); - if (imet_route.find(key) != imet_route.end()) + SWSS_LOG_INFO("Del IMET key:%s Vni:%d", key.c_str(), vni); + if (m_imet_route.find(key) != m_imet_route.end()) { - SWSS_LOG_DEBUG("IMET found key:%s Vni:%d", key.c_str(), vni); - if (imet_route[key].redist_add_status == false) - { - SWSS_LOG_DEBUG("IMET found key:%s Vni:%d, it should have not happened", key.c_str(), vni); - ret = false; - } - imet_route.erase(key); + ret = true; + m_imet_route.erase(key); } return ret; } @@ -284,27 +394,27 @@ void FdbSync::imetAddRoute(struct in_addr vtep, string vlan_str, uint32_t vni) string vlan_id = "Vlan" + vlan_str; string key = vlan_id + ":" + inet_ntoa(vtep); - if (!checkImetExit(key, vni)) + if (!checkImetExist(key, vni)) + { return; + } - SWSS_LOG_NOTICE("%sIMET Add route key:%s vtep:%s %s", - m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "", - key.c_str(), inet_ntoa(vtep), vlan_id.c_str()); + SWSS_LOG_INFO("%sIMET Add route key:%s vtep:%s %s", + m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "", + key.c_str(), inet_ntoa(vtep), vlan_id.c_str()); std::vector fvVector; FieldValueTuple f("vni", to_string(vni)); fvVector.push_back(f); - imet_route[key].redist_add_status = true; - - // If warmstart is in progress, we take all netlink changes into the cache map + // If warmstart is in progress, we take all netlink changes into the cache map if (m_AppRestartAssist->isWarmStartInProgress()) { m_AppRestartAssist->insertToMap(APP_VXLAN_REMOTE_VNI_TABLE_NAME, key, fvVector, false); return; } - m_imetTable.set(key, fvVector); + m_imetTable.set(key, fvVector); return; } @@ -314,11 +424,13 @@ void FdbSync::imetDelRoute(struct in_addr vtep, string vlan_str, uint32_t vni) string key = vlan_id + ":" + inet_ntoa(vtep); if (!checkDelImet(key, vni)) + { return; + } - SWSS_LOG_NOTICE("%sIMET Del route key:%s vtep:%s %s", - m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "", - key.c_str(), inet_ntoa(vtep), vlan_id.c_str()); + SWSS_LOG_INFO("%sIMET Del route key:%s vtep:%s %s", + m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "", + key.c_str(), inet_ntoa(vtep), vlan_id.c_str()); std::vector fvVector; FieldValueTuple f("vni", to_string(vni)); @@ -331,20 +443,16 @@ void FdbSync::imetDelRoute(struct in_addr vtep, string vlan_str, uint32_t vni) return; } - m_imetTable.del(key); + m_imetTable.del(key); return; } -void FdbSync::macUpdateVxlanDB(string key) +void FdbSync::macDelVxlanDB(string key) { string vtep = m_mac[key].vtep; string type; string vni = to_string(m_mac[key].vni); - - if (m_mac[key].type) - type = "static"; - else - type = "dynamic"; + type = m_mac[key].type; std::vector fvVector; FieldValueTuple rv("remote_vtep", vtep); @@ -354,65 +462,45 @@ void FdbSync::macUpdateVxlanDB(string key) fvVector.push_back(t); fvVector.push_back(v); - SWSS_LOG_NOTICE("%sVXLAN_FDB_TABLE: ADD_KEY %s vtep:%s type:%s", - m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "" , - key.c_str(), vtep.c_str(), type.c_str()); - // If warmstart is in progress, we take all netlink changes into the cache map if (m_AppRestartAssist->isWarmStartInProgress()) { - m_AppRestartAssist->insertToMap(APP_VXLAN_FDB_TABLE_NAME, key, fvVector, false); + m_AppRestartAssist->insertToMap(APP_VXLAN_FDB_TABLE_NAME, key, fvVector, true); return; } - SWSS_LOG_NOTICE("VXLAN_FDB_TABLE: ADD_KEY %s vtep:%s type:%s", key.c_str(), vtep.c_str(), type.c_str()); - m_fdbTable.set(key, fvVector); + SWSS_LOG_INFO("VXLAN_FDB_TABLE: DEL_KEY %s vtep:%s type:%s", key.c_str(), vtep.c_str(), type.c_str()); + m_fdbTable.del(key); + return; + } -void FdbSync::macDelVxlanDB(string key) +void FdbSync::macAddVxlan(string key, struct in_addr vtep, string type, uint32_t vni, string intf_name) { - string vtep = m_mac[key].vtep; - string type; - string vni = to_string(m_mac[key].vni); + string svtep = inet_ntoa(vtep); + string svni = to_string(vni); - if (m_mac[key].type) - type = "static"; - else - type = "dynamic"; + /* Update the DB with Vxlan MAC */ + m_mac[key] = {svtep, type, vni, intf_name}; std::vector fvVector; - FieldValueTuple rv("remote_vtep", vtep); + FieldValueTuple rv("remote_vtep", svtep); FieldValueTuple t("type", type); - FieldValueTuple v("vni", vni); + FieldValueTuple v("vni", svni); fvVector.push_back(rv); fvVector.push_back(t); fvVector.push_back(v); - SWSS_LOG_NOTICE("%sVXLAN_FDB_TABLE: DEL_KEY %s vtep:%s type:%s", - m_AppRestartAssist->isWarmStartInProgress() ? "WARM-RESTART:" : "" , - key.c_str(), vtep.c_str(), type.c_str()); - // If warmstart is in progress, we take all netlink changes into the cache map if (m_AppRestartAssist->isWarmStartInProgress()) { - m_AppRestartAssist->insertToMap(APP_VXLAN_FDB_TABLE_NAME, key, fvVector, true); + m_AppRestartAssist->insertToMap(APP_VXLAN_FDB_TABLE_NAME, key, fvVector, false); return; } - SWSS_LOG_NOTICE("VXLAN_FDB_TABLE: DEL_KEY %s vtep:%s type:%s", key.c_str(), vtep.c_str(), type.c_str()); - m_fdbTable.del(key); - return; - -} - -void FdbSync::macAddVxlan(string key, struct in_addr vtep, uint32_t type, uint32_t vni, string intf_name) -{ - m_mac[key].vtep = inet_ntoa(vtep); - m_mac[key].type = type; - m_mac[key].vni = vni; - m_mac[key].ifname = intf_name; + SWSS_LOG_INFO("VXLAN_FDB_TABLE: ADD_KEY %s vtep:%s type:%s", key.c_str(), svtep.c_str(), type.c_str()); + m_fdbTable.set(key, fvVector); - macUpdateVxlanDB(key); return; } @@ -420,7 +508,7 @@ void FdbSync::macDelVxlan(string key) { if (m_mac.find(key) != m_mac.end()) { - SWSS_LOG_INFO("DEL_KEY %s vtep:%s type:%d", key.c_str(), m_mac[key].vtep.c_str(), m_mac[key].type); + SWSS_LOG_INFO("DEL_KEY %s vtep:%s type:%s", key.c_str(), m_mac[key].vtep.c_str(), m_mac[key].type.c_str()); macDelVxlanDB(key); m_mac.erase(key); } @@ -439,14 +527,15 @@ void FdbSync::onMsgNbr(int nlmsg_type, struct nl_object *obj) string key; bool delete_key = false; size_t str_loc = string::npos; - uint32_t type = 0; - bool isNotVxlanLink = false; + string type = ""; string vlan_id = ""; - bool isIntfExist = false; + bool isVxlanIntf = false; if ((nlmsg_type != RTM_NEWNEIGH) && (nlmsg_type != RTM_GETNEIGH) && (nlmsg_type != RTM_DELNEIGH)) + { return; + } /* Only MAC route is to be supported */ if (rtnl_neigh_get_family(neigh) != AF_BRIDGE) @@ -454,43 +543,48 @@ void FdbSync::onMsgNbr(int nlmsg_type, struct nl_object *obj) return; } ifindex = rtnl_neigh_get_ifindex(neigh); - if (intf_info.find(ifindex) != intf_info.end()) + if (m_intf_info.find(ifindex) != m_intf_info.end()) { - isIntfExist = true; - ifname = intf_info[ifindex].ifname; + isVxlanIntf = true; + ifname = m_intf_info[ifindex].ifname; } nl_addr2str(rtnl_neigh_get_lladdr(neigh), macStr, MAX_ADDR_SIZE); - if (isIntfExist == false) + if (isVxlanIntf == false) { - /* In Normal run kernel should not ageout this mac */ - isNotVxlanLink = true; - - /* When the mac is not learned on the vxlan interface then check if we need to refresh the route */ if (nlmsg_type != RTM_DELNEIGH) + { return; + } } else { /* If this is for vnet bridge vxlan interface, then return */ if (ifname.find(VXLAN_BR_IF_NAME_PREFIX) != string::npos) + { return; + } /* VxLan netdevice should be in - format */ - str_loc = ifname.find("-"); + str_loc = ifname.rfind("-"); if (str_loc == string::npos) + { return; + } vlan_id = "Vlan" + ifname.substr(str_loc+1, std::string::npos); - vni = intf_info[ifindex].vni; + vni = m_intf_info[ifindex].vni; } - if (isNotVxlanLink) + if (isVxlanIntf == false) { vlan = rtnl_neigh_get_vlan(neigh); - macRefreshStateDB(vlan, macStr); + if (m_isEvpnNvoExist) + { + macRefreshStateDB(vlan, macStr); + } return; } @@ -516,7 +610,11 @@ void FdbSync::onMsgNbr(int nlmsg_type, struct nl_object *obj) if (state & NUD_NOARP) { /* This is a static route */ - type = true; + type = "static"; + } + else + { + type = "dynamic"; } /* Handling IMET routes */ @@ -571,14 +669,14 @@ void FdbSync::onMsgLink(int nlmsg_type, struct nl_object *obj) if (rtnl_link_vxlan_get_id(link, &vni) != 0) { - SWSS_LOG_NOTICE("Op:%d VxLAN dev:%s index:%d vni:%d. Not found", nlmsg_type, ifname? ifname: nil, ifindex, vni); + SWSS_LOG_INFO("Op:%d VxLAN dev:%s index:%d vni:%d. Not found", nlmsg_type, ifname? ifname: nil, ifindex, vni); return; } SWSS_LOG_INFO("Op:%d VxLAN dev %s index:%d vni:%d", nlmsg_type, ifname? ifname: nil, ifindex, vni); if (nlmsg_type == RTM_NEWLINK) { - intf_info[ifindex].vni = vni; - intf_info[ifindex].ifname = ifname; + m_intf_info[ifindex].vni = vni; + m_intf_info[ifindex].ifname = ifname; } return; } diff --git a/fdbsyncd/fdbsync.h b/fdbsyncd/fdbsync.h index 09423ca7b5..98661ff589 100644 --- a/fdbsyncd/fdbsync.h +++ b/fdbsyncd/fdbsync.h @@ -24,13 +24,13 @@ enum FDB_TYPE { FDB_TYPE_DYNAMIC = 2, }; -struct fdb_info +struct m_fdb_info { char mac[32]; - unsigned int vid; + std::string vid; /*Store as Vlan */ char port_name[32]; - short type; /*dynamic or static*/ - short op_type; /*add or del*/ + short type; /*dynamic or static*/ + short op_type; /*add or del*/ }; class FdbSync : public NetMsg @@ -38,88 +38,97 @@ class FdbSync : public NetMsg public: enum { MAX_ADDR_SIZE = 64 }; - FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb); + FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb, DBConnector *config_db); ~FdbSync(); virtual void onMsg(int nlmsg_type, struct nl_object *obj); bool isFdbRestoreDone(); - - AppRestartAssist *getRestartAssist() + + AppRestartAssist *getRestartAssist() { return m_AppRestartAssist; } - - SubscriberStateTable *getFdbStateTable() + + SubscriberStateTable *getFdbStateTable() { return &m_fdbStateTable; } + SubscriberStateTable *getCfgEvpnNvoTable() + { + return &m_cfgEvpnNvoTable; + } + void processStateFdb(); + void processCfgEvpnNvo(); + bool m_reconcileDone = false; + bool m_isEvpnNvoExist = false; + private: Table m_stateFdbRestoreTable; ProducerStateTable m_fdbTable; ProducerStateTable m_imetTable; SubscriberStateTable m_fdbStateTable; AppRestartAssist *m_AppRestartAssist; + SubscriberStateTable m_cfgEvpnNvoTable; - struct fdbmacinfo + struct m_local_fdb_info { - std::string port_name; + std::string port_name; short type;/*dynamic or static*/ }; - std::unordered_map fdbmac; + std::unordered_map m_fdb_mac; - void macDelVxlanEntry(std::string auxkey, struct fdb_info *info); + void macDelVxlanEntry(std::string auxkey, struct m_fdb_info *info); - void macAddSrcDB(struct fdb_info *info); + void macUpdateCache(struct m_fdb_info *info); - bool macCheckSrcDB(struct fdb_info *info); + bool macCheckSrcDB(struct m_fdb_info *info); - void macUpdateStateDB(struct fdb_info *info); + void updateLocalMac(struct m_fdb_info *info); + + void updateAllLocalMac(); void macRefreshStateDB(int vlan, std::string kmac); - bool checkImetExit(std::string key, uint32_t vni); + bool checkImetExist(std::string key, uint32_t vni); bool checkDelImet(std::string key, uint32_t vni); - struct macinfo + struct m_mac_info { std::string vtep; - unsigned int type; + std::string type; unsigned int vni; std::string ifname; }; - std::unordered_map m_mac; + std::unordered_map m_mac; - struct imetinfo + struct m_imet_info { unsigned int vni; - bool redist_add_status; }; - std::unordered_map imet_route; + std::unordered_map m_imet_route; struct intf { std::string ifname; unsigned int vni; }; - std::unordered_map intf_info; - - std::map m_vlanVniMap; + std::unordered_map m_intf_info; - void macAddVxlan(std::string key, struct in_addr vtep, uint32_t type, uint32_t vni, std::string intf_name); + void addLocalMac(std::string key, std::string op); + void macAddVxlan(std::string key, struct in_addr vtep, std::string type, uint32_t vni, std::string intf_name); void macDelVxlan(std::string auxkey); - void macUpdateVxlanDB(std::string key); void macDelVxlanDB(std::string key); void imetAddRoute(struct in_addr vtep, std::string ifname, uint32_t vni); void imetDelRoute(struct in_addr vtep, std::string ifname, uint32_t vni); - void onMsgNbr(int nlmsg_type, struct nl_object *obj); - void onMsgLink(int nlmsg_type, struct nl_object *obj); + void onMsgNbr(int nlmsg_type, struct nl_object *obj); + void onMsgLink(int nlmsg_type, struct nl_object *obj); }; } diff --git a/fdbsyncd/fdbsyncd.cpp b/fdbsyncd/fdbsyncd.cpp index 6b4123ea64..eeffeb68c1 100644 --- a/fdbsyncd/fdbsyncd.cpp +++ b/fdbsyncd/fdbsyncd.cpp @@ -11,8 +11,6 @@ using namespace std; using namespace swss; -class FdbSync *g_fdbsync; - int main(int argc, char **argv) { Logger::linkToDbNative("fdbsyncd"); @@ -21,9 +19,9 @@ int main(int argc, char **argv) RedisPipeline pipelineAppDB(&appDb); DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); DBConnector log_db(LOGLEVEL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + DBConnector config_db(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); - FdbSync sync(&pipelineAppDB, &stateDb); - g_fdbsync = &sync; + FdbSync sync(&pipelineAppDB, &stateDb, &config_db); NetDispatcher::getInstance().registerMessageHandler(RTM_NEWNEIGH, &sync); NetDispatcher::getInstance().registerMessageHandler(RTM_DELNEIGH, &sync); @@ -34,6 +32,8 @@ int main(int argc, char **argv) try { NetLink netlink; + Selectable *temps; + int ret; Select s; using namespace std::chrono; @@ -44,7 +44,7 @@ int main(int argc, char **argv) */ if (sync.getRestartAssist()->isWarmStartInProgress()) { - sync.getRestartAssist()->readTablesToMap(); + sync.getRestartAssist()->readTablesToMap(); SWSS_LOG_NOTICE("Starting ReconcileTimer"); } @@ -52,36 +52,46 @@ int main(int argc, char **argv) netlink.registerGroup(RTNLGRP_NEIGH); SWSS_LOG_NOTICE("Listens to link and neigh messages..."); netlink.dumpRequest(RTM_GETLINK); + s.addSelectable(&netlink); + ret = s.select(&temps, 1); + if (ret == Select::ERROR) + { + SWSS_LOG_ERROR("Error in RTM_GETLINK dump"); + } + netlink.dumpRequest(RTM_GETNEIGH); - s.addSelectable(&netlink); s.addSelectable(sync.getFdbStateTable()); + s.addSelectable(sync.getCfgEvpnNvoTable()); while (true) { - Selectable *temps; s.select(&temps); - if(temps == (Selectable *)sync.getFdbStateTable()) + if(temps == (Selectable *)sync.getFdbStateTable()) { sync.processStateFdb(); } + else if (temps == (Selectable *)sync.getCfgEvpnNvoTable()) + { + sync.processCfgEvpnNvo(); + } else { /* * If warmstart is in progress, we check the reconcile timer, * if timer expired, we stop the timer and start the reconcile process */ - if (sync.getRestartAssist()->isWarmStartInProgress()) - { - if (sync.getRestartAssist()->checkReconcileTimer(temps)) - { - sync.m_reconcileDone = true; - sync.getRestartAssist()->stopReconcileTimer(s); - sync.getRestartAssist()->reconcile(); - SWSS_LOG_NOTICE("VXLAN FDB VNI Reconcillation Complete (Timer)"); - } - } - } + if (sync.getRestartAssist()->isWarmStartInProgress()) + { + if (sync.getRestartAssist()->checkReconcileTimer(temps)) + { + sync.m_reconcileDone = true; + sync.getRestartAssist()->stopReconcileTimer(s); + sync.getRestartAssist()->reconcile(); + SWSS_LOG_NOTICE("VXLAN FDB VNI Reconcillation Complete (Timer)"); + } + } + } } } catch (const std::exception& e) From 1f907b773d99d8d602731c0ab9ae09fa743b29fc Mon Sep 17 00:00:00 2001 From: Kishore Kunal Date: Tue, 24 Nov 2020 16:09:49 -0800 Subject: [PATCH 24/24] Remove variable not used --- fdbsyncd/fdbsync.cpp | 15 --------------- fdbsyncd/fdbsync.h | 1 - 2 files changed, 16 deletions(-) diff --git a/fdbsyncd/fdbsync.cpp b/fdbsyncd/fdbsync.cpp index 5e94845d26..45915f40e9 100644 --- a/fdbsyncd/fdbsync.cpp +++ b/fdbsyncd/fdbsync.cpp @@ -24,7 +24,6 @@ using namespace swss; FdbSync::FdbSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb, DBConnector *config_db) : m_fdbTable(pipelineAppDB, APP_VXLAN_FDB_TABLE_NAME), m_imetTable(pipelineAppDB, APP_VXLAN_REMOTE_VNI_TABLE_NAME), - m_stateFdbRestoreTable(stateDb, STATE_EVPN_FDB_RESTORE_TABLE_NAME), m_fdbStateTable(stateDb, STATE_FDB_TABLE_NAME), m_cfgEvpnNvoTable(config_db, CFG_VXLAN_EVPN_NVO_TABLE_NAME) { @@ -44,20 +43,6 @@ FdbSync::~FdbSync() } } -// Check if neighbor table is restored in kernel -bool FdbSync::isFdbRestoreDone() -{ - string value; - - m_stateFdbRestoreTable.hget("Flags", "restored", value); - if (value == "true") - { - SWSS_LOG_INFO("neighbor table restore to kernel is done"); - return true; - } - return true; -} - void FdbSync::processCfgEvpnNvo() { std::deque entries; diff --git a/fdbsyncd/fdbsync.h b/fdbsyncd/fdbsync.h index 98661ff589..1d79af95ac 100644 --- a/fdbsyncd/fdbsync.h +++ b/fdbsyncd/fdbsync.h @@ -69,7 +69,6 @@ class FdbSync : public NetMsg bool m_isEvpnNvoExist = false; private: - Table m_stateFdbRestoreTable; ProducerStateTable m_fdbTable; ProducerStateTable m_imetTable; SubscriberStateTable m_fdbStateTable;