Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layer 2 Forwarding Enhancements #885

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9afa981
add LAG name map to counter table
anilkpandey May 11, 2019
9f9935d
Delete .DS_Store
anilkpandey Jun 12, 2019
14f36f4
Merge remote-tracking branch 'upstream/master'
anilkpandey Aug 27, 2019
23dc382
Merge remote-tracking branch 'upstream/master'
anilkpandey Sep 7, 2019
d5370f4
Layer 2 Forwarding Enhancements
anilkpandey Sep 7, 2019
80a91a5
Layer 2 Forwarding Enhancements
anilkpandey Sep 8, 2019
0398cc8
Layer 2 Forwarding Enhancements
anilkpandey Sep 8, 2019
a53a461
Updated to reflect latest code changes
anilkpandey Sep 14, 2019
e02a7e3
Update fdborch.cpp
anilkpandey Sep 20, 2019
fb1d01b
add portchannel OID to NAME mapping in LAG_NAME_MAP_TABLE
anilkpandey Sep 26, 2019
93b50a5
Merge remote-tracking branch 'upstream/master'
anilkpandey Oct 15, 2019
a61485a
Update fdborch.cpp
anilkpandey Oct 21, 2019
3269a27
Update fdborch.cpp
anilkpandey Oct 22, 2019
30dfa58
Update fdborch.cpp
anilkpandey Oct 29, 2019
81b5f54
Update conftest.py
anilkpandey Oct 29, 2019
0df7f35
Update fdborch.cpp
anilkpandey Nov 1, 2019
cd6af32
Merge remote-tracking branch 'upstream/master'
anilkpandey Nov 5, 2019
7cb0d37
Update fdborch.cpp
anilkpandey Nov 6, 2019
7c29491
Update fdborch.cpp
anilkpandey Nov 8, 2019
753acb4
Update portsorch.cpp
anilkpandey Nov 10, 2019
0d0cb03
Update vlanmgr.cpp
anilkpandey Nov 10, 2019
869937e
Merge remote-tracking branch 'upstream/master'
anilkpandey Nov 14, 2019
379c2d7
Merge remote-tracking branch 'upstream/master'
anilkpandey Dec 6, 2019
da3f975
Merge remote-tracking branch 'upstream/master'
anilkpandey Dec 13, 2019
c852011
updated as per review comments
anilkpandey Dec 16, 2019
a9fb507
Update vlanmgr.cpp
anilkpandey Dec 16, 2019
a9c4b5d
Merge remote-tracking branch 'upstream/master'
anilkpandey Apr 24, 2020
bcaeb98
Update portsorch.cpp
anilkpandey Apr 24, 2020
602bf2b
Merge remote-tracking branch 'upstream/master'
anilkpandey Oct 29, 2020
61c0f75
Merge remote-tracking branch 'upstream/master'
anilkpandey Oct 29, 2020
a5c33d2
Merge remote-tracking branch 'upstream/master'
anilkpandey Dec 4, 2020
757cf70
Create .DS_Store
anilkpandey Dec 4, 2020
56e330e
update latest changes after synching with master
anilkpandey Dec 4, 2020
33f513f
fix lgtm issue
anilkpandey Dec 14, 2020
94bbb50
Delete .DS_Store
anilkpandey Dec 15, 2020
cac0096
Merge remote-tracking branch 'upstream/master'
anilkpandey Dec 15, 2020
47bcce9
Merge remote-tracking branch 'upstream/master'
anilkpandey Jan 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 200 additions & 8 deletions cfgmgr/vlanmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ using namespace swss;

#define DOT1Q_BRIDGE_NAME "Bridge"
#define VLAN_PREFIX "Vlan"
#define SWITCH_STR "switch"
#define LAG_PREFIX "PortChannel"
#define DEFAULT_VLAN_ID "1"
#define DEFAULT_MTU_STR "9100"
#define VLAN_HLEN 4
#define MAX_VLAN_ID 4095

