Skip to content

Commit c9ae6aa

Browse files
Fix issue: there is no retry while creating a RIF which is in removing state (sonic-net#2679)
* Fix issue: there is no retry while creating a RIF which is in removing state
1 parent 79afcb3 commit c9ae6aa

File tree

6 files changed

+350
-1
lines changed

6 files changed

+350
-1
lines changed

orchagent/intfsorch.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,11 @@ bool IntfsOrch::setIntf(const string& alias, sai_object_id_t vrf_id, const IpPre
470470
{
471471
SWSS_LOG_ENTER();
472472

473+
if (m_removingIntfses.find(alias) != m_removingIntfses.end())
474+
{
475+
return false;
476+
}
477+
473478
Port port;
474479
gPortsOrch->getPort(alias, port);
475480

@@ -1076,10 +1081,12 @@ void IntfsOrch::doTask(Consumer &consumer)
10761081
{
10771082
if (removeIntf(alias, port.m_vr_id, ip_prefix_in_key ? &ip_prefix : nullptr))
10781083
{
1084+
m_removingIntfses.erase(alias);
10791085
it = consumer.m_toSync.erase(it);
10801086
}
10811087
else
10821088
{
1089+
m_removingIntfses.insert(alias);
10831090
it++;
10841091
continue;
10851092
}

orchagent/intfsorch.h

+2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ class IntfsOrch : public Orch
9292
unique_ptr<ProducerTable> m_flexCounterTable;
9393
unique_ptr<ProducerTable> m_flexCounterGroupTable;
9494

95+
std::set<std::string> m_removingIntfses;
96+
9597
std::string getRifFlexCounterTableKey(std::string s);
9698

9799
bool addRouterIntfs(sai_object_id_t vrf_id, Port &port, string loopbackAction);

tests/mock_tests/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ tests_SOURCES = aclorch_ut.cpp \
4949
swssnet_ut.cpp \
5050
flowcounterrouteorch_ut.cpp \
5151
orchdaemon_ut.cpp \
52+
intfsorch_ut.cpp \
5253
warmrestartassist_ut.cpp \
5354
test_failure_handling.cpp \
5455
$(top_srcdir)/lib/gearboxutils.cpp \

tests/mock_tests/intfsorch_ut.cpp

+330
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
#define private public // make Directory::m_values available to clean it.
2+
#include "directory.h"
3+
#undef private
4+
#include "gtest/gtest.h"
5+
#include "ut_helper.h"
6+
#include "mock_orchagent_main.h"
7+
#include "mock_table.h"
8+
#include <memory>
9+
#include <vector>
10+
11+
12+
13+
namespace intfsorch_test
14+
{
15+
using namespace std;
16+
17+
int create_rif_count = 0;
18+
int remove_rif_count = 0;
19+
sai_router_interface_api_t *pold_sai_rif_api;
20+
sai_router_interface_api_t ut_sai_rif_api;
21+
22+
sai_status_t _ut_create_router_interface(
23+
_Out_ sai_object_id_t *router_interface_id,
24+
_In_ sai_object_id_t switch_id,
25+
_In_ uint32_t attr_count,
26+
_In_ const sai_attribute_t *attr_list)
27+
{
28+
++create_rif_count;
29+
return SAI_STATUS_SUCCESS;
30+
}
31+
32+
sai_status_t _ut_remove_router_interface(
33+
_In_ sai_object_id_t router_interface_id)
34+
{
35+
++remove_rif_count;
36+
return SAI_STATUS_SUCCESS;
37+
}
38+
39+
struct IntfsOrchTest : public ::testing::Test
40+
{
41+
shared_ptr<swss::DBConnector> m_app_db;
42+
shared_ptr<swss::DBConnector> m_config_db;
43+
shared_ptr<swss::DBConnector> m_state_db;
44+
shared_ptr<swss::DBConnector> m_chassis_app_db;
45+
46+
//sai_router_interface_api_t *old_sai_rif_api_ptr;
47+
48+
//sai_create_router_interface_fn old_create_rif;
49+
//sai_remove_router_interface_fn old_remove_rif;
50+
void SetUp() override
51+
{
52+
map<string, string> profile = {
53+
{ "SAI_VS_SWITCH_TYPE", "SAI_VS_SWITCH_TYPE_BCM56850" },
54+
{ "KV_DEVICE_MAC_ADDRESS", "20:03:04:05:06:00" }
55+
};
56+
57+
ut_helper::initSaiApi(profile);
58+
pold_sai_rif_api = sai_router_intfs_api;
59+
ut_sai_rif_api = *sai_router_intfs_api;
60+
sai_router_intfs_api = &ut_sai_rif_api;
61+
62+
sai_router_intfs_api->create_router_interface = _ut_create_router_interface;
63+
sai_router_intfs_api->remove_router_interface = _ut_remove_router_interface;
64+
65+
m_app_db = make_shared<swss::DBConnector>("APPL_DB", 0);
66+
m_config_db = make_shared<swss::DBConnector>("CONFIG_DB", 0);
67+
m_state_db = make_shared<swss::DBConnector>("STATE_DB", 0);
68+
m_chassis_app_db = make_shared<swss::DBConnector>("CHASSIS_APP_DB", 0);
69+
70+
sai_attribute_t attr;
71+
72+
attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
73+
attr.value.booldata = true;
74+
75+
auto status = sai_switch_api->create_switch(&gSwitchId, 1, &attr);
76+
ASSERT_EQ(status, SAI_STATUS_SUCCESS);
77+
78+
// Get switch source MAC address
79+
attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS;
80+
status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
81+
82+
ASSERT_EQ(status, SAI_STATUS_SUCCESS);
83+
84+
gMacAddress = attr.value.mac;
85+
86+
attr.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID;
87+
status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
88+
89+
ASSERT_EQ(status, SAI_STATUS_SUCCESS);
90+
91+
gVirtualRouterId = attr.value.oid;
92+
93+
94+
ASSERT_EQ(gCrmOrch, nullptr);
95+
gCrmOrch = new CrmOrch(m_config_db.get(), CFG_CRM_TABLE_NAME);
96+
97+
TableConnector stateDbSwitchTable(m_state_db.get(), "SWITCH_CAPABILITY");
98+
TableConnector conf_asic_sensors(m_config_db.get(), CFG_ASIC_SENSORS_TABLE_NAME);
99+
TableConnector app_switch_table(m_app_db.get(), APP_SWITCH_TABLE_NAME);
100+
101+
vector<TableConnector> switch_tables = {
102+
conf_asic_sensors,
103+
app_switch_table
104+
};
105+
106+
ASSERT_EQ(gSwitchOrch, nullptr);
107+
gSwitchOrch = new SwitchOrch(m_app_db.get(), switch_tables, stateDbSwitchTable);
108+
109+
// Create dependencies ...
110+
TableConnector stateDbBfdSessionTable(m_state_db.get(), STATE_BFD_SESSION_TABLE_NAME);
111+
gBfdOrch = new BfdOrch(m_app_db.get(), APP_BFD_SESSION_TABLE_NAME, stateDbBfdSessionTable);
112+
113+
const int portsorch_base_pri = 40;
114+
vector<table_name_with_pri_t> ports_tables = {
115+
{ APP_PORT_TABLE_NAME, portsorch_base_pri + 5 },
116+
{ APP_VLAN_TABLE_NAME, portsorch_base_pri + 2 },
117+
{ APP_VLAN_MEMBER_TABLE_NAME, portsorch_base_pri },
118+
{ APP_LAG_TABLE_NAME, portsorch_base_pri + 4 },
119+
{ APP_LAG_MEMBER_TABLE_NAME, portsorch_base_pri }
120+
};
121+
122+
vector<string> flex_counter_tables = {
123+
CFG_FLEX_COUNTER_TABLE_NAME
124+
};
125+
auto* flexCounterOrch = new FlexCounterOrch(m_config_db.get(), flex_counter_tables);
126+
gDirectory.set(flexCounterOrch);
127+
128+
ASSERT_EQ(gPortsOrch, nullptr);
129+
gPortsOrch = new PortsOrch(m_app_db.get(), m_state_db.get(), ports_tables, m_chassis_app_db.get());
130+
131+
vector<string> vnet_tables = {
132+
APP_VNET_RT_TABLE_NAME,
133+
APP_VNET_RT_TUNNEL_TABLE_NAME
134+
};
135+
136+
vector<string> cfg_vnet_tables = {
137+
CFG_VNET_RT_TABLE_NAME,
138+
CFG_VNET_RT_TUNNEL_TABLE_NAME
139+
};
140+
141+
auto* vnet_orch = new VNetOrch(m_app_db.get(), APP_VNET_TABLE_NAME);
142+
gDirectory.set(vnet_orch);
143+
auto* cfg_vnet_rt_orch = new VNetCfgRouteOrch(m_config_db.get(), m_app_db.get(), cfg_vnet_tables);
144+
gDirectory.set(cfg_vnet_rt_orch);
145+
auto* vnet_rt_orch = new VNetRouteOrch(m_app_db.get(), vnet_tables, vnet_orch);
146+
gDirectory.set(vnet_rt_orch);
147+
ASSERT_EQ(gVrfOrch, nullptr);
148+
gVrfOrch = new VRFOrch(m_app_db.get(), APP_VRF_TABLE_NAME, m_state_db.get(), STATE_VRF_OBJECT_TABLE_NAME);
149+
gDirectory.set(gVrfOrch);
150+
151+
ASSERT_EQ(gIntfsOrch, nullptr);
152+
gIntfsOrch = new IntfsOrch(m_app_db.get(), APP_INTF_TABLE_NAME, gVrfOrch, m_chassis_app_db.get());
153+
154+
const int fdborch_pri = 20;
155+
156+
vector<table_name_with_pri_t> app_fdb_tables = {
157+
{ APP_FDB_TABLE_NAME, FdbOrch::fdborch_pri},
158+
{ APP_VXLAN_FDB_TABLE_NAME, FdbOrch::fdborch_pri},
159+
{ APP_MCLAG_FDB_TABLE_NAME, fdborch_pri}
160+
};
161+
162+
TableConnector stateDbFdb(m_state_db.get(), STATE_FDB_TABLE_NAME);
163+
TableConnector stateMclagDbFdb(m_state_db.get(), STATE_MCLAG_REMOTE_FDB_TABLE_NAME);
164+
ASSERT_EQ(gFdbOrch, nullptr);
165+
gFdbOrch = new FdbOrch(m_app_db.get(), app_fdb_tables, stateDbFdb, stateMclagDbFdb, gPortsOrch);
166+
167+
ASSERT_EQ(gNeighOrch, nullptr);
168+
gNeighOrch = new NeighOrch(m_app_db.get(), APP_NEIGH_TABLE_NAME, gIntfsOrch, gFdbOrch, gPortsOrch, m_chassis_app_db.get());
169+
170+
auto* tunnel_decap_orch = new TunnelDecapOrch(m_app_db.get(), APP_TUNNEL_DECAP_TABLE_NAME);
171+
vector<string> mux_tables = {
172+
CFG_MUX_CABLE_TABLE_NAME,
173+
CFG_PEER_SWITCH_TABLE_NAME
174+
};
175+
auto* mux_orch = new MuxOrch(m_config_db.get(), mux_tables, tunnel_decap_orch, gNeighOrch, gFdbOrch);
176+
gDirectory.set(mux_orch);
177+
178+
ASSERT_EQ(gFgNhgOrch, nullptr);
179+
const int fgnhgorch_pri = 15;
180+
181+
vector<table_name_with_pri_t> fgnhg_tables = {
182+
{ CFG_FG_NHG, fgnhgorch_pri },
183+
{ CFG_FG_NHG_PREFIX, fgnhgorch_pri },
184+
{ CFG_FG_NHG_MEMBER, fgnhgorch_pri }
185+
};
186+
gFgNhgOrch = new FgNhgOrch(m_config_db.get(), m_app_db.get(), m_state_db.get(), fgnhg_tables, gNeighOrch, gIntfsOrch, gVrfOrch);
187+
188+
ASSERT_EQ(gSrv6Orch, nullptr);
189+
vector<string> srv6_tables = {
190+
APP_SRV6_SID_LIST_TABLE_NAME,
191+
APP_SRV6_MY_SID_TABLE_NAME
192+
};
193+
gSrv6Orch = new Srv6Orch(m_app_db.get(), srv6_tables, gSwitchOrch, gVrfOrch, gNeighOrch);
194+
195+
// Start FlowCounterRouteOrch
196+
static const vector<string> route_pattern_tables = {
197+
CFG_FLOW_COUNTER_ROUTE_PATTERN_TABLE_NAME,
198+
};
199+
gFlowCounterRouteOrch = new FlowCounterRouteOrch(m_config_db.get(), route_pattern_tables);
200+
201+
ASSERT_EQ(gRouteOrch, nullptr);
202+
const int routeorch_pri = 5;
203+
vector<table_name_with_pri_t> route_tables = {
204+
{ APP_ROUTE_TABLE_NAME, routeorch_pri },
205+
{ APP_LABEL_ROUTE_TABLE_NAME, routeorch_pri }
206+
};
207+
gRouteOrch = new RouteOrch(m_app_db.get(), route_tables, gSwitchOrch, gNeighOrch, gIntfsOrch, gVrfOrch, gFgNhgOrch, gSrv6Orch);
208+
gNhgOrch = new NhgOrch(m_app_db.get(), APP_NEXTHOP_GROUP_TABLE_NAME);
209+
210+
// Recreate buffer orch to read populated data
211+
vector<string> buffer_tables = { APP_BUFFER_POOL_TABLE_NAME,
212+
APP_BUFFER_PROFILE_TABLE_NAME,
213+
APP_BUFFER_QUEUE_TABLE_NAME,
214+
APP_BUFFER_PG_TABLE_NAME,
215+
APP_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME,
216+
APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME };
217+
218+
gBufferOrch = new BufferOrch(m_app_db.get(), m_config_db.get(), m_state_db.get(), buffer_tables);
219+
220+
Table portTable = Table(m_app_db.get(), APP_PORT_TABLE_NAME);
221+
222+
// Get SAI default ports to populate DB
223+
auto ports = ut_helper::getInitialSaiPorts();
224+
225+
// Populate pot table with SAI ports
226+
for (const auto &it : ports)
227+
{
228+
portTable.set(it.first, it.second);
229+
}
230+
// Set PortConfigDone
231+
portTable.set("PortConfigDone", { { "count", to_string(ports.size()) } });
232+
gPortsOrch->addExistingData(&portTable);
233+
static_cast<Orch *>(gPortsOrch)->doTask();
234+
portTable.set("PortInitDone", { { "lanes", "0" } });
235+
gPortsOrch->addExistingData(&portTable);
236+
static_cast<Orch *>(gPortsOrch)->doTask();
237+
}
238+
239+
void TearDown() override
240+
{
241+
gDirectory.m_values.clear();
242+
243+
delete gCrmOrch;
244+
gCrmOrch = nullptr;
245+
246+
delete gSwitchOrch;
247+
gSwitchOrch = nullptr;
248+
249+
delete gBfdOrch;
250+
gBfdOrch = nullptr;
251+
252+
delete gNeighOrch;
253+
gNeighOrch = nullptr;
254+
255+
delete gFdbOrch;
256+
gFdbOrch = nullptr;
257+
258+
delete gPortsOrch;
259+
gPortsOrch = nullptr;
260+
261+
delete gIntfsOrch;
262+
gIntfsOrch = nullptr;
263+
264+
delete gFgNhgOrch;
265+
gFgNhgOrch = nullptr;
266+
267+
delete gSrv6Orch;
268+
gSrv6Orch = nullptr;
269+
270+
delete gRouteOrch;
271+
gRouteOrch = nullptr;
272+
273+
delete gNhgOrch;
274+
gNhgOrch = nullptr;
275+
276+
delete gBufferOrch;
277+
gBufferOrch = nullptr;
278+
279+
delete gVrfOrch;
280+
gVrfOrch = nullptr;
281+
282+
delete gFlowCounterRouteOrch;
283+
gFlowCounterRouteOrch = nullptr;
284+
285+
sai_router_intfs_api = pold_sai_rif_api;
286+
ut_helper::uninitSaiApi();
287+
}
288+
};
289+
290+
TEST_F(IntfsOrchTest, IntfsOrchDeleteCreateRetry)
291+
{
292+
// create a interface
293+
std::deque<KeyOpFieldsValuesTuple> entries;
294+
entries.push_back({"Ethernet0", "SET", { {"mtu", "9100"}}});
295+
auto consumer = dynamic_cast<Consumer *>(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME));
296+
consumer->addToSync(entries);
297+
auto current_create_count = create_rif_count;
298+
static_cast<Orch *>(gIntfsOrch)->doTask();
299+
ASSERT_EQ(current_create_count + 1, create_rif_count);
300+
301+
// create dependency to the interface
302+
gIntfsOrch->increaseRouterIntfsRefCount("Ethernet0");
303+
304+
// delete the interface, expect retry because dependency exists
305+
entries.clear();
306+
entries.push_back({"Ethernet0", "DEL", { {} }});
307+
consumer = dynamic_cast<Consumer *>(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME));
308+
consumer->addToSync(entries);
309+
auto current_remove_count = remove_rif_count;
310+
static_cast<Orch *>(gIntfsOrch)->doTask();
311+
ASSERT_EQ(current_remove_count, remove_rif_count);
312+
313+
// create the interface again, expect retry because interface is in removing
314+
entries.clear();
315+
entries.push_back({"Ethernet0", "SET", { {"mtu", "9100"}}});
316+
consumer = dynamic_cast<Consumer *>(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME));
317+
consumer->addToSync(entries);
318+
current_create_count = create_rif_count;
319+
static_cast<Orch *>(gIntfsOrch)->doTask();
320+
ASSERT_EQ(current_create_count, create_rif_count);
321+
322+
// remove the dependency, expect delete and create a new one
323+
gIntfsOrch->decreaseRouterIntfsRefCount("Ethernet0");
324+
current_create_count = create_rif_count;
325+
current_remove_count = remove_rif_count;
326+
static_cast<Orch *>(gIntfsOrch)->doTask();
327+
ASSERT_EQ(current_create_count + 1, create_rif_count);
328+
ASSERT_EQ(current_remove_count + 1, remove_rif_count);
329+
}
330+
}

tests/mock_tests/orchdaemon_ut.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ namespace orchdaemon_test
3939

4040
~OrchDaemonTest()
4141
{
42-
42+
sai_switch_api = nullptr;
4343
};
4444
};
4545

0 commit comments

Comments
 (0)