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
+ }
0 commit comments