extern MacAddress gMacAddress;

Expand All @@ -28,6 +30,8 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c
m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME),
m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME),
m_stateVlanMemberTable(stateDb, STATE_VLAN_MEMBER_TABLE_NAME),
m_appFdbTableProducer(appDb, APP_FDB_TABLE_NAME),
m_appSwitchTableProducer(appDb, APP_SWITCH_TABLE_NAME),
m_appVlanTableProducer(appDb, APP_VLAN_TABLE_NAME),
m_appVlanMemberTableProducer(appDb, APP_VLAN_MEMBER_TABLE_NAME),
replayDone(false)
Expand Down Expand Up @@ -112,6 +116,10 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c

EXEC_WITH_ERROR_THROW(echo_cmd_backup, res);
}
/* vlan state notification from portsorch */
m_VlanStateNotificationConsumer = new swss::NotificationConsumer(appDb, "VLANSTATE");
auto vlanStatusNotificatier = new Notifier(m_VlanStateNotificationConsumer, this, "VLANSTATE");
Orch::addExecutor(vlanStatusNotificatier);
}

bool VlanMgr::addHostVlan(int vlan_id)
Expand All @@ -125,7 +133,7 @@ bool VlanMgr::addHostVlan(int vlan_id)
+ BASH_CMD + " -c \""
+ BRIDGE_CMD + " vlan add vid " + std::to_string(vlan_id) + " dev " + DOT1Q_BRIDGE_NAME + " self && "
+ IP_CMD + " link add link " + DOT1Q_BRIDGE_NAME
+ " up"
+ " down"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change the above comments to reflect this change.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is already explained in the comments above:
"Changed default vlan state in kernel to Down and make it Up only when first port/lag in the vlan is oper up"

+ " name " + VLAN_PREFIX + std::to_string(vlan_id)
+ " address " + gMacAddress.to_string()
+ " type vlan id " + std::to_string(vlan_id) + "\"";
Expand Down Expand Up @@ -218,14 +226,29 @@ bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const str
// /bin/bash -c "/sbin/ip link set {{port_alias}} master Bridge &&
// /sbin/bridge vlan del vid 1 dev {{ port_alias }} &&
// /sbin/bridge vlan add vid {{vlan_id}} dev {{port_alias}} {{tagging_mode}}"
ostringstream cmds, inner;
inner << IP_CMD " link set " << shellquote(port_alias) << " master " DOT1Q_BRIDGE_NAME " && "
BRIDGE_CMD " vlan del vid " DEFAULT_VLAN_ID " dev " << shellquote(port_alias) << " && "
BRIDGE_CMD " vlan add vid " + std::to_string(vlan_id) + " dev " << shellquote(port_alias) << " " + tagging_cmd;
cmds << BASH_CMD " -c " << shellquote(inner.str());

const std::string key = std::string("") + "Vlan1|" + port_alias;

std::string res;
EXEC_WITH_ERROR_THROW(cmds.str(), res);
if (isVlanMemberStateOk(key)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, update the comments above to reflect the changes here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added explanation in comments section:
"Added support for add/remove vlan 1 from config. Also, if port is member of vlan 1, will not remove it from vlan 1 after adding port to bridge in kernel."

ostringstream cmds, inner;
inner << IP_CMD " link set " << shellquote(port_alias) << " master " DOT1Q_BRIDGE_NAME " && "
BRIDGE_CMD " vlan add vid " + std::to_string(vlan_id) + " dev " << shellquote(port_alias) << " " + tagging_cmd;
cmds << BASH_CMD " -c " << shellquote(inner.str());

std::string res;
EXEC_WITH_ERROR_THROW(cmds.str(), res);
}
else
{
ostringstream cmds, inner;
inner << IP_CMD " link set " << shellquote(port_alias) << " master " DOT1Q_BRIDGE_NAME " && "
BRIDGE_CMD " vlan del vid " DEFAULT_VLAN_ID " dev " << shellquote(port_alias) << " && "
BRIDGE_CMD " vlan add vid " + std::to_string(vlan_id) + " dev " << shellquote(port_alias) << " " + tagging_cmd;
cmds << BASH_CMD " -c " << shellquote(inner.str());

std::string res;
EXEC_WITH_ERROR_THROW(cmds.str(), res);
}

