@@ -15,14 +15,13 @@ using namespace swss;
15
15
#define LAG_PREFIX " PortChannel"
16
16
#define LOOPBACK_PREFIX " Loopback"
17
17
#define VNET_PREFIX " Vnet"
18
+ #define MTU_INHERITANCE " 0"
18
19
#define VRF_PREFIX " Vrf"
19
20
20
21
#define LOOPBACK_DEFAULT_MTU_STR " 65536"
21
22
22
23
IntfMgr::IntfMgr (DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames) :
23
24
Orch(cfgDb, tableNames),
24
- m_cfgIntfTable(cfgDb, CFG_INTF_TABLE_NAME),
25
- m_cfgVlanIntfTable(cfgDb, CFG_VLAN_INTF_TABLE_NAME),
26
25
m_statePortTable(stateDb, STATE_PORT_TABLE_NAME),
27
26
m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME),
28
27
m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME),
@@ -167,6 +166,157 @@ bool IntfMgr::isIntfChangeVrf(const string &alias, const string &vrfName)
167
166
return false ;
168
167
}
169
168
169
+ void IntfMgr::addHostSubIntf (const string&intf, const string &subIntf, const string &vlan)
170
+ {
171
+ // TODO: remove when validation check at mgmt is in place
172
+ for (const auto &c : intf)
173
+ {
174
+ if (!isalnum (c))
175
+ {
176
+ SWSS_LOG_ERROR (" Invalid parent port name %s for host sub interface %s" , intf.c_str (), subIntf.c_str ());
177
+ return ;
178
+ }
179
+ }
180
+ for (const auto &c : vlan)
181
+ {
182
+ if (!isdigit (c))
183
+ {
184
+ SWSS_LOG_ERROR (" Invalid vlan id %s for host sub interface %s" , vlan.c_str (), subIntf.c_str ());
185
+ return ;
186
+ }
187
+ }
188
+
189
+ stringstream cmd;
190
+ string res;
191
+
192
+ cmd << IP_CMD << " link add link " << intf << " name " << subIntf << " type vlan id " << vlan;
193
+ EXEC_WITH_ERROR_THROW (cmd.str (), res);
194
+ }
195
+
196
+ void IntfMgr::setHostSubIntfMtu (const string &subIntf, const string &mtu)
197
+ {
198
+ // TODO: remove when validation check at mgmt is in place
199
+ size_t found = subIntf.find (VLAN_SUB_INTERFACE_SEPARATOR);
200
+ if (found == string::npos)
201
+ {
202
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
203
+ return ;
204
+ }
205
+ size_t i = 0 ;
206
+ for (const auto &c : subIntf)
207
+ {
208
+ if (i < found && !isalnum (c))
209
+ {
210
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
211
+ return ;
212
+ }
213
+ else if (i > found && !isdigit (c))
214
+ {
215
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
216
+ return ;
217
+ }
218
+ i++;
219
+ }
220
+
221
+ stringstream cmd;
222
+ string res;
223
+
224
+ cmd << IP_CMD << " link set " << subIntf << " mtu " << mtu;
225
+ EXEC_WITH_ERROR_THROW (cmd.str (), res);
226
+ }
227
+
228
+ void IntfMgr::setHostSubIntfAdminStatus (const string &subIntf, const string &adminStatus)
229
+ {
230
+ // TODO: remove when validation check at mgmt is in place
231
+ size_t found = subIntf.find (VLAN_SUB_INTERFACE_SEPARATOR);
232
+ if (found == string::npos)
233
+ {
234
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
235
+ return ;
236
+ }
237
+ size_t i = 0 ;
238
+ for (const auto &c : subIntf)
239
+ {
240
+ if (i < found && !isalnum (c))
241
+ {
242
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
243
+ return ;
244
+ }
245
+ else if (i > found && !isdigit (c))
246
+ {
247
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
248
+ return ;
249
+ }
250
+ i++;
251
+ }
252
+
253
+ stringstream cmd;
254
+ string res;
255
+
256
+ cmd << IP_CMD << " link set " << subIntf << " " << adminStatus;
257
+ EXEC_WITH_ERROR_THROW (cmd.str (), res);
258
+ }
259
+
260
+ void IntfMgr::removeHostSubIntf (const string &subIntf)
261
+ {
262
+ // TODO: remove when validation check at mgmt is in place
263
+ size_t found = subIntf.find (VLAN_SUB_INTERFACE_SEPARATOR);
264
+ if (found == string::npos)
265
+ {
266
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
267
+ return ;
268
+ }
269
+ size_t i = 0 ;
270
+ for (const auto &c : subIntf)
271
+ {
272
+ if (i < found && !isalnum (c))
273
+ {
274
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
275
+ return ;
276
+ }
277
+ else if (i > found && !isdigit (c))
278
+ {
279
+ SWSS_LOG_ERROR (" Invalid host sub interface name: %s" , subIntf.c_str ());
280
+ return ;
281
+ }
282
+ i++;
283
+ }
284
+
285
+ stringstream cmd;
286
+ string res;
287
+
288
+ cmd << IP_CMD << " link del " << subIntf;
289
+ EXEC_WITH_ERROR_THROW (cmd.str (), res);
290
+ }
291
+
292
+ void IntfMgr::setSubIntfStateOk (const string &alias)
293
+ {
294
+ vector<FieldValueTuple> fvTuples = {{" state" , " ok" }};
295
+
296
+ if (!alias.compare (0 , strlen (LAG_PREFIX), LAG_PREFIX))
297
+ {
298
+ m_stateLagTable.set (alias, fvTuples);
299
+ }
300
+ else
301
+ {
302
+ // EthernetX using PORT_TABLE
303
+ m_statePortTable.set (alias, fvTuples);
304
+ }
305
+ }
306
+
307
+ void IntfMgr::removeSubIntfState (const string &alias)
308
+ {
309
+ if (!alias.compare (0 , strlen (LAG_PREFIX), LAG_PREFIX))
310
+ {
311
+ m_stateLagTable.del (alias);
312
+ }
313
+ else
314
+ {
315
+ // EthernetX using PORT_TABLE
316
+ m_statePortTable.del (alias);
317
+ }
318
+ }
319
+
170
320
bool IntfMgr::isIntfStateOk (const string &alias)
171
321
{
172
322
vector<FieldValueTuple> temp;
@@ -217,23 +367,43 @@ bool IntfMgr::isIntfStateOk(const string &alias)
217
367
}
218
368
219
369
bool IntfMgr::doIntfGeneralTask (const vector<string>& keys,
220
- const vector<FieldValueTuple>& data,
370
+ vector<FieldValueTuple> data,
221
371
const string& op)
222
372
{
223
373
SWSS_LOG_ENTER ();
224
374
225
375
string alias (keys[0 ]);
226
- string vrf_name = " " ;
376
+ string vlanId;
377
+ string subIntfAlias;
378
+ size_t found = alias.find (VLAN_SUB_INTERFACE_SEPARATOR);
379
+ if (found != string::npos)
380
+ {
381
+ // This is a sub interface
382
+ // subIntfAlias holds the complete sub interface name
383
+ // while alias becomes the parent interface
384
+ subIntfAlias = alias;
385
+ vlanId = alias.substr (found + 1 );
386
+ alias = alias.substr (0 , found);
387
+ }
227
388
bool is_lo = !alias.compare (0 , strlen (LOOPBACK_PREFIX), LOOPBACK_PREFIX);
228
389
390
+ string vrf_name = " " ;
391
+ string mtu = " " ;
392
+ string adminStatus = " " ;
229
393
for (auto idx : data)
230
394
{
231
395
const auto &field = fvField (idx);
232
396
const auto &value = fvValue (idx);
397
+
233
398
if (field == " vnet_name" || field == " vrf_name" )
234
399
{
235
400
vrf_name = value;
236
401
}
402
+
403
+ if (field == " admin_status" )
404
+ {
405
+ adminStatus = value;
406
+ }
237
407
}
238
408
239
409
if (op == SET_COMMAND)
@@ -256,16 +426,73 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
256
426
SWSS_LOG_ERROR (" %s can not change to %s directly, skipping" , alias.c_str (), vrf_name.c_str ());
257
427
return true ;
258
428
}
429
+
259
430
if (is_lo)
260
431
{
261
432
addLoopbackIntf (alias);
262
433
}
434
+
263
435
if (!vrf_name.empty ())
264
436
{
265
437
setIntfVrf (alias, vrf_name);
266
438
}
267
- m_appIntfTableProducer.set (alias, data);
268
- m_stateIntfTable.hset (alias, " vrf" , vrf_name);
439
+
440
+ if (!subIntfAlias.empty ())
441
+ {
442
+ if (m_subIntfList.find (subIntfAlias) == m_subIntfList.end ())
443
+ {
444
+ try
445
+ {
446
+ addHostSubIntf (alias, subIntfAlias, vlanId);
447
+ }
448
+ catch (const std::runtime_error &e)
449
+ {
450
+ SWSS_LOG_NOTICE (" Sub interface ip link add failure. Runtime error: %s" , e.what ());
451
+ return false ;
452
+ }
453
+
454
+ m_subIntfList.insert (subIntfAlias);
455
+ }
456
+
457
+ if (!mtu.empty ())
458
+ {
459
+ try
460
+ {
461
+ setHostSubIntfMtu (subIntfAlias, mtu);
462
+ }
463
+ catch (const std::runtime_error &e)
464
+ {
465
+ SWSS_LOG_NOTICE (" Sub interface ip link set mtu failure. Runtime error: %s" , e.what ());
466
+ return false ;
467
+ }
468
+ }
469
+ else
470
+ {
471
+ FieldValueTuple fvTuple (" mtu" , MTU_INHERITANCE);
472
+ data.push_back (fvTuple);
473
+ }
474
+
475
+ if (adminStatus.empty ())
476
+ {
477
+ adminStatus = " up" ;
478
+ FieldValueTuple fvTuple (" admin_status" , adminStatus);
479
+ data.push_back (fvTuple);
480
+ }
481
+ try
482
+ {
483
+ setHostSubIntfAdminStatus (subIntfAlias, adminStatus);
484
+ }
485
+ catch (const std::runtime_error &e)
486
+ {
487
+ SWSS_LOG_NOTICE (" Sub interface ip link set admin status %s failure. Runtime error: %s" , adminStatus.c_str (), e.what ());
488
+ return false ;
489
+ }
490
+
491
+ // set STATE_DB port state
492
+ setSubIntfStateOk (subIntfAlias);
493
+ }
494
+ m_appIntfTableProducer.set (subIntfAlias.empty () ? alias : subIntfAlias, data);
495
+ m_stateIntfTable.hset (subIntfAlias.empty () ? alias : subIntfAlias, " vrf" , vrf_name);
269
496
}
270
497
else if (op == DEL_COMMAND)
271
498
{
@@ -275,13 +502,24 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
275
502
{
276
503
return false ;
277
504
}
505
+
278
506
setIntfVrf (alias, " " );
507
+
279
508
if (is_lo)
280
509
{
281
510
delLoopbackIntf (alias);
282
511
}
283
- m_appIntfTableProducer.del (alias);
284
- m_stateIntfTable.del (alias);
512
+
513
+ if (!subIntfAlias.empty ())
514
+ {
515
+ removeHostSubIntf (subIntfAlias);
516
+ m_subIntfList.erase (subIntfAlias);
517
+
518
+ removeSubIntfState (subIntfAlias);
519
+ }
520
+
521
+ m_appIntfTableProducer.del (subIntfAlias.empty () ? alias : subIntfAlias);
522
+ m_stateIntfTable.del (subIntfAlias.empty () ? alias : subIntfAlias);
285
523
}
286
524
else
287
525
{
@@ -304,7 +542,7 @@ bool IntfMgr::doIntfAddrTask(const vector<string>& keys,
304
542
if (op == SET_COMMAND)
305
543
{
306
544
/*
307
- * Don't proceed if port/LAG/VLAN and intfGeneral are not ready yet.
545
+ * Don't proceed if port/LAG/VLAN/subport and intfGeneral is not ready yet.
308
546
* The pending task will be checked periodically and retried.
309
547
*/
310
548
if (!isIntfStateOk (alias) || !isIntfCreated (alias))
0 commit comments