From 04d5906b4f544e35d37286b99fc11050d8168922 Mon Sep 17 00:00:00 2001 From: peter_yu Date: Thu, 12 May 2022 09:38:33 +0000 Subject: [PATCH] [neighsync] Modification for ignoring neighbor entries 1. [neighsync] Ignore neighbor entries on non-router-interface 2. Don't ignore reserved IPv4 LL address - For BGP unnumber, reserved IPv4 LL (169.254.0.1) will be used as next hop. FRR configure it as permanent neighbor when BGP session is established. We ignore neighbor entry learned on non-router interface currently, this reserved IPv4 LL will not be synced if we don't configure use-link-local-only before this neighbor learnt event. 3. [neighsyncd] Ignore null MAC address neighbor while adding neighbor By executing the following commands would cause the netlink message bring a NULL MAC neighbor and cause the neighsyncd exception. The libnl api `nl_addr2str` would output the string `"none"` if the lladdr is `NULL`, and the string is an exception case for the class `MacAddress`. Therefore, this commit add to ignore this condition while the `rtnl_neigh_get_lladdr` can not retrieve the lladdr successfully ``` ip neigh replace 1.2.3.8 lladdr 00:33:55:66:55:66 dev Vlan10 nud noarp ip neigh replace 1.2.3.8 lladdr 00:33:55:66:55:66 dev Vlan10 nud none ``` --- neighsyncd/neighsync.cpp | 72 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/neighsyncd/neighsync.cpp b/neighsyncd/neighsync.cpp index 46f51b9266..b80d2e66a2 100644 --- a/neighsyncd/neighsync.cpp +++ b/neighsyncd/neighsync.cpp @@ -18,6 +18,9 @@ using namespace std; using namespace swss; +#define VLAN_SUB_INTERFACE_SEPARATOR "." +#define RESERVED_IPV4_LL "169.254.0.1" + NeighSync::NeighSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb, DBConnector *cfgDb) : m_neighTable(pipelineAppDB, APP_NEIGH_TABLE_NAME), m_stateNeighRestoreTable(stateDb, STATE_NEIGH_RESTORE_TABLE_NAME), @@ -55,11 +58,50 @@ bool NeighSync::isNeighRestoreDone() return false; } +Table *NeighSync::getInterfaceTable(const std::string &intfName) +{ + if (intfName.find(FRONT_PANEL_PORT_PREFIX) != string::npos) + { + if (intfName.find(VLAN_SUB_INTERFACE_SEPARATOR) != string::npos) + return &m_cfgSubInterfaceTable; + return &m_cfgInterfaceTable; + } + else if (intfName.find(PORTCHANNEL_PREFIX) != string::npos) + { + if (intfName.find(VLAN_SUB_INTERFACE_SEPARATOR) != string::npos) + return &m_cfgSubInterfaceTable; + return &m_cfgLagInterfaceTable; + } + else if (intfName.find(VLAN_PREFIX) != string::npos) + { + return &m_cfgVlanInterfaceTable; + } + else if (intfName.find(VLAN_SUB_INTERFACE_SEPARATOR) != string::npos) + { + if ((intfName.find(FRONT_PANEL_PORT_PREFIX) != string::npos) || (intfName.find(PORTCHANNEL_PREFIX) != string::npos)) + return &m_cfgSubInterfaceTable; + } + return nullptr; +} + +bool NeighSync::isRouterInterface(const std::string &intfName) +{ + vector values; + Table *intfTable_p = nullptr; + intfTable_p = getInterfaceTable(intfName); + if ((intfTable_p != nullptr) && intfTable_p->get(intfName, values)) + { + return true; + } + return false; +} + void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj) { char ipStr[MAX_ADDR_SIZE + 1] = {0}; char macStr[MAX_ADDR_SIZE + 1] = {0}; struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj; + struct nl_addr *lladdr = NULL; string key; string family; string intfName; @@ -133,6 +175,19 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj) delete_key = true; } + /* Ignore the following neighbor entries + * - learned on non-router interface + * - learned on SAG disabled interface + * For reserved IPv4 link-local address (169.254.0.1) used as next hop for BGP unnumber, + * this entry shouldn't be ignored even if it satisfy the above condition + * */ + //if (!delete_key && !isRouterInterface(intfName) && !isSagEnabled(intfName) && strcmp(ipStr, RESERVED_IPV4_LL)) ///FIXME, isSagEnabled + if (!delete_key && !isRouterInterface(intfName) && strcmp(ipStr, RESERVED_IPV4_LL)) + { + SWSS_LOG_INFO("Ignore neighbor %s on non-router-interface %s", ipStr, intfName.c_str()); + return; + } + if (use_zero_mac) { std::string zero_mac = "00:00:00:00:00:00"; @@ -140,7 +195,14 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj) } else { - nl_addr2str(rtnl_neigh_get_lladdr(neigh), macStr, MAX_ADDR_SIZE); + /* Get the link-layer address */ + lladdr = rtnl_neigh_get_lladdr(neigh); + + /* Check if the link-layer address is NULL */ + if (lladdr != NULL) + { + nl_addr2str(lladdr, macStr, MAX_ADDR_SIZE); + } } if (!delete_key && !strncmp(macStr, "none", MAX_ADDR_SIZE)) @@ -149,10 +211,12 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj) return; } - /* Ignore neighbor entries with Broadcast Mac - Trigger for directed broadcast */ - if (!delete_key && (MacAddress(macStr) == MacAddress("ff:ff:ff:ff:ff:ff"))) + /* Ignore neighbor entries with Broadcast/Null Mac */ + if (!delete_key + && ((lladdr == NULL) + || (MacAddress(macStr) == MacAddress("ff:ff:ff:ff:ff:ff")))) { - SWSS_LOG_INFO("Broadcast Mac received, ignoring for %s", ipStr); + SWSS_LOG_INFO("Broadcast/Null Mac received, ignoring for %s", ipStr); return; }