return true;
}
Expand Down Expand Up @@ -263,6 +286,137 @@ bool VlanMgr::isVlanMacOk()
return !!gMacAddress;
}

void VlanMgr::doSwitchTask(Consumer &consumer)
{
SWSS_LOG_ENTER();
auto it = consumer.m_toSync.begin();

while (it != consumer.m_toSync.end())
{
KeyOpFieldsValuesTuple t = it->second;

string key = kfvKey(t);
string op = kfvOp(t);

/* Ensure the key starts with "switch" otherwise ignore */
if (key != SWITCH_STR)
{
SWSS_LOG_NOTICE("Ignoring SWITCH key %s", key.c_str());
it = consumer.m_toSync.erase(it);
continue;
}

SWSS_LOG_DEBUG("key:switch");

for (auto i : kfvFieldsValues(t))
{
if (fvField(i) == "fdb_aging_time")
{
long agingTime = 0;
SWSS_LOG_DEBUG("attribute:fdb_aging_time");
if (op == SET_COMMAND)
{
SWSS_LOG_DEBUG("operation:set");
agingTime = strtol(fvValue(i).c_str(), NULL, 0);
if (agingTime < 0)
{
SWSS_LOG_ERROR("Invalid fdb_aging_time %s", fvValue(i).c_str());
break;
}
SWSS_LOG_DEBUG("value:%s",fvValue(i).c_str());
}
else if (op == DEL_COMMAND)
{
SWSS_LOG_DEBUG("operation:del");
agingTime = 0;
}
else
{
SWSS_LOG_ERROR("Unknown operation type %s", op.c_str());
break;
}

vector<FieldValueTuple> fvVector;
FieldValueTuple aging_time("fdb_aging_time", to_string(agingTime));
fvVector.push_back(aging_time);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have range for aging Time?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Range is 0-1000000. It is validated during config.

m_appSwitchTableProducer.set(key, fvVector);
break;
}
}

it = consumer.m_toSync.erase(it);
}
}

void VlanMgr::doFdbTask(Consumer &consumer)
{
auto it = consumer.m_toSync.begin();

while (it != consumer.m_toSync.end())
{
KeyOpFieldsValuesTuple t = it->second;

/* format: <VLAN_name>|<MAC_address> */
vector<string> keys = tokenize(kfvKey(t), config_db_key_delimiter, 1);
/* keys[0] is vlan as (Vlan10) and keys[1] is mac as (00-00-00-00-00-00) */
string op = kfvOp(t);

/* Ensure the key starts with "Vlan" otherwise ignore */
if (strncmp(keys[0].c_str(), VLAN_PREFIX, 4))
{
SWSS_LOG_ERROR("Invalid key format. No 'Vlan' prefix: %s", keys[0].c_str());
it = consumer.m_toSync.erase(it);
continue;
}

unsigned long vlan_id;
vlan_id = strtoul(keys[0].substr(strlen(VLAN_PREFIX)).c_str(), NULL, 0);

if ((vlan_id <= 0) || (vlan_id > MAX_VLAN_ID))
{
SWSS_LOG_ERROR("Invalid key format. Vlan is out of range: %s", keys[0].c_str());
it = consumer.m_toSync.erase(it);
continue;
}

MacAddress mac = MacAddress(keys[1]);

string key = VLAN_PREFIX + to_string(vlan_id);
key += DEFAULT_KEY_SEPARATOR;
key += mac.to_string();

if (op == SET_COMMAND)
{
string port;
for (auto i : kfvFieldsValues(t))
{
if (fvField(i) == "port")
{
port = fvValue(i);
break;
}
}

vector<FieldValueTuple> fvVector;
FieldValueTuple p("port", port);
fvVector.push_back(p);
FieldValueTuple t("type", "static");
fvVector.push_back(t);

m_appFdbTableProducer.set(key, fvVector);
}
else if (op == DEL_COMMAND)
{
m_appFdbTableProducer.del(key);
}
else
{
SWSS_LOG_ERROR("Unknown operation type %s", op.c_str());
}
it = consumer.m_toSync.erase(it);
}
}

