Skip to content

Commit 3b84199

Browse files
theasianpianistcscarpitta
authored andcommitted
Fix multi VLAN neighbor learning (sonic-net#3049)
What I did When adding a new neighbor, check if the neighbor IP has already been learned on a different VLAN. If it has, remove the old neighbor entry before adding the new one. Why I did it On Gemini devices, if a neighbor IP moves from an active port in one VLAN to a second VLAN, then back to the first VLAN (with 3 different MAC addresses), orchagent will crash. Even though the MAC address of the last move is different from the first MAC address, orchagent believes the last MAC address to already be programmed in the hardware and tries to set an attribute of the entry which doesn't exist.
1 parent e611f4e commit 3b84199

11 files changed

Lines changed: 643 additions & 335 deletions

orchagent/neighorch.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,27 @@ bool NeighOrch::addNeighbor(const NeighborEntry &neighborEntry, const MacAddress
933933
}
934934
}
935935

936+
PortsOrch* ports_orch = gDirectory.get<PortsOrch*>();
937+
auto vlan_ports = ports_orch->getAllVlans();
938+
939+
for (auto vlan_port: vlan_ports)
940+
{
941+
if (vlan_port == alias)
942+
{
943+
continue;
944+
}
945+
NeighborEntry temp_entry = { ip_address, vlan_port };
946+
if (m_syncdNeighbors.find(temp_entry) != m_syncdNeighbors.end())
947+
{
948+
SWSS_LOG_NOTICE("Neighbor %s on %s already exists, removing before adding new neighbor", ip_address.to_string().c_str(), vlan_port.c_str());
949+
if (!removeNeighbor(temp_entry))
950+
{
951+
SWSS_LOG_ERROR("Failed to remove neighbor %s on %s", ip_address.to_string().c_str(), vlan_port.c_str());
952+
return false;
953+
}
954+
}
955+
}
956+
936957
MuxOrch* mux_orch = gDirectory.get<MuxOrch*>();
937958
bool hw_config = isHwConfigured(neighborEntry);
938959

orchagent/portsorch.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,11 @@ map<string, Port>& PortsOrch::getAllPorts()
13441344
return m_portList;
13451345
}
13461346

1347+
unordered_set<string>& PortsOrch::getAllVlans()
1348+
{
1349+
return m_vlanPorts;
1350+
}
1351+
13471352
bool PortsOrch::getPort(string alias, Port &p)
13481353
{
13491354
SWSS_LOG_ENTER();
@@ -6047,6 +6052,7 @@ bool PortsOrch::addVlan(string vlan_alias)
60476052
m_portList[vlan_alias] = vlan;
60486053
m_port_ref_count[vlan_alias] = 0;
60496054
saiOidToAlias[vlan_oid] = vlan_alias;
6055+
m_vlanPorts.emplace(vlan_alias);
60506056

60516057
return true;
60526058
}
@@ -6113,6 +6119,7 @@ bool PortsOrch::removeVlan(Port vlan)
61136119
saiOidToAlias.erase(vlan.m_vlan_info.vlan_oid);
61146120
m_portList.erase(vlan.m_alias);
61156121
m_port_ref_count.erase(vlan.m_alias);
6122+
m_vlanPorts.erase(vlan.m_alias);
61166123

61176124
return true;
61186125
}

orchagent/portsorch.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define SWSS_PORTSORCH_H
33

44
#include <map>
5+
#include <unordered_set>
56

67
#include "acltable.h"
78
#include "orch.h"
@@ -150,6 +151,8 @@ class PortsOrch : public Orch, public Subject
150151
bool createVlanHostIntf(Port& vl, string hostif_name);
151152
bool removeVlanHostIntf(Port vl);
152153

154+
unordered_set<string>& getAllVlans();
155+
153156
bool createBindAclTableGroup(sai_object_id_t port_oid,
154157
sai_object_id_t acl_table_oid,
155158
sai_object_id_t &group_oid,
@@ -311,6 +314,7 @@ class PortsOrch : public Orch, public Subject
311314
map<int, gearbox_port_t> m_gearboxPortMap;
312315
map<sai_object_id_t, tuple<sai_object_id_t, sai_object_id_t>> m_gearboxPortListLaneMap;
313316

317+
unordered_set<string> m_vlanPorts;
314318
port_config_state_t m_portConfigState = PORT_CONFIG_MISSING;
315319
sai_uint32_t m_portCount;
316320
map<set<uint32_t>, sai_object_id_t> m_portListLaneMap;

tests/mock_tests/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ tests_SOURCES = aclorch_ut.cpp \
4444
mock_table.cpp \
4545
mock_hiredis.cpp \
4646
mock_redisreply.cpp \
47+
mock_sai_api.cpp \
4748
bulker_ut.cpp \
4849
portmgr_ut.cpp \
4950
sflowmgrd_ut.cpp \
@@ -56,6 +57,7 @@ tests_SOURCES = aclorch_ut.cpp \
5657
warmrestartassist_ut.cpp \
5758
test_failure_handling.cpp \
5859
warmrestarthelper_ut.cpp \
60+
neighorch_ut.cpp \
5961
$(top_srcdir)/warmrestart/warmRestartHelper.cpp \
6062
$(top_srcdir)/lib/gearboxutils.cpp \
6163
$(top_srcdir)/lib/subintf.cpp \

tests/mock_tests/flowcounterrouteorch_ut.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ namespace flowcounterrouteorch_test
135135

136136
ASSERT_EQ(gPortsOrch, nullptr);
137137
gPortsOrch = new PortsOrch(m_app_db.get(), m_state_db.get(), ports_tables, m_chassis_app_db.get());
138+
gDirectory.set(gPortsOrch);
138139

139140
vector<string> vnet_tables = {
140141
APP_VNET_RT_TABLE_NAME,

0 commit comments

Comments
 (0)