Skip to content

Commit 56d66a1

Browse files
wendanilguohan
authored andcommitted
Sub port interface implementation (sonic-net#969)
IntfMgrd: Listen to CONFIG_DB VLAN_SUB_INTERFACE table. Process host sub port interface: create, set (admin_status), and remove using ip link and ip address system call, and update the STATE_DB Relay the VLAN_SUB_INTERFACE table operation and field-value content to APPL_DB INTF_TABLE. IntfOrch: Listen to APPL_DB INTF_TABLE. Process sub port interface on physical port: create (a Port object for sub port interface), set (admin_status), and remove. PortsOrch: Add member function to create a Port object for sub port interface vs unit test: sub port interface creation sub port interface add IP addresses sub port interface admin status change sub port interface remove IP addresses sub port interface removal Signed-off-by: Wenda Ni <[email protected]>
1 parent c57fc34 commit 56d66a1

13 files changed

+908
-27
lines changed

cfgmgr/intfmgr.cpp

+247-9
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@ using namespace swss;
1515
#define LAG_PREFIX "PortChannel"
1616
#define LOOPBACK_PREFIX "Loopback"
1717
#define VNET_PREFIX "Vnet"
18+
#define MTU_INHERITANCE "0"
1819
#define VRF_PREFIX "Vrf"
1920

2021
#define LOOPBACK_DEFAULT_MTU_STR "65536"
2122

2223
IntfMgr::IntfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames) :
2324
Orch(cfgDb, tableNames),
24-
m_cfgIntfTable(cfgDb, CFG_INTF_TABLE_NAME),
25-
m_cfgVlanIntfTable(cfgDb, CFG_VLAN_INTF_TABLE_NAME),
2625
m_statePortTable(stateDb, STATE_PORT_TABLE_NAME),
2726
m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME),
2827
m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME),
@@ -167,6 +166,157 @@ bool IntfMgr::isIntfChangeVrf(const string &alias, const string &vrfName)
167166
return false;
168167
}
169168

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+
170320
bool IntfMgr::isIntfStateOk(const string &alias)
171321
{
172322
vector<FieldValueTuple> temp;
@@ -217,23 +367,43 @@ bool IntfMgr::isIntfStateOk(const string &alias)
217367
}
218368

219369
bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
220-
const vector<FieldValueTuple>& data,
370+
vector<FieldValueTuple> data,
221371
const string& op)
222372
{
223373
SWSS_LOG_ENTER();
224374

225375
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+
}
227388
bool is_lo = !alias.compare(0, strlen(LOOPBACK_PREFIX), LOOPBACK_PREFIX);
228389

390+
string vrf_name = "";
391+
string mtu = "";
392+
string adminStatus = "";
229393
for (auto idx : data)
230394
{
231395
const auto &field = fvField(idx);
232396
const auto &value = fvValue(idx);
397+
233398
if (field == "vnet_name" || field == "vrf_name")
234399
{
235400
vrf_name = value;
236401
}
402+
403+
if (field == "admin_status")
404+
{
405+
adminStatus = value;
406+
}
237407
}
238408

239409
if (op == SET_COMMAND)
@@ -256,16 +426,73 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
256426
SWSS_LOG_ERROR("%s can not change to %s directly, skipping", alias.c_str(), vrf_name.c_str());
257427
return true;
258428
}
429+
259430
if (is_lo)
260431
{
261432
addLoopbackIntf(alias);
262433
}
434+
263435
if (!vrf_name.empty())
264436
{
265437
setIntfVrf(alias, vrf_name);
266438
}
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);
269496
}
270497
else if (op == DEL_COMMAND)
271498
{
@@ -275,13 +502,24 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
275502
{
276503
return false;
277504
}
505+
278506
setIntfVrf(alias, "");
507+
279508
if (is_lo)
280509
{
281510
delLoopbackIntf(alias);
282511
}
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);
285523
}
286524
else
287525
{
@@ -304,7 +542,7 @@ bool IntfMgr::doIntfAddrTask(const vector<string>& keys,
304542
if (op == SET_COMMAND)
305543
{
306544
/*
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.
308546
* The pending task will be checked periodically and retried.
309547
*/
310548
if (!isIntfStateOk(alias) || !isIntfCreated(alias))

cfgmgr/intfmgr.h

+11-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <map>
99
#include <string>
10+
#include <set>
1011

1112
namespace swss {
1213

@@ -18,12 +19,13 @@ class IntfMgr : public Orch
1819

1920
private:
2021
ProducerStateTable m_appIntfTableProducer;
21-
Table m_cfgIntfTable, m_cfgVlanIntfTable;
2222
Table m_statePortTable, m_stateLagTable, m_stateVlanTable, m_stateVrfTable, m_stateIntfTable;
2323

24+
std::set<std::string> m_subIntfList;
25+
2426
void setIntfIp(const std::string &alias, const std::string &opCmd, const IpPrefix &ipPrefix);
2527
void setIntfVrf(const std::string &alias, const std::string &vrfName);
26-
bool doIntfGeneralTask(const std::vector<std::string>& keys, const std::vector<FieldValueTuple>& data, const std::string& op);
28+
bool doIntfGeneralTask(const std::vector<std::string>& keys, std::vector<FieldValueTuple> data, const std::string& op);
2729
bool doIntfAddrTask(const std::vector<std::string>& keys, const std::vector<FieldValueTuple>& data, const std::string& op);
2830
void doTask(Consumer &consumer);
2931
bool isIntfStateOk(const std::string &alias);
@@ -32,6 +34,13 @@ class IntfMgr : public Orch
3234
int getIntfIpCount(const std::string &alias);
3335
void addLoopbackIntf(const std::string &alias);
3436
void delLoopbackIntf(const std::string &alias);
37+
38+
void addHostSubIntf(const std::string&intf, const std::string &subIntf, const std::string &vlan);
39+
void setHostSubIntfMtu(const std::string &subIntf, const std::string &mtu);
40+
void setHostSubIntfAdminStatus(const std::string &subIntf, const std::string &admin_status);
41+
void removeHostSubIntf(const std::string &subIntf);
42+
void setSubIntfStateOk(const std::string &alias);
43+
void removeSubIntfState(const std::string &alias);
3544
};
3645

3746
}

cfgmgr/intfmgrd.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ int main(int argc, char **argv)
4545
CFG_LAG_INTF_TABLE_NAME,
4646
CFG_VLAN_INTF_TABLE_NAME,
4747
CFG_LOOPBACK_INTERFACE_TABLE_NAME,
48+
CFG_VLAN_SUB_INTF_TABLE_NAME,
4849
};
4950

5051
DBConnector cfgDb(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);

orchagent/bufferorch.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ task_process_status BufferOrch::processQueue(Consumer &consumer)
598598
}
599599

600600
/*
601-
Input sample "BUFFER_PG_TABLE|Ethernet4,Ethernet45|10-15"
601+
Input sample "BUFFER_PG|Ethernet4,Ethernet45|10-15"
602602
*/
603603
task_process_status BufferOrch::processPriorityGroup(Consumer &consumer)
604604
{

0 commit comments

Comments
 (0)