void VlanMgr::doVlanTask(Consumer &consumer)
{
if (!isVlanMacOk())
Expand Down Expand Up @@ -666,9 +820,47 @@ void VlanMgr::doTask(Consumer &consumer)
{
doVlanMemberTask(consumer);
}
else if (table_name == CFG_FDB_TABLE_NAME)
{
doFdbTask(consumer);
}
else if (table_name == CFG_SWITCH_TABLE_NAME)
{
SWSS_LOG_DEBUG("Table:SWITCH");
doSwitchTask(consumer);
}
else
{
SWSS_LOG_ERROR("Unknown config table %s ", table_name.c_str());
throw runtime_error("VlanMgr doTask failure.");
}
}

void VlanMgr::doTask(NotificationConsumer &consumer)
{
std::string op;
std::string data;
std::vector<swss::FieldValueTuple> values;

if (&consumer != m_VlanStateNotificationConsumer)
{
SWSS_LOG_WARN("received incorrect notification message");
return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log a message

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will change code accordingly

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

consumer.pop(op, data, values);

unsigned long vlan_id = strtoul(data.substr(strlen(VLAN_PREFIX)).c_str(), NULL, 0);

SWSS_LOG_NOTICE("vlanmgr received port status notification state %s vlan %s",
op.c_str(), data.c_str());

if (isVlanStateOk(data))
{
setHostVlanAdminState((int)vlan_id, op);
}
else
{
SWSS_LOG_ERROR("received state update for vlan %s not existing", data.c_str());
}
}
9 changes: 8 additions & 1 deletion cfgmgr/vlanmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
#include "dbconnector.h"
#include "producerstatetable.h"
#include "orch.h"
#include "notifier.h"

#include <set>
#include <map>
#include <string>

namespace swss {

class VlanMgr : public Orch
{
public:
Expand All @@ -19,17 +19,24 @@ class VlanMgr : public Orch

private:
ProducerStateTable m_appVlanTableProducer, m_appVlanMemberTableProducer;
ProducerStateTable m_appFdbTableProducer;
ProducerStateTable m_appSwitchTableProducer;
Table m_cfgVlanTable, m_cfgVlanMemberTable;
Table m_statePortTable, m_stateLagTable;
Table m_stateVlanTable, m_stateVlanMemberTable;
std::set<std::string> m_vlans;
NotificationConsumer* m_VlanStateNotificationConsumer;

std::set<std::string> m_vlanReplay;
std::set<std::string> m_vlanMemberReplay;
bool replayDone;

void doTask(Consumer &consumer);
void doTask(NotificationConsumer &consumer);
void doVlanTask(Consumer &consumer);
void doVlanMemberTask(Consumer &consumer);
void doFdbTask(Consumer &consumer);
void doSwitchTask(Consumer &consumer);
void processUntaggedVlanMembers(std::string vlan, const std::string &members);

bool addHostVlan(int vlan_id);
Expand Down
2 changes: 2 additions & 0 deletions cfgmgr/vlanmgrd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ int main(int argc, char **argv)
vector<string> cfg_vlan_tables = {
CFG_VLAN_TABLE_NAME,
CFG_VLAN_MEMBER_TABLE_NAME,
CFG_FDB_TABLE_NAME,
CFG_SWITCH_TABLE_NAME,
};

DBConnector cfgDb("CONFIG_DB", 0);
Expand Down
Loading