From 9d68329636d8f0b4cc94fc69b18dc22920693665 Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Fri, 20 Oct 2017 21:56:25 -0700 Subject: [PATCH 1/7] configDB enforcer for VLAN Signed-off-by: Jipan Yang --- Makefile.am | 2 +- configure.ac | 1 + portsyncd/linksync.cpp | 75 +----- portsyncd/linksync.h | 4 +- vlanconfd/Makefile.am | 15 ++ vlanconfd/switchconfvlan.cpp | 139 ++++++++++ vlanconfd/switchconfvlan.h | 34 +++ vlanconfd/vlanconf.cpp | 474 +++++++++++++++++++++++++++++++++++ vlanconfd/vlanconf.h | 44 ++++ vlanconfd/vlanconfd.cpp | 87 +++++++ 10 files changed, 798 insertions(+), 77 deletions(-) create mode 100644 vlanconfd/Makefile.am create mode 100644 vlanconfd/switchconfvlan.cpp create mode 100644 vlanconfd/switchconfvlan.h create mode 100644 vlanconfd/vlanconf.cpp create mode 100644 vlanconfd/vlanconf.h create mode 100644 vlanconfd/vlanconfd.cpp diff --git a/Makefile.am b/Makefile.am index 20553983e15..8bd1642cefd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig +SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig vlanconfd if HAVE_LIBTEAM SUBDIRS += teamsyncd diff --git a/configure.ac b/configure.ac index 145a0a1d6ad..6aa52af22e8 100644 --- a/configure.ac +++ b/configure.ac @@ -87,6 +87,7 @@ AC_CONFIG_FILES([ teamsyncd/Makefile swssconfig/Makefile tests/Makefile + vlanconfd/Makefile ]) AC_OUTPUT diff --git a/portsyncd/linksync.cpp b/portsyncd/linksync.cpp index 9a0c232d3e8..4deb234d952 100644 --- a/portsyncd/linksync.cpp +++ b/portsyncd/linksync.cpp @@ -32,10 +32,7 @@ extern bool g_init; LinkSync::LinkSync(DBConnector *db) : m_portTableProducer(db, APP_PORT_TABLE_NAME), - m_vlanTableProducer(db, APP_VLAN_TABLE_NAME), - m_vlanMemberTableProducer(db, APP_VLAN_MEMBER_TABLE_NAME), - m_portTableConsumer(db, APP_PORT_TABLE_NAME), - m_vlanMemberTableConsumer(db, APP_VLAN_MEMBER_TABLE_NAME) + m_portTableConsumer(db, APP_PORT_TABLE_NAME) { /* See the comments for g_portSet in portsyncd.cpp */ for (string port : g_portSet) @@ -53,22 +50,6 @@ LinkSync::LinkSync(DBConnector *db) : } } } - - vector tuples; - m_vlanMemberTableConsumer.getTableContent(tuples); - - for (auto tuple : tuples) - { - vector keys = tokenize(kfvKey(tuple), ':'); - string vlan = keys[0]; - string member = keys[1]; - - if (g_vlanMap.find(vlan) == g_vlanMap.end()) - { - g_vlanMap[vlan] = set(); - } - g_vlanMap[vlan].insert(member); - } } void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj) @@ -82,7 +63,6 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj) string key = rtnl_link_get_name(link); if (key.compare(0, INTFS_PREFIX.length(), INTFS_PREFIX) && - key.compare(0, VLAN_PREFIX.length(), VLAN_PREFIX) && key.compare(0, LAG_PREFIX.length(), LAG_PREFIX)) { return; @@ -120,65 +100,12 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj) return; } - /* VLAN member: A separate entry in VLAN_TABLE will be inserted */ - if (master) - { - string master_key = m_ifindexNameMap[master]; - /* Verify the master interface starts with "Vlan" to exclude "PortChannel" interfaces */ - if (!master_key.compare(0, VLAN_PREFIX.length(), VLAN_PREFIX)) - { - string member_key = master_key + ":" + key; - - if (nlmsg_type == RTM_DELLINK) /* Will it happen? */ - { - m_vlanMemberTableProducer.del(member_key); - } - else /* RTM_NEWLINK */ - { - vector fvVector; - FieldValueTuple t("tagging_mode", "untagged"); - fvVector.push_back(t); - - m_vlanMemberTableProducer.set(member_key, fvVector); - } - } - } - /* No longer a VLAN member: Check if it was a member before and remove it */ - else - { - for (auto i = g_vlanMap.begin(); i != g_vlanMap.end(); i++) - { - set member_set = (*i).second; - if (member_set.find(key) != member_set.end()) - { - string member_key = (*i).first + ":" + key; - m_vlanMemberTableProducer.del(member_key); - } - } - } - vector fvVector; FieldValueTuple a("admin_status", admin ? "up" : "down"); FieldValueTuple m("mtu", to_string(mtu)); fvVector.push_back(a); fvVector.push_back(m); - /* VLAN interfaces: Check if the type is bridge */ - if (type && !strcmp(type, VLAN_DRV_NAME)) - { - if (nlmsg_type == RTM_DELLINK) - { - m_vlanTableProducer.del(key); - } - else - { - FieldValueTuple o("oper_status", oper ? "up" : "down"); - fvVector.push_back(o); - m_vlanTableProducer.set(key, fvVector); - } - return; - } - /* front panel interfaces: Check if the port is in the PORT_TABLE * non-front panel interfaces such as eth0, lo which are not in the * PORT_TABLE are ignored. */ diff --git a/portsyncd/linksync.h b/portsyncd/linksync.h index b14832eb51e..1c9038ab3aa 100644 --- a/portsyncd/linksync.h +++ b/portsyncd/linksync.h @@ -19,8 +19,8 @@ class LinkSync : public NetMsg virtual void onMsg(int nlmsg_type, struct nl_object *obj); private: - ProducerStateTable m_portTableProducer, m_vlanTableProducer, m_vlanMemberTableProducer; - Table m_portTableConsumer, m_vlanMemberTableConsumer; + ProducerStateTable m_portTableProducer; + Table m_portTableConsumer; std::map m_ifindexNameMap; }; diff --git a/vlanconfd/Makefile.am b/vlanconfd/Makefile.am new file mode 100644 index 00000000000..a246bc00066 --- /dev/null +++ b/vlanconfd/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/cfgorch + +bin_PROGRAMS = vlanconfd + +if DEBUG +DBGFLAGS = -ggdb -DDEBUG +else +DBGFLAGS = -g +endif + +vlanconfd_SOURCES = vlanconfd.cpp vlanconf.cpp switchconfvlan.cpp $(top_srcdir)/cfgorch/cfgorch.cpp + +vlanconfd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) +vlanconfd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) +vlanconfd_LDADD = -lswsscommon diff --git a/vlanconfd/switchconfvlan.cpp b/vlanconfd/switchconfvlan.cpp new file mode 100644 index 00000000000..54812bbcc9c --- /dev/null +++ b/vlanconfd/switchconfvlan.cpp @@ -0,0 +1,139 @@ +#include +#include +#include "logger.h" +#include "dbconnector.h" +#include "producerstatetable.h" +#include "switchconfvlan.h" +#include "exec.h" + +using namespace std; +using namespace swss; + +#define DOT1Q_BRIDGE_NAME "Bridge" +#define CFG_SWITCH_ATTR_NAME "SWITCH_ATTR" + +SwitchConfVlan::SwitchConfVlan(DBConnector *cfgDb, DBConnector *appDb, string tableName) : + CfgOrch(cfgDb, tableName), + m_cfgSwitchTableConsumer(cfgDb, tableName, CONFIGDB_TABLE_NAME_SEPARATOR), + m_appSwitchTableProducer(appDb, APP_SWITCH_TABLE_NAME) +{ + +} + +SwitchConfVlan::~SwitchConfVlan() +{ + +} + +void SwitchConfVlan::syncCfgDB() +{ + CfgOrch::syncCfgDB(CFG_SWITCH_TABLE_NAME, m_cfgSwitchTableConsumer); +} + +/* + * ls /sys/class/net/Bridge/brif/ | xargs -n 1 -I % sh -c 'echo %; echo 0 > /sys/class/net/Bridge/brif/%/unicast_flood' + */ +void SwitchConfVlan::updateHostFloodControl(string brif) +{ + string brif_path = "/sys/class/net/"; + string cmd, res; + string unicast_op, multicast_op, broadcast_op; + struct stat sb; + + brif_path += DOT1Q_BRIDGE_NAME; + brif_path += "/brif/"; + + if (stat(brif_path.c_str(), &sb) || !S_ISDIR(sb.st_mode)) + { + SWSS_LOG_INFO("updateHostFloodControl: %s doens't exist", brif_path.c_str()); + return; + } + + unicast_op = (m_unicast_miss_flood ? " 1 > " : " 0 > "); + multicast_op = (m_multicast_miss_flood ? " 1 > " : " 0 > "); + broadcast_op = (m_broadcast_flood ? " 1 > " : " 0 > "); + + if (brif.empty()) + { + string cmd_prefix; + /* Apply to all bridge ports in 1q bridge */ + cmd_prefix = "ls " + brif_path; + cmd_prefix += " | xargs -n 1 -I % sh -c 'echo"; + + cmd = cmd_prefix + unicast_op; + cmd += brif_path + "%/unicast_flood'"; + swss::exec(cmd, res); + + cmd = cmd_prefix + multicast_op; + cmd += brif_path + "%/multicast_flood'"; + swss::exec(cmd, res); + + cmd = cmd_prefix + broadcast_op; + cmd += brif_path + "%/broadcast_flood'"; + swss::exec(cmd, res); + } + else + { + cmd = "echo" + unicast_op; + cmd += brif_path + brif + "/unicast_flood"; + swss::exec(cmd, res); + + cmd = "echo" + multicast_op; + cmd += brif_path + brif + "/multicast_flood"; + swss::exec(cmd, res); + + cmd = "echo" + broadcast_op; + cmd += brif_path + brif + "/broadcast_flood"; + swss::exec(cmd, res); + } +} + +void SwitchConfVlan::getHostFloodSetting(bool &flood, string &action) +{ + if (action == "forward" || action == "trap") + { + flood = true; + } + else + { + flood = false; + } + +} + +void SwitchConfVlan::doTask(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); + + SWSS_LOG_DEBUG("Switch doTask: %s", (dumpTuple(consumer, t)).c_str()); + + if (key == CFG_SWITCH_ATTR_NAME) + { + for (auto i : kfvFieldsValues(t)) + { + if (fvField(i) == "fdb_unicast_miss_packet_action") { + getHostFloodSetting(m_unicast_miss_flood, fvValue(i)); + } + else if (fvField(i) == "fdb_multicast_miss_packet_action") { + getHostFloodSetting(m_multicast_miss_flood, fvValue(i)); + } + else if (fvField(i) == "fdb_broadcast_miss_packet_action") { + getHostFloodSetting(m_broadcast_flood, fvValue(i)); + } + } + string all_brif; + updateHostFloodControl(all_brif); + m_appSwitchTableProducer.set(key, kfvFieldsValues(t)); + } + + it = consumer.m_toSync.erase(it); + continue; + } +} \ No newline at end of file diff --git a/vlanconfd/switchconfvlan.h b/vlanconfd/switchconfvlan.h new file mode 100644 index 00000000000..40f3d19aa05 --- /dev/null +++ b/vlanconfd/switchconfvlan.h @@ -0,0 +1,34 @@ +#ifndef __SWITCHCONFVLAN__ +#define __SWITCHCONFVLAN__ + +#include "dbconnector.h" +#include "cfgorch.h" + +#include +#include + +namespace swss { + + +class SwitchConfVlan : public CfgOrch +{ +public: + SwitchConfVlan(DBConnector *cfgDb, DBConnector *appDb, string tableName); + virtual ~SwitchConfVlan(); + void updateHostFloodControl(string brif); + void syncCfgDB(); +private: + bool m_unicast_miss_flood = true; + bool m_multicast_miss_flood = true; + bool m_broadcast_flood = true; + + ProducerStateTable m_appSwitchTableProducer; + Table m_cfgSwitchTableConsumer; + + void doTask(Consumer &consumer); + void getHostFloodSetting(bool &flood, string &action); +}; + +} + +#endif diff --git a/vlanconfd/vlanconf.cpp b/vlanconfd/vlanconf.cpp new file mode 100644 index 00000000000..3c06d116dab --- /dev/null +++ b/vlanconfd/vlanconf.cpp @@ -0,0 +1,474 @@ +#include +#include "logger.h" +#include "producerstatetable.h" +#include "macaddress.h" +#include "vlanconf.h" +#include "switchconfvlan.h" +#include "exec.h" +#include "tokenize.h" + +using namespace std; +using namespace swss; + +#define DOT1Q_BRIDGE_NAME "Bridge" +#define VLAN_PREFIX "Vlan" +#define LAG_PREFIX "PortChannel" +#define DEFAULT_VLAN_ID 1 + +extern MacAddress gMacAddress; +extern SwitchConfVlan *gSwtichConfVlan; + +VlanConf::VlanConf(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, vector tableNames) : + CfgOrch(cfgDb, tableNames), + m_cfgVlanTable(cfgDb, CFG_VLAN_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), + m_cfgVlanMemberTable(cfgDb, CFG_VLAN_MEMBER_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), + m_statePortTable(stateDb, STATE_PORT_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), + m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), + m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), + m_appVlanTableProducer(appDb, APP_VLAN_TABLE_NAME), + m_appVlanMemberTableProducer(appDb, APP_VLAN_MEMBER_TABLE_NAME) +{ + SWSS_LOG_ENTER(); + + // Initialize Linux dot1q bridge and enable vlan filtering + string cmd, res; + + cmd = "ip link del "; + cmd += DOT1Q_BRIDGE_NAME; + swss::exec(cmd, res); + cmd = "ip link add "; + cmd += DOT1Q_BRIDGE_NAME; + cmd += " up type bridge"; + swss::exec(cmd, res); + cmd = "echo 1 > /sys/class/net/"; + cmd += DOT1Q_BRIDGE_NAME; + cmd += "/bridge/vlan_filtering"; + swss::exec(cmd, res); + cmd = "bridge vlan del vid " + std::to_string(DEFAULT_VLAN_ID) + + " dev " + DOT1Q_BRIDGE_NAME + " self"; + swss::exec(cmd, res); +} + +void VlanConf::syncCfgDB() +{ + CfgOrch::syncCfgDB(CFG_VLAN_TABLE_NAME, m_cfgVlanTable); + CfgOrch::syncCfgDB(CFG_VLAN_MEMBER_TABLE_NAME, m_cfgVlanMemberTable); +} + +bool VlanConf::addHostVlan(int vlan_id) +{ + string cmd, res; + + cmd = "bridge vlan add vid " + to_string(vlan_id) + " dev " + + DOT1Q_BRIDGE_NAME + " self"; + swss::exec(cmd, res); + cmd = "ip link add link "; + cmd += DOT1Q_BRIDGE_NAME; + cmd += " name "; + cmd += VLAN_PREFIX + to_string(vlan_id) + + " type vlan id " + to_string(vlan_id); + swss::exec(cmd, res); + + cmd = "ip link set "; + cmd += VLAN_PREFIX + to_string(vlan_id); + cmd += " address " + gMacAddress.to_string(); + swss::exec(cmd, res); + + // Bring up vlan port by default + cmd = "ip link set "; + cmd += VLAN_PREFIX + to_string(vlan_id); + cmd += " up"; + swss::exec(cmd, res); + return true; +} + +bool VlanConf::removeHostVlan(int vlan_id) +{ + string cmd, res; + + cmd = "ip link del "; + cmd += VLAN_PREFIX + to_string(vlan_id); + swss::exec(cmd, res); + + cmd = "bridge vlan del vid " + to_string(vlan_id) + " dev " + + DOT1Q_BRIDGE_NAME + " self"; + swss::exec(cmd, res); + + return true; +} + +bool VlanConf::setHostVlanAdminState(int vlan_id, string &admin_status) +{ + string cmd, res; + + cmd = "ip link set "; + cmd += VLAN_PREFIX + to_string(vlan_id) + " " + admin_status; + swss::exec(cmd, res); + return true; +} + +bool VlanConf::setHostVlanMtu(int vlan_id, uint32_t mtu) +{ + string cmd, res; + + cmd = "ip link set "; + cmd += VLAN_PREFIX + to_string(vlan_id) + " mtu " + to_string(mtu); + swss::exec(cmd, res); + return true; +} + +bool VlanConf::addHostVlanMember(int vlan_id, string &port_alias, string& tagging_mode) +{ + string cmd, res; + + // Should be ok to run set master command more than one time. + cmd = "ip link set " + port_alias + " master " + DOT1Q_BRIDGE_NAME; + swss::exec(cmd, res); + if (tagging_mode == "untagged" || tagging_mode == "priority_tagged") + { + // We are setting pvid as untagged vlan id. + cmd = "bridge vlan add vid " + to_string(vlan_id) + " dev " + + port_alias + " pvid untagged"; + } + else + { + cmd = "bridge vlan add vid " + to_string(vlan_id) + " dev " + + port_alias; + } + swss::exec(cmd, res); + // Apply switch level flood control to this port + gSwtichConfVlan->updateHostFloodControl(port_alias); + + // Bring up vlan member port and set MTU to 9100 by default + cmd = "ip link set " + port_alias + " up mtu 9100"; + swss::exec(cmd, res); + return true; +} + + +bool VlanConf::removeHostVlanMember(int vlan_id, string &port_alias) +{ + string cmd, res; + + cmd = "bridge vlan del vid " + to_string(vlan_id) + " dev " + + port_alias; + swss::exec(cmd, res); + + // When port is not member of any VLAN, it shall be detached from Dot1Q bridge! + cmd = "bridge vlan show dev " + port_alias + " | grep None"; + swss::exec(cmd, res); + if (!res.empty()) + { + cmd = "ip link set " + port_alias + " nomaster"; + swss::exec(cmd, res); + } + + return true; +} + +bool VlanConf::isVlanMacOk() +{ + return !(!gMacAddress); +} + +void VlanConf::doVlanTask(Consumer &consumer) +{ + + if (!isVlanMacOk()) + { + SWSS_LOG_DEBUG("VLAN mac not ready, delaying VLAN task"); + return; + } + auto it = consumer.m_toSync.begin(); + + while (it != consumer.m_toSync.end()) + { + auto &t = it->second; + + string key = kfvKey(t); + + /* Ensure the key starts with "Vlan" otherwise ignore */ + if (strncmp(key.c_str(), VLAN_PREFIX, 4)) + { + SWSS_LOG_ERROR("Invalid key format. No 'Vlan' prefix: %s", key.c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + int vlan_id; + vlan_id = stoi(key.substr(4)); + + string vlan_alias, port_alias; + string op = kfvOp(t); + + if (op == SET_COMMAND) + { + string admin_status; + uint32_t mtu = 0; + vector fvVector; + string members; + + /* Add host VLAN when it has not been created. */ + if (m_vlans.find(key) == m_vlans.end()) + { + addHostVlan(vlan_id); + } + + /* set up host env .... */ + for (auto i : kfvFieldsValues(t)) + { + /* Set port admin status */ + if (fvField(i) == "admin_status") { + admin_status = fvValue(i); + setHostVlanAdminState(vlan_id, admin_status); + fvVector.push_back(i); + } + /* Set port mtu */ + else if (fvField(i) == "mtu") { + mtu = (uint32_t)stoul(fvValue(i)); + setHostVlanMtu(vlan_id, mtu); + fvVector.push_back(i); + } + else if (fvField(i) == "members@") { + members = fvValue(i); + } + } + /* fvVector should not be empty */ + if (fvVector.empty()) + { + FieldValueTuple a("admin_status", "up"); + fvVector.push_back(a); + } + m_appVlanTableProducer.set(key, fvVector); + m_vlans.insert(key); + + fvVector.clear(); + FieldValueTuple s("state", "ok"); + fvVector.push_back(s); + m_stateVlanTable.set(key, fvVector); + + it = consumer.m_toSync.erase(it); + + /* + * Members configured together with VLAN in untagged mode. + * This is to be compatible with access VLAN configuration from minigraph. + */ + if (!members.empty()) + { + processUntaggedVlanMembers(key, members); + } + } + else if (op == DEL_COMMAND) + { + if (m_vlans.find(key) != m_vlans.end()) + { + removeHostVlan(vlan_id); + m_vlans.erase(key); + m_appVlanTableProducer.del(key); + m_stateVlanTable.del(key); + } + else + { + SWSS_LOG_ERROR("%s doesn't exist", key.c_str()); + } + SWSS_LOG_DEBUG("%s", (dumpTuple(consumer, t)).c_str()); + it = consumer.m_toSync.erase(it); + } + else + { + SWSS_LOG_ERROR("Unknown operation type %s", op.c_str()); + SWSS_LOG_DEBUG("%s", (dumpTuple(consumer, t)).c_str()); + it = consumer.m_toSync.erase(it); + } + } +} + +bool VlanConf::isMemberStateOk(string &alias) +{ + vector temp; + + if (!alias.compare(0, strlen(LAG_PREFIX), LAG_PREFIX)) + { + if (m_stateLagTable.get(alias, temp)) + { + SWSS_LOG_DEBUG("%s is ready\n", alias.c_str()); + return true; + } + } + else if (m_statePortTable.get(alias, temp)) + { + SWSS_LOG_DEBUG("%s is ready\n", alias.c_str()); + return true; + } + SWSS_LOG_DEBUG("%s is not ready\n", alias.c_str()); + return false; +} + +bool VlanConf::isVlanStateOk(string &alias) +{ + vector temp; + + if (!alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX)) + { + if (m_stateVlanTable.get(alias, temp)) + { + SWSS_LOG_DEBUG("%s is ready\n", alias.c_str()); + return true; + } + } + SWSS_LOG_DEBUG("%s is not ready\n", alias.c_str()); + return false; +} + +/* + * members is grouped in format like + * "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6, + * Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12, + * Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18, + * Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24" + */ +void VlanConf::processUntaggedVlanMembers(string vlan, string &members) +{ + + auto consumer_it = m_consumerMap.find(CFG_VLAN_MEMBER_TABLE_NAME); + if (consumer_it == m_consumerMap.end()) + { + SWSS_LOG_ERROR("Failed to find tableName:%s", CFG_VLAN_MEMBER_TABLE_NAME); + return; + } + Consumer& consumer = consumer_it->second; + + vector vlanMembers = tokenize(members, ','); + + for (auto vlanMember : vlanMembers) + { + string member_key = vlan + CONFIGDB_KEY_SEPARATOR + vlanMember; + + /* Directly put it into consumer.m_toSync map */ + if (consumer.m_toSync.find(member_key) == consumer.m_toSync.end()) + { + vector fvVector; + FieldValueTuple t("tagging_mode", "untagged"); + fvVector.push_back(t); + consumer.m_toSync[member_key] = make_tuple(member_key, SET_COMMAND, fvVector); + SWSS_LOG_DEBUG("%s", (dumpTuple(consumer, consumer.m_toSync[member_key])).c_str()); + } + /* + * There is pending task from consumber pipe, in this case just skip it. + */ + else + { + SWSS_LOG_WARN("Duplicate key %s found in table:%s", member_key.c_str(), CFG_VLAN_MEMBER_TABLE_NAME); + continue; + } + } + + doTask(consumer); + return; +} + +void VlanConf::doVlanMemberTask(Consumer &consumer) +{ + auto it = consumer.m_toSync.begin(); + while (it != consumer.m_toSync.end()) + { + auto &t = it->second; + + string key = kfvKey(t); + + /* Ensure the key starts with "Vlan" otherwise ignore */ + if (strncmp(key.c_str(), VLAN_PREFIX, 4)) + { + SWSS_LOG_ERROR("Invalid key format. No 'Vlan' prefix: %s", key.c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + key = key.substr(4); + size_t found = key.find(CONFIGDB_KEY_SEPARATOR); + int vlan_id; + string vlan_alias, port_alias; + if (found != string::npos) + { + vlan_id = stoi(key.substr(0, found)); + port_alias = key.substr(found+1); + } + else + { + SWSS_LOG_ERROR("Invalid key format. No member port is presented: %s", + kfvKey(t).c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + vlan_alias = VLAN_PREFIX + to_string(vlan_id); + string op = kfvOp(t); + + if (op == SET_COMMAND) + { + /* Don't proceed if member port/lag is not ready yet */ + if (!isMemberStateOk(port_alias) || !isVlanStateOk(vlan_alias)) + { + SWSS_LOG_DEBUG("%s not ready, delaying", kfvKey(t).c_str()); + it++; + continue; + } + string tagging_mode = "untagged"; + + for (auto i : kfvFieldsValues(t)) + { + if (fvField(i) == "tagging_mode") + tagging_mode = fvValue(i); + } + + if (tagging_mode != "untagged" && + tagging_mode != "tagged" && + tagging_mode != "priority_tagged") + { + SWSS_LOG_ERROR("Wrong tagging_mode '%s' for key: %s", tagging_mode.c_str(), kfvKey(t).c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + addHostVlanMember(vlan_id, port_alias, tagging_mode); + + key = VLAN_PREFIX + to_string(vlan_id); + key += DEFAULT_KEY_SEPARATOR; + key += port_alias; + m_appVlanMemberTableProducer.set(key, kfvFieldsValues(t)); + it = consumer.m_toSync.erase(it); + } + else if (op == DEL_COMMAND) + { + removeHostVlanMember(vlan_id, port_alias); + key = VLAN_PREFIX + to_string(vlan_id); + key += DEFAULT_KEY_SEPARATOR; + key += port_alias; + m_appVlanMemberTableProducer.del(key); + SWSS_LOG_DEBUG("%s", (dumpTuple(consumer, t)).c_str()); + it = consumer.m_toSync.erase(it); + } + else + { + SWSS_LOG_ERROR("Unknown operation type %s", op.c_str()); + it = consumer.m_toSync.erase(it); + } + } +} + +void VlanConf::doTask(Consumer &consumer) +{ + SWSS_LOG_ENTER(); + + string table_name = consumer.m_consumer->getTableName(); + + if (table_name == CFG_VLAN_TABLE_NAME) + doVlanTask(consumer); + else if (table_name == CFG_VLAN_MEMBER_TABLE_NAME) + doVlanMemberTask(consumer); + else + { + SWSS_LOG_ERROR("Unknown config table %s ", table_name.c_str()); + throw runtime_error("VlanConf doTask failure."); + } +} diff --git a/vlanconfd/vlanconf.h b/vlanconfd/vlanconf.h new file mode 100644 index 00000000000..ec30190faa1 --- /dev/null +++ b/vlanconfd/vlanconf.h @@ -0,0 +1,44 @@ +#ifndef __VLANCONF__ +#define __VLANCONF__ + +#include "dbconnector.h" +#include "producerstatetable.h" +#include "cfgorch.h" + +#include +#include +#include + +namespace swss { + +class VlanConf : public CfgOrch +{ +public: + VlanConf(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, vector tableNames); + void syncCfgDB(); +private: + ProducerStateTable m_appVlanTableProducer, m_appVlanMemberTableProducer; + Table m_cfgVlanTable, m_cfgVlanMemberTable; + Table m_statePortTable, m_stateLagTable; + Table m_stateVlanTable; + std::set m_vlans; + + void doTask(Consumer &consumer); + void doVlanTask(Consumer &consumer); + void doVlanMemberTask(Consumer &consumer); + void processUntaggedVlanMembers(string vlan, string &members); + + bool addHostVlan(int vlan_id); + bool removeHostVlan(int vlan_id); + bool setHostVlanAdminState(int vlan_id, string &admin_status); + bool setHostVlanMtu(int vlan_id, uint32_t mtu); + bool addHostVlanMember(int vlan_id, string &port_alias, string& tagging_mode); + bool removeHostVlanMember(int vlan_id, string &port_alias); + bool isMemberStateOk(string &alias); + bool isVlanStateOk(string &alias); + bool isVlanMacOk(); +}; + +} + +#endif diff --git a/vlanconfd/vlanconfd.cpp b/vlanconfd/vlanconfd.cpp new file mode 100644 index 00000000000..6daa677eaa7 --- /dev/null +++ b/vlanconfd/vlanconfd.cpp @@ -0,0 +1,87 @@ +#include +#include +#include "dbconnector.h" +#include "select.h" +#include "exec.h" +#include "schema.h" +#include "macaddress.h" +#include "producerstatetable.h" +#include "switchconfvlan.h" +#include "vlanconf.h" + +using namespace std; +using namespace swss; + +/* select() function timeout retry time, in millisecond */ +#define SELECT_TIMEOUT 1000 + +MacAddress gMacAddress; +SwitchConfVlan *gSwtichConfVlan; + +int main(int argc, char **argv) +{ + Logger::linkToDbNative("vlanconfd"); + SWSS_LOG_ENTER(); + + SWSS_LOG_NOTICE("--- Starting vlanconfd ---"); + + string mac_str, cfg_mac_str; + swss::exec("ip link show eth0 | grep ether | awk '{print $2}'", mac_str); + gMacAddress = mac_str; + + try + { + vector cfg_vlan_tables = { + CFG_VLAN_TABLE_NAME, + CFG_VLAN_MEMBER_TABLE_NAME, + }; + + DBConnector cfgDb(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + DBConnector appDb(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + + gSwtichConfVlan = new SwitchConfVlan(&cfgDb, &appDb, CFG_SWITCH_TABLE_NAME); + VlanConf vlanconf(&cfgDb, &appDb, &stateDb, cfg_vlan_tables); + + std::vector cfgOrchList = {&vlanconf, gSwtichConfVlan}; + + swss::Select s; + for (CfgOrch *o : cfgOrchList) + { + s.addSelectables(o->getSelectables()); + } + + SWSS_LOG_NOTICE("starting main loop"); + while (true) + { + Selectable *sel; + int fd, ret; + + ret = s.select(&sel, &fd, SELECT_TIMEOUT); + if (ret == Select::ERROR) + { + SWSS_LOG_NOTICE("Error: %s!\n", strerror(errno)); + continue; + } + if (ret == Select::TIMEOUT) + { + ((CfgOrch *)&vlanconf)->doTask(); + continue; + } + + for (CfgOrch *o : cfgOrchList) + { + TableConsumable *c = (TableConsumable *)sel; + if (o->hasSelectable(c)) + { + o->execute(c->getTableName()); + } + } + } + } + catch(const std::exception &e) + { + SWSS_LOG_ERROR("Runtime error: %s", e.what()); + } + return 0; +} From 35dc6a4653a6e59963fa0725f33da73949ffcaf9 Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Tue, 24 Oct 2017 22:34:28 -0700 Subject: [PATCH 2/7] Use OrchBase for configDB vlan configuration enforcer Signed-off-by: Jipan Yang --- .gitignore | 1 + Makefile.am | 2 +- cfgagent/Makefile.am | 15 ++++++++ .../switchconf.cpp | 37 ++++++++++++------- .../switchconfvlan.h => cfgagent/switchconf.h | 16 ++++---- {vlanconfd => cfgagent}/vlanconf.cpp | 11 +++--- {vlanconfd => cfgagent}/vlanconf.h | 4 +- {vlanconfd => cfgagent}/vlanconfd.cpp | 19 +++++----- configure.ac | 2 +- vlanconfd/Makefile.am | 15 -------- 10 files changed, 67 insertions(+), 55 deletions(-) create mode 100644 cfgagent/Makefile.am rename vlanconfd/switchconfvlan.cpp => cfgagent/switchconf.cpp (75%) rename vlanconfd/switchconfvlan.h => cfgagent/switchconf.h (56%) rename {vlanconfd => cfgagent}/vlanconf.cpp (97%) rename {vlanconfd => cfgagent}/vlanconf.h (95%) rename {vlanconfd => cfgagent}/vlanconfd.cpp (82%) delete mode 100644 vlanconfd/Makefile.am diff --git a/.gitignore b/.gitignore index ba3fa90eb41..6fca1966e2b 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ deps/ teamsyncd/teamsyncd fpmsyncd/fpmsyncd intfsyncd/intfsyncd +cfgagent/vlanconfd neighsyncd/neighsyncd portsyncd/portsyncd orchagent/orchagent diff --git a/Makefile.am b/Makefile.am index 8bd1642cefd..3811bdbc2be 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig vlanconfd +SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig cfgagent if HAVE_LIBTEAM SUBDIRS += teamsyncd diff --git a/cfgagent/Makefile.am b/cfgagent/Makefile.am new file mode 100644 index 00000000000..379ddfa0a8a --- /dev/null +++ b/cfgagent/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/orchagent +CFLAGS_SAI = -I /usr/include/sai + +bin_PROGRAMS = vlanconfd + +if DEBUG +DBGFLAGS = -ggdb -DDEBUG +else +DBGFLAGS = -g +endif + +vlanconfd_SOURCES = vlanconfd.cpp vlanconf.cpp switchconf.cpp $(top_srcdir)/orchagent/orchbase.cpp +vlanconfd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) +vlanconfd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) +vlanconfd_LDADD = -lswsscommon \ No newline at end of file diff --git a/vlanconfd/switchconfvlan.cpp b/cfgagent/switchconf.cpp similarity index 75% rename from vlanconfd/switchconfvlan.cpp rename to cfgagent/switchconf.cpp index 54812bbcc9c..6868c62c3db 100644 --- a/vlanconfd/switchconfvlan.cpp +++ b/cfgagent/switchconf.cpp @@ -3,7 +3,7 @@ #include "logger.h" #include "dbconnector.h" #include "producerstatetable.h" -#include "switchconfvlan.h" +#include "switchconf.h" #include "exec.h" using namespace std; @@ -12,28 +12,34 @@ using namespace swss; #define DOT1Q_BRIDGE_NAME "Bridge" #define CFG_SWITCH_ATTR_NAME "SWITCH_ATTR" -SwitchConfVlan::SwitchConfVlan(DBConnector *cfgDb, DBConnector *appDb, string tableName) : - CfgOrch(cfgDb, tableName), - m_cfgSwitchTableConsumer(cfgDb, tableName, CONFIGDB_TABLE_NAME_SEPARATOR), - m_appSwitchTableProducer(appDb, APP_SWITCH_TABLE_NAME) +SwitchConf::SwitchConf(DBConnector *cfgDb, DBConnector *appDb, string tableName) : + OrchBase(cfgDb, tableName), + m_cfgSwitchTable(cfgDb, tableName, CONFIGDB_TABLE_NAME_SEPARATOR) { - + /* + * There could be multiple configDB enforcers listening on SWITCH table. + * Only one of them will pass the configuration down to appDB, others + * get the config data for local consumtion. + */ + if (appDb) + { + m_appSwitchTableProducer = make_shared(appDb, APP_SWITCH_TABLE_NAME); + } } -SwitchConfVlan::~SwitchConfVlan() +SwitchConf::~SwitchConf() { - } -void SwitchConfVlan::syncCfgDB() +void SwitchConf::syncCfgDB() { - CfgOrch::syncCfgDB(CFG_SWITCH_TABLE_NAME, m_cfgSwitchTableConsumer); + OrchBase::syncDB(CFG_SWITCH_TABLE_NAME, m_cfgSwitchTable); } /* * ls /sys/class/net/Bridge/brif/ | xargs -n 1 -I % sh -c 'echo %; echo 0 > /sys/class/net/Bridge/brif/%/unicast_flood' */ -void SwitchConfVlan::updateHostFloodControl(string brif) +void SwitchConf::updateHostFloodControl(string brif) { string brif_path = "/sys/class/net/"; string cmd, res; @@ -88,7 +94,7 @@ void SwitchConfVlan::updateHostFloodControl(string brif) } } -void SwitchConfVlan::getHostFloodSetting(bool &flood, string &action) +void SwitchConf::getHostFloodSetting(bool &flood, string &action) { if (action == "forward" || action == "trap") { @@ -101,7 +107,7 @@ void SwitchConfVlan::getHostFloodSetting(bool &flood, string &action) } -void SwitchConfVlan::doTask(Consumer &consumer) +void SwitchConf::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -130,7 +136,10 @@ void SwitchConfVlan::doTask(Consumer &consumer) } string all_brif; updateHostFloodControl(all_brif); - m_appSwitchTableProducer.set(key, kfvFieldsValues(t)); + if (m_appSwitchTableProducer !=nullptr) + { + m_appSwitchTableProducer->set(key, kfvFieldsValues(t)); + } } it = consumer.m_toSync.erase(it); diff --git a/vlanconfd/switchconfvlan.h b/cfgagent/switchconf.h similarity index 56% rename from vlanconfd/switchconfvlan.h rename to cfgagent/switchconf.h index 40f3d19aa05..d049601dc30 100644 --- a/vlanconfd/switchconfvlan.h +++ b/cfgagent/switchconf.h @@ -1,8 +1,8 @@ -#ifndef __SWITCHCONFVLAN__ -#define __SWITCHCONFVLAN__ +#ifndef __SWITCHCONF__ +#define __SWITCHCONF__ #include "dbconnector.h" -#include "cfgorch.h" +#include "orchbase.h" #include #include @@ -10,11 +10,11 @@ namespace swss { -class SwitchConfVlan : public CfgOrch +class SwitchConf : public OrchBase { public: - SwitchConfVlan(DBConnector *cfgDb, DBConnector *appDb, string tableName); - virtual ~SwitchConfVlan(); + SwitchConf(DBConnector *cfgDb, DBConnector *appDb, string tableName); + virtual ~SwitchConf(); void updateHostFloodControl(string brif); void syncCfgDB(); private: @@ -22,8 +22,8 @@ class SwitchConfVlan : public CfgOrch bool m_multicast_miss_flood = true; bool m_broadcast_flood = true; - ProducerStateTable m_appSwitchTableProducer; - Table m_cfgSwitchTableConsumer; + shared_ptr m_appSwitchTableProducer = nullptr; + Table m_cfgSwitchTable; void doTask(Consumer &consumer); void getHostFloodSetting(bool &flood, string &action); diff --git a/vlanconfd/vlanconf.cpp b/cfgagent/vlanconf.cpp similarity index 97% rename from vlanconfd/vlanconf.cpp rename to cfgagent/vlanconf.cpp index 3c06d116dab..1194b6fa109 100644 --- a/vlanconfd/vlanconf.cpp +++ b/cfgagent/vlanconf.cpp @@ -3,7 +3,7 @@ #include "producerstatetable.h" #include "macaddress.h" #include "vlanconf.h" -#include "switchconfvlan.h" +#include "switchconf.h" #include "exec.h" #include "tokenize.h" @@ -16,10 +16,10 @@ using namespace swss; #define DEFAULT_VLAN_ID 1 extern MacAddress gMacAddress; -extern SwitchConfVlan *gSwtichConfVlan; +extern SwitchConf *gSwtichConfVlan; VlanConf::VlanConf(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, vector tableNames) : - CfgOrch(cfgDb, tableNames), + OrchBase(cfgDb, tableNames), m_cfgVlanTable(cfgDb, CFG_VLAN_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), m_cfgVlanMemberTable(cfgDb, CFG_VLAN_MEMBER_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), m_statePortTable(stateDb, STATE_PORT_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), @@ -51,8 +51,8 @@ VlanConf::VlanConf(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, void VlanConf::syncCfgDB() { - CfgOrch::syncCfgDB(CFG_VLAN_TABLE_NAME, m_cfgVlanTable); - CfgOrch::syncCfgDB(CFG_VLAN_MEMBER_TABLE_NAME, m_cfgVlanMemberTable); + OrchBase::syncDB(CFG_VLAN_TABLE_NAME, m_cfgVlanTable); + OrchBase::syncDB(CFG_VLAN_MEMBER_TABLE_NAME, m_cfgVlanMemberTable); } bool VlanConf::addHostVlan(int vlan_id) @@ -404,6 +404,7 @@ void VlanConf::doVlanMemberTask(Consumer &consumer) vlan_alias = VLAN_PREFIX + to_string(vlan_id); string op = kfvOp(t); + // TODO: store port/lag/VLAN data in local data structure and perform more validations. if (op == SET_COMMAND) { /* Don't proceed if member port/lag is not ready yet */ diff --git a/vlanconfd/vlanconf.h b/cfgagent/vlanconf.h similarity index 95% rename from vlanconfd/vlanconf.h rename to cfgagent/vlanconf.h index ec30190faa1..ce2589e1b7c 100644 --- a/vlanconfd/vlanconf.h +++ b/cfgagent/vlanconf.h @@ -3,7 +3,7 @@ #include "dbconnector.h" #include "producerstatetable.h" -#include "cfgorch.h" +#include "orchbase.h" #include #include @@ -11,7 +11,7 @@ namespace swss { -class VlanConf : public CfgOrch +class VlanConf : public OrchBase { public: VlanConf(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, vector tableNames); diff --git a/vlanconfd/vlanconfd.cpp b/cfgagent/vlanconfd.cpp similarity index 82% rename from vlanconfd/vlanconfd.cpp rename to cfgagent/vlanconfd.cpp index 6daa677eaa7..32c142727b2 100644 --- a/vlanconfd/vlanconfd.cpp +++ b/cfgagent/vlanconfd.cpp @@ -6,7 +6,7 @@ #include "schema.h" #include "macaddress.h" #include "producerstatetable.h" -#include "switchconfvlan.h" +#include "switchconf.h" #include "vlanconf.h" using namespace std; @@ -16,7 +16,7 @@ using namespace swss; #define SELECT_TIMEOUT 1000 MacAddress gMacAddress; -SwitchConfVlan *gSwtichConfVlan; +SwitchConf *gSwtichConfVlan; int main(int argc, char **argv) { @@ -25,7 +25,7 @@ int main(int argc, char **argv) SWSS_LOG_NOTICE("--- Starting vlanconfd ---"); - string mac_str, cfg_mac_str; + string mac_str; swss::exec("ip link show eth0 | grep ether | awk '{print $2}'", mac_str); gMacAddress = mac_str; @@ -40,13 +40,14 @@ int main(int argc, char **argv) DBConnector appDb(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); - gSwtichConfVlan = new SwitchConfVlan(&cfgDb, &appDb, CFG_SWITCH_TABLE_NAME); + + gSwtichConfVlan = new SwitchConf(&cfgDb, &appDb, CFG_SWITCH_TABLE_NAME); VlanConf vlanconf(&cfgDb, &appDb, &stateDb, cfg_vlan_tables); - std::vector cfgOrchList = {&vlanconf, gSwtichConfVlan}; + std::vector cfgOrchList = {&vlanconf, gSwtichConfVlan}; swss::Select s; - for (CfgOrch *o : cfgOrchList) + for (OrchBase *o : cfgOrchList) { s.addSelectables(o->getSelectables()); } @@ -65,11 +66,11 @@ int main(int argc, char **argv) } if (ret == Select::TIMEOUT) { - ((CfgOrch *)&vlanconf)->doTask(); + ((OrchBase *)&vlanconf)->doTask(); continue; } - for (CfgOrch *o : cfgOrchList) + for (OrchBase *o : cfgOrchList) { TableConsumable *c = (TableConsumable *)sel; if (o->hasSelectable(c)) @@ -83,5 +84,5 @@ int main(int argc, char **argv) { SWSS_LOG_ERROR("Runtime error: %s", e.what()); } - return 0; + return -1; } diff --git a/configure.ac b/configure.ac index 6aa52af22e8..ae5b49a8b20 100644 --- a/configure.ac +++ b/configure.ac @@ -87,7 +87,7 @@ AC_CONFIG_FILES([ teamsyncd/Makefile swssconfig/Makefile tests/Makefile - vlanconfd/Makefile + cfgagent/Makefile ]) AC_OUTPUT diff --git a/vlanconfd/Makefile.am b/vlanconfd/Makefile.am deleted file mode 100644 index a246bc00066..00000000000 --- a/vlanconfd/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/cfgorch - -bin_PROGRAMS = vlanconfd - -if DEBUG -DBGFLAGS = -ggdb -DDEBUG -else -DBGFLAGS = -g -endif - -vlanconfd_SOURCES = vlanconfd.cpp vlanconf.cpp switchconfvlan.cpp $(top_srcdir)/cfgorch/cfgorch.cpp - -vlanconfd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) -vlanconfd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) -vlanconfd_LDADD = -lswsscommon From ccba8ee12a2a2040975c7b618d309f800d32af41 Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Wed, 25 Oct 2017 17:00:41 -0700 Subject: [PATCH 3/7] Rename vlanconf to vlanmgr, and spin off switchmgr Signed-off-by: Jipan Yang --- .gitignore | 2 +- cfgagent/Makefile.am | 11 +- cfgagent/switchconf.cpp | 148 ------------------ cfgagent/switchconf.h | 34 ----- cfgagent/vlanconf.h | 44 ------ cfgagent/{vlanconf.cpp => vlanmgr.cpp} | 187 +++++++++++------------ cfgagent/vlanmgr.h | 44 ++++++ cfgagent/{vlanconfd.cpp => vlanmgrd.cpp} | 18 +-- 8 files changed, 149 insertions(+), 339 deletions(-) delete mode 100644 cfgagent/switchconf.cpp delete mode 100644 cfgagent/switchconf.h delete mode 100644 cfgagent/vlanconf.h rename cfgagent/{vlanconf.cpp => vlanmgr.cpp} (73%) create mode 100644 cfgagent/vlanmgr.h rename cfgagent/{vlanconfd.cpp => vlanmgrd.cpp} (77%) diff --git a/.gitignore b/.gitignore index 6fca1966e2b..0bfa4d8bc15 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,7 @@ deps/ teamsyncd/teamsyncd fpmsyncd/fpmsyncd intfsyncd/intfsyncd -cfgagent/vlanconfd +cfgagent/vlanmgrd neighsyncd/neighsyncd portsyncd/portsyncd orchagent/orchagent diff --git a/cfgagent/Makefile.am b/cfgagent/Makefile.am index 379ddfa0a8a..6abef240111 100644 --- a/cfgagent/Makefile.am +++ b/cfgagent/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/orchagent CFLAGS_SAI = -I /usr/include/sai -bin_PROGRAMS = vlanconfd +bin_PROGRAMS = vlanmgrd if DEBUG DBGFLAGS = -ggdb -DDEBUG @@ -9,7 +9,8 @@ else DBGFLAGS = -g endif -vlanconfd_SOURCES = vlanconfd.cpp vlanconf.cpp switchconf.cpp $(top_srcdir)/orchagent/orchbase.cpp -vlanconfd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) -vlanconfd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) -vlanconfd_LDADD = -lswsscommon \ No newline at end of file +vlanmgrd_SOURCES = vlanmgrd.cpp vlanmgr.cpp $(top_srcdir)/orchagent/orchbase.cpp +vlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) +vlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) +vlanmgrd_LDADD = -lswsscommon + diff --git a/cfgagent/switchconf.cpp b/cfgagent/switchconf.cpp deleted file mode 100644 index 6868c62c3db..00000000000 --- a/cfgagent/switchconf.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include -#include "logger.h" -#include "dbconnector.h" -#include "producerstatetable.h" -#include "switchconf.h" -#include "exec.h" - -using namespace std; -using namespace swss; - -#define DOT1Q_BRIDGE_NAME "Bridge" -#define CFG_SWITCH_ATTR_NAME "SWITCH_ATTR" - -SwitchConf::SwitchConf(DBConnector *cfgDb, DBConnector *appDb, string tableName) : - OrchBase(cfgDb, tableName), - m_cfgSwitchTable(cfgDb, tableName, CONFIGDB_TABLE_NAME_SEPARATOR) -{ - /* - * There could be multiple configDB enforcers listening on SWITCH table. - * Only one of them will pass the configuration down to appDB, others - * get the config data for local consumtion. - */ - if (appDb) - { - m_appSwitchTableProducer = make_shared(appDb, APP_SWITCH_TABLE_NAME); - } -} - -SwitchConf::~SwitchConf() -{ -} - -void SwitchConf::syncCfgDB() -{ - OrchBase::syncDB(CFG_SWITCH_TABLE_NAME, m_cfgSwitchTable); -} - -/* - * ls /sys/class/net/Bridge/brif/ | xargs -n 1 -I % sh -c 'echo %; echo 0 > /sys/class/net/Bridge/brif/%/unicast_flood' - */ -void SwitchConf::updateHostFloodControl(string brif) -{ - string brif_path = "/sys/class/net/"; - string cmd, res; - string unicast_op, multicast_op, broadcast_op; - struct stat sb; - - brif_path += DOT1Q_BRIDGE_NAME; - brif_path += "/brif/"; - - if (stat(brif_path.c_str(), &sb) || !S_ISDIR(sb.st_mode)) - { - SWSS_LOG_INFO("updateHostFloodControl: %s doens't exist", brif_path.c_str()); - return; - } - - unicast_op = (m_unicast_miss_flood ? " 1 > " : " 0 > "); - multicast_op = (m_multicast_miss_flood ? " 1 > " : " 0 > "); - broadcast_op = (m_broadcast_flood ? " 1 > " : " 0 > "); - - if (brif.empty()) - { - string cmd_prefix; - /* Apply to all bridge ports in 1q bridge */ - cmd_prefix = "ls " + brif_path; - cmd_prefix += " | xargs -n 1 -I % sh -c 'echo"; - - cmd = cmd_prefix + unicast_op; - cmd += brif_path + "%/unicast_flood'"; - swss::exec(cmd, res); - - cmd = cmd_prefix + multicast_op; - cmd += brif_path + "%/multicast_flood'"; - swss::exec(cmd, res); - - cmd = cmd_prefix + broadcast_op; - cmd += brif_path + "%/broadcast_flood'"; - swss::exec(cmd, res); - } - else - { - cmd = "echo" + unicast_op; - cmd += brif_path + brif + "/unicast_flood"; - swss::exec(cmd, res); - - cmd = "echo" + multicast_op; - cmd += brif_path + brif + "/multicast_flood"; - swss::exec(cmd, res); - - cmd = "echo" + broadcast_op; - cmd += brif_path + brif + "/broadcast_flood"; - swss::exec(cmd, res); - } -} - -void SwitchConf::getHostFloodSetting(bool &flood, string &action) -{ - if (action == "forward" || action == "trap") - { - flood = true; - } - else - { - flood = false; - } - -} - -void SwitchConf::doTask(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); - - SWSS_LOG_DEBUG("Switch doTask: %s", (dumpTuple(consumer, t)).c_str()); - - if (key == CFG_SWITCH_ATTR_NAME) - { - for (auto i : kfvFieldsValues(t)) - { - if (fvField(i) == "fdb_unicast_miss_packet_action") { - getHostFloodSetting(m_unicast_miss_flood, fvValue(i)); - } - else if (fvField(i) == "fdb_multicast_miss_packet_action") { - getHostFloodSetting(m_multicast_miss_flood, fvValue(i)); - } - else if (fvField(i) == "fdb_broadcast_miss_packet_action") { - getHostFloodSetting(m_broadcast_flood, fvValue(i)); - } - } - string all_brif; - updateHostFloodControl(all_brif); - if (m_appSwitchTableProducer !=nullptr) - { - m_appSwitchTableProducer->set(key, kfvFieldsValues(t)); - } - } - - it = consumer.m_toSync.erase(it); - continue; - } -} \ No newline at end of file diff --git a/cfgagent/switchconf.h b/cfgagent/switchconf.h deleted file mode 100644 index d049601dc30..00000000000 --- a/cfgagent/switchconf.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __SWITCHCONF__ -#define __SWITCHCONF__ - -#include "dbconnector.h" -#include "orchbase.h" - -#include -#include - -namespace swss { - - -class SwitchConf : public OrchBase -{ -public: - SwitchConf(DBConnector *cfgDb, DBConnector *appDb, string tableName); - virtual ~SwitchConf(); - void updateHostFloodControl(string brif); - void syncCfgDB(); -private: - bool m_unicast_miss_flood = true; - bool m_multicast_miss_flood = true; - bool m_broadcast_flood = true; - - shared_ptr m_appSwitchTableProducer = nullptr; - Table m_cfgSwitchTable; - - void doTask(Consumer &consumer); - void getHostFloodSetting(bool &flood, string &action); -}; - -} - -#endif diff --git a/cfgagent/vlanconf.h b/cfgagent/vlanconf.h deleted file mode 100644 index ce2589e1b7c..00000000000 --- a/cfgagent/vlanconf.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __VLANCONF__ -#define __VLANCONF__ - -#include "dbconnector.h" -#include "producerstatetable.h" -#include "orchbase.h" - -#include -#include -#include - -namespace swss { - -class VlanConf : public OrchBase -{ -public: - VlanConf(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, vector tableNames); - void syncCfgDB(); -private: - ProducerStateTable m_appVlanTableProducer, m_appVlanMemberTableProducer; - Table m_cfgVlanTable, m_cfgVlanMemberTable; - Table m_statePortTable, m_stateLagTable; - Table m_stateVlanTable; - std::set m_vlans; - - void doTask(Consumer &consumer); - void doVlanTask(Consumer &consumer); - void doVlanMemberTask(Consumer &consumer); - void processUntaggedVlanMembers(string vlan, string &members); - - bool addHostVlan(int vlan_id); - bool removeHostVlan(int vlan_id); - bool setHostVlanAdminState(int vlan_id, string &admin_status); - bool setHostVlanMtu(int vlan_id, uint32_t mtu); - bool addHostVlanMember(int vlan_id, string &port_alias, string& tagging_mode); - bool removeHostVlanMember(int vlan_id, string &port_alias); - bool isMemberStateOk(string &alias); - bool isVlanStateOk(string &alias); - bool isVlanMacOk(); -}; - -} - -#endif diff --git a/cfgagent/vlanconf.cpp b/cfgagent/vlanmgr.cpp similarity index 73% rename from cfgagent/vlanconf.cpp rename to cfgagent/vlanmgr.cpp index 1194b6fa109..08a9ea3b544 100644 --- a/cfgagent/vlanconf.cpp +++ b/cfgagent/vlanmgr.cpp @@ -2,8 +2,7 @@ #include "logger.h" #include "producerstatetable.h" #include "macaddress.h" -#include "vlanconf.h" -#include "switchconf.h" +#include "vlanmgr.h" #include "exec.h" #include "tokenize.h" @@ -16,9 +15,8 @@ using namespace swss; #define DEFAULT_VLAN_ID 1 extern MacAddress gMacAddress; -extern SwitchConf *gSwtichConfVlan; -VlanConf::VlanConf(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, vector tableNames) : +VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector &tableNames) : OrchBase(cfgDb, tableNames), m_cfgVlanTable(cfgDb, CFG_VLAN_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), m_cfgVlanMemberTable(cfgDb, CFG_VLAN_MEMBER_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), @@ -31,147 +29,144 @@ VlanConf::VlanConf(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, SWSS_LOG_ENTER(); // Initialize Linux dot1q bridge and enable vlan filtering - string cmd, res; - - cmd = "ip link del "; - cmd += DOT1Q_BRIDGE_NAME; - swss::exec(cmd, res); - cmd = "ip link add "; - cmd += DOT1Q_BRIDGE_NAME; - cmd += " up type bridge"; - swss::exec(cmd, res); - cmd = "echo 1 > /sys/class/net/"; - cmd += DOT1Q_BRIDGE_NAME; - cmd += "/bridge/vlan_filtering"; - swss::exec(cmd, res); - cmd = "bridge vlan del vid " + std::to_string(DEFAULT_VLAN_ID) - + " dev " + DOT1Q_BRIDGE_NAME + " self"; - swss::exec(cmd, res); + stringstream cmd; + string res; + + cmd << "ip link del " << DOT1Q_BRIDGE_NAME; + swss::exec(cmd.str(), res); + + cmd.str(""); + cmd << "ip link add " << DOT1Q_BRIDGE_NAME << " up type bridge"; + swss::exec(cmd.str(), res); + + cmd.str(""); + cmd << "echo 1 > /sys/class/net/" << DOT1Q_BRIDGE_NAME << "/bridge/vlan_filtering"; + swss::exec(cmd.str(), res); + + cmd.str(""); + cmd << "bridge vlan del vid " << DEFAULT_VLAN_ID << " dev " << DOT1Q_BRIDGE_NAME << " self"; + swss::exec(cmd.str(), res); } -void VlanConf::syncCfgDB() +void VlanMgr::syncCfgDB() { OrchBase::syncDB(CFG_VLAN_TABLE_NAME, m_cfgVlanTable); OrchBase::syncDB(CFG_VLAN_MEMBER_TABLE_NAME, m_cfgVlanMemberTable); } -bool VlanConf::addHostVlan(int vlan_id) +bool VlanMgr::addHostVlan(int vlan_id) { - string cmd, res; - - cmd = "bridge vlan add vid " + to_string(vlan_id) + " dev " - + DOT1Q_BRIDGE_NAME + " self"; - swss::exec(cmd, res); - cmd = "ip link add link "; - cmd += DOT1Q_BRIDGE_NAME; - cmd += " name "; - cmd += VLAN_PREFIX + to_string(vlan_id) - + " type vlan id " + to_string(vlan_id); - swss::exec(cmd, res); - - cmd = "ip link set "; - cmd += VLAN_PREFIX + to_string(vlan_id); - cmd += " address " + gMacAddress.to_string(); - swss::exec(cmd, res); + stringstream cmd; + string res; + + cmd << "bridge vlan add vid " << vlan_id << " dev " << DOT1Q_BRIDGE_NAME << " self"; + swss::exec(cmd.str(), res); + + cmd.str(""); + cmd << "ip link add link " << DOT1Q_BRIDGE_NAME << " name " << VLAN_PREFIX << vlan_id << " type vlan id " << vlan_id; + swss::exec(cmd.str(), res); + + cmd.str(""); + cmd << "ip link set " << VLAN_PREFIX << vlan_id << " address " << gMacAddress.to_string(); + swss::exec(cmd.str(), res); // Bring up vlan port by default - cmd = "ip link set "; - cmd += VLAN_PREFIX + to_string(vlan_id); - cmd += " up"; - swss::exec(cmd, res); + cmd.str(""); + cmd << "ip link set " << VLAN_PREFIX << vlan_id << " up"; + swss::exec(cmd.str(), res); return true; } -bool VlanConf::removeHostVlan(int vlan_id) +bool VlanMgr::removeHostVlan(int vlan_id) { - string cmd, res; + stringstream cmd; + string res; - cmd = "ip link del "; - cmd += VLAN_PREFIX + to_string(vlan_id); - swss::exec(cmd, res); + cmd << "ip link del " << VLAN_PREFIX << vlan_id; + swss::exec(cmd.str(), res); - cmd = "bridge vlan del vid " + to_string(vlan_id) + " dev " - + DOT1Q_BRIDGE_NAME + " self"; - swss::exec(cmd, res); + cmd.str(""); + cmd << "bridge vlan del vid " << vlan_id << " dev " << DOT1Q_BRIDGE_NAME << " self"; + swss::exec(cmd.str(), res); return true; } -bool VlanConf::setHostVlanAdminState(int vlan_id, string &admin_status) +bool VlanMgr::setHostVlanAdminState(int vlan_id, const string &admin_status) { - string cmd, res; + stringstream cmd; + string res; - cmd = "ip link set "; - cmd += VLAN_PREFIX + to_string(vlan_id) + " " + admin_status; - swss::exec(cmd, res); + cmd << "ip link set " << VLAN_PREFIX << vlan_id << " " << admin_status; + swss::exec(cmd.str(), res); return true; } -bool VlanConf::setHostVlanMtu(int vlan_id, uint32_t mtu) +bool VlanMgr::setHostVlanMtu(int vlan_id, uint32_t mtu) { - string cmd, res; + stringstream cmd; + string res; - cmd = "ip link set "; - cmd += VLAN_PREFIX + to_string(vlan_id) + " mtu " + to_string(mtu); - swss::exec(cmd, res); + cmd << "ip link set " << VLAN_PREFIX << vlan_id << " mtu " << mtu; + swss::exec(cmd.str(), res); return true; } -bool VlanConf::addHostVlanMember(int vlan_id, string &port_alias, string& tagging_mode) +bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const string& tagging_mode) { - string cmd, res; + stringstream cmd; + string res; // Should be ok to run set master command more than one time. - cmd = "ip link set " + port_alias + " master " + DOT1Q_BRIDGE_NAME; - swss::exec(cmd, res); + cmd << "ip link set " << port_alias << " master " << DOT1Q_BRIDGE_NAME; + swss::exec(cmd.str(), res); + cmd.str(""); if (tagging_mode == "untagged" || tagging_mode == "priority_tagged") { // We are setting pvid as untagged vlan id. - cmd = "bridge vlan add vid " + to_string(vlan_id) + " dev " - + port_alias + " pvid untagged"; + cmd << "bridge vlan add vid " << vlan_id << " dev " << port_alias << " pvid untagged"; } else { - cmd = "bridge vlan add vid " + to_string(vlan_id) + " dev " - + port_alias; + cmd << "bridge vlan add vid " << vlan_id << " dev " << port_alias; } - swss::exec(cmd, res); - // Apply switch level flood control to this port - gSwtichConfVlan->updateHostFloodControl(port_alias); + swss::exec(cmd.str(), res); + cmd.str(""); // Bring up vlan member port and set MTU to 9100 by default - cmd = "ip link set " + port_alias + " up mtu 9100"; - swss::exec(cmd, res); + cmd << "ip link set " << port_alias << " up mtu 9100"; + swss::exec(cmd.str(), res); return true; } - -bool VlanConf::removeHostVlanMember(int vlan_id, string &port_alias) +bool VlanMgr::removeHostVlanMember(int vlan_id, const string &port_alias) { - string cmd, res; + stringstream cmd; + string res; - cmd = "bridge vlan del vid " + to_string(vlan_id) + " dev " - + port_alias; - swss::exec(cmd, res); + cmd << "bridge vlan del vid " << vlan_id << " dev " << port_alias; + swss::exec(cmd.str(), res); + cmd.str(""); // When port is not member of any VLAN, it shall be detached from Dot1Q bridge! - cmd = "bridge vlan show dev " + port_alias + " | grep None"; - swss::exec(cmd, res); + cmd << "bridge vlan show dev " << port_alias << " | grep None"; + swss::exec(cmd.str(), res); if (!res.empty()) { - cmd = "ip link set " + port_alias + " nomaster"; - swss::exec(cmd, res); + cmd.str(""); + cmd << "ip link set " << port_alias << " nomaster"; + swss::exec(cmd.str(), res); } return true; } -bool VlanConf::isVlanMacOk() +bool VlanMgr::isVlanMacOk() { return !(!gMacAddress); } -void VlanConf::doVlanTask(Consumer &consumer) +void VlanMgr::doVlanTask(Consumer &consumer) { if (!isVlanMacOk()) @@ -283,7 +278,7 @@ void VlanConf::doVlanTask(Consumer &consumer) } } -bool VlanConf::isMemberStateOk(string &alias) +bool VlanMgr::isMemberStateOk(const string &alias) { vector temp; @@ -291,20 +286,20 @@ bool VlanConf::isMemberStateOk(string &alias) { if (m_stateLagTable.get(alias, temp)) { - SWSS_LOG_DEBUG("%s is ready\n", alias.c_str()); + SWSS_LOG_DEBUG("%s is ready", alias.c_str()); return true; } } else if (m_statePortTable.get(alias, temp)) { - SWSS_LOG_DEBUG("%s is ready\n", alias.c_str()); + SWSS_LOG_DEBUG("%s is ready", alias.c_str()); return true; } - SWSS_LOG_DEBUG("%s is not ready\n", alias.c_str()); + SWSS_LOG_DEBUG("%s is not ready", alias.c_str()); return false; } -bool VlanConf::isVlanStateOk(string &alias) +bool VlanMgr::isVlanStateOk(const string &alias) { vector temp; @@ -312,11 +307,11 @@ bool VlanConf::isVlanStateOk(string &alias) { if (m_stateVlanTable.get(alias, temp)) { - SWSS_LOG_DEBUG("%s is ready\n", alias.c_str()); + SWSS_LOG_DEBUG("%s is ready", alias.c_str()); return true; } } - SWSS_LOG_DEBUG("%s is not ready\n", alias.c_str()); + SWSS_LOG_DEBUG("%s is not ready", alias.c_str()); return false; } @@ -327,7 +322,7 @@ bool VlanConf::isVlanStateOk(string &alias) * Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18, * Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24" */ -void VlanConf::processUntaggedVlanMembers(string vlan, string &members) +void VlanMgr::processUntaggedVlanMembers(string vlan, const string &members) { auto consumer_it = m_consumerMap.find(CFG_VLAN_MEMBER_TABLE_NAME); @@ -367,7 +362,7 @@ void VlanConf::processUntaggedVlanMembers(string vlan, string &members) return; } -void VlanConf::doVlanMemberTask(Consumer &consumer) +void VlanMgr::doVlanMemberTask(Consumer &consumer) { auto it = consumer.m_toSync.begin(); while (it != consumer.m_toSync.end()) @@ -457,7 +452,7 @@ void VlanConf::doVlanMemberTask(Consumer &consumer) } } -void VlanConf::doTask(Consumer &consumer) +void VlanMgr::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -470,6 +465,6 @@ void VlanConf::doTask(Consumer &consumer) else { SWSS_LOG_ERROR("Unknown config table %s ", table_name.c_str()); - throw runtime_error("VlanConf doTask failure."); + throw runtime_error("VlanMgr doTask failure."); } } diff --git a/cfgagent/vlanmgr.h b/cfgagent/vlanmgr.h new file mode 100644 index 00000000000..2ca8cb2a7af --- /dev/null +++ b/cfgagent/vlanmgr.h @@ -0,0 +1,44 @@ +#ifndef __VLANMGR__ +#define __VLANMGR__ + +#include "dbconnector.h" +#include "producerstatetable.h" +#include "orchbase.h" + +#include +#include +#include + +namespace swss { + +class VlanMgr : public OrchBase +{ +public: + VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector &tableNames); + void syncCfgDB(); +private: + ProducerStateTable m_appVlanTableProducer, m_appVlanMemberTableProducer; + Table m_cfgVlanTable, m_cfgVlanMemberTable; + Table m_statePortTable, m_stateLagTable; + Table m_stateVlanTable; + std::set m_vlans; + + void doTask(Consumer &consumer); + void doVlanTask(Consumer &consumer); + void doVlanMemberTask(Consumer &consumer); + void processUntaggedVlanMembers(string vlan, const string &members); + + bool addHostVlan(int vlan_id); + bool removeHostVlan(int vlan_id); + bool setHostVlanAdminState(int vlan_id, const string &admin_status); + bool setHostVlanMtu(int vlan_id, uint32_t mtu); + bool addHostVlanMember(int vlan_id, const string &port_alias, const string& tagging_mode); + bool removeHostVlanMember(int vlan_id, const string &port_alias); + bool isMemberStateOk(const string &alias); + bool isVlanStateOk(const string &alias); + bool isVlanMacOk(); +}; + +} + +#endif diff --git a/cfgagent/vlanconfd.cpp b/cfgagent/vlanmgrd.cpp similarity index 77% rename from cfgagent/vlanconfd.cpp rename to cfgagent/vlanmgrd.cpp index 32c142727b2..a8ef83f7bfd 100644 --- a/cfgagent/vlanconfd.cpp +++ b/cfgagent/vlanmgrd.cpp @@ -6,8 +6,7 @@ #include "schema.h" #include "macaddress.h" #include "producerstatetable.h" -#include "switchconf.h" -#include "vlanconf.h" +#include "vlanmgr.h" using namespace std; using namespace swss; @@ -16,14 +15,13 @@ using namespace swss; #define SELECT_TIMEOUT 1000 MacAddress gMacAddress; -SwitchConf *gSwtichConfVlan; int main(int argc, char **argv) { - Logger::linkToDbNative("vlanconfd"); + Logger::linkToDbNative("vlanmgrd"); SWSS_LOG_ENTER(); - SWSS_LOG_NOTICE("--- Starting vlanconfd ---"); + SWSS_LOG_NOTICE("--- Starting vlanmgrd ---"); string mac_str; swss::exec("ip link show eth0 | grep ether | awk '{print $2}'", mac_str); @@ -40,11 +38,9 @@ int main(int argc, char **argv) DBConnector appDb(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + VlanMgr vlanmgr(&cfgDb, &appDb, &stateDb, cfg_vlan_tables); - gSwtichConfVlan = new SwitchConf(&cfgDb, &appDb, CFG_SWITCH_TABLE_NAME); - VlanConf vlanconf(&cfgDb, &appDb, &stateDb, cfg_vlan_tables); - - std::vector cfgOrchList = {&vlanconf, gSwtichConfVlan}; + std::vector cfgOrchList = {&vlanmgr}; swss::Select s; for (OrchBase *o : cfgOrchList) @@ -61,12 +57,12 @@ int main(int argc, char **argv) ret = s.select(&sel, &fd, SELECT_TIMEOUT); if (ret == Select::ERROR) { - SWSS_LOG_NOTICE("Error: %s!\n", strerror(errno)); + SWSS_LOG_NOTICE("Error: %s!", strerror(errno)); continue; } if (ret == Select::TIMEOUT) { - ((OrchBase *)&vlanconf)->doTask(); + ((OrchBase *)&vlanmgr)->doTask(); continue; } From 686b86f4a78726fbfd673a26de9ce874f8f0e01a Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Sun, 29 Oct 2017 18:12:19 +0800 Subject: [PATCH 4/7] Use shell full path command macros Signed-off-by: Jipan Yang --- cfgagent/Makefile.am | 2 +- cfgagent/shellcmd.h | 15 +++++++++++++ cfgagent/vlanmgr.cpp | 49 +++++++++++++++++++++++++------------------ cfgagent/vlanmgrd.cpp | 6 +++++- 4 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 cfgagent/shellcmd.h diff --git a/cfgagent/Makefile.am b/cfgagent/Makefile.am index 6abef240111..3fd83db4551 100644 --- a/cfgagent/Makefile.am +++ b/cfgagent/Makefile.am @@ -9,7 +9,7 @@ else DBGFLAGS = -g endif -vlanmgrd_SOURCES = vlanmgrd.cpp vlanmgr.cpp $(top_srcdir)/orchagent/orchbase.cpp +vlanmgrd_SOURCES = vlanmgrd.cpp vlanmgr.cpp $(top_srcdir)/orchagent/orchbase.cpp shellcmd.h vlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) vlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) vlanmgrd_LDADD = -lswsscommon diff --git a/cfgagent/shellcmd.h b/cfgagent/shellcmd.h new file mode 100644 index 00000000000..4cca97deae0 --- /dev/null +++ b/cfgagent/shellcmd.h @@ -0,0 +1,15 @@ +#ifndef __SHELLCMD__ +#define __SHELLCMD__ + +#define IP_CMD "/sbin/ip" +#define BRIDGE_CMD "/sbin/bridge" +#define ECHO_CMD "/bin/echo" +#define REDIS_CLI_CMD "/usr/bin/redis-cli" +#define XARGS_CMD "/usr/bin/xargs" +#define GREP_CMD "/bin/grep" +#define AWK_CMD "/usr/bin/awk" +#define LS_CMD "/bin/ls" +#define PASTE_CMD "/usr/bin/paste" +#define SED_CMD "/bin/sed" + +#endif /* __SHELLCMD__ */ diff --git a/cfgagent/vlanmgr.cpp b/cfgagent/vlanmgr.cpp index 08a9ea3b544..1dab4ff31c9 100644 --- a/cfgagent/vlanmgr.cpp +++ b/cfgagent/vlanmgr.cpp @@ -5,6 +5,7 @@ #include "vlanmgr.h" #include "exec.h" #include "tokenize.h" +#include "shellcmd.h" using namespace std; using namespace swss; @@ -13,6 +14,8 @@ using namespace swss; #define VLAN_PREFIX "Vlan" #define LAG_PREFIX "PortChannel" #define DEFAULT_VLAN_ID 1 +#define MAX_MTU 9100 +#define VLAN_HLEN 4 extern MacAddress gMacAddress; @@ -32,19 +35,19 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c stringstream cmd; string res; - cmd << "ip link del " << DOT1Q_BRIDGE_NAME; + cmd << IP_CMD << " link del " << DOT1Q_BRIDGE_NAME; swss::exec(cmd.str(), res); cmd.str(""); - cmd << "ip link add " << DOT1Q_BRIDGE_NAME << " up type bridge"; + cmd << IP_CMD << " link add " << DOT1Q_BRIDGE_NAME << " up type bridge"; swss::exec(cmd.str(), res); cmd.str(""); - cmd << "echo 1 > /sys/class/net/" << DOT1Q_BRIDGE_NAME << "/bridge/vlan_filtering"; + cmd << ECHO_CMD << " 1 > /sys/class/net/" << DOT1Q_BRIDGE_NAME << "/bridge/vlan_filtering"; swss::exec(cmd.str(), res); cmd.str(""); - cmd << "bridge vlan del vid " << DEFAULT_VLAN_ID << " dev " << DOT1Q_BRIDGE_NAME << " self"; + cmd << BRIDGE_CMD << " vlan del vid " << DEFAULT_VLAN_ID << " dev " << DOT1Q_BRIDGE_NAME << " self"; swss::exec(cmd.str(), res); } @@ -59,20 +62,20 @@ bool VlanMgr::addHostVlan(int vlan_id) stringstream cmd; string res; - cmd << "bridge vlan add vid " << vlan_id << " dev " << DOT1Q_BRIDGE_NAME << " self"; + cmd << BRIDGE_CMD << " vlan add vid " << vlan_id << " dev " << DOT1Q_BRIDGE_NAME << " self"; swss::exec(cmd.str(), res); cmd.str(""); - cmd << "ip link add link " << DOT1Q_BRIDGE_NAME << " name " << VLAN_PREFIX << vlan_id << " type vlan id " << vlan_id; + cmd << IP_CMD << " link add link " << DOT1Q_BRIDGE_NAME << " name " << VLAN_PREFIX << vlan_id << " type vlan id " << vlan_id; swss::exec(cmd.str(), res); cmd.str(""); - cmd << "ip link set " << VLAN_PREFIX << vlan_id << " address " << gMacAddress.to_string(); + cmd << IP_CMD << " link set " << VLAN_PREFIX << vlan_id << " address " << gMacAddress.to_string(); swss::exec(cmd.str(), res); // Bring up vlan port by default cmd.str(""); - cmd << "ip link set " << VLAN_PREFIX << vlan_id << " up"; + cmd << IP_CMD << " link set " << VLAN_PREFIX << vlan_id << " up"; swss::exec(cmd.str(), res); return true; } @@ -82,11 +85,11 @@ bool VlanMgr::removeHostVlan(int vlan_id) stringstream cmd; string res; - cmd << "ip link del " << VLAN_PREFIX << vlan_id; + cmd << IP_CMD << " link del " << VLAN_PREFIX << vlan_id; swss::exec(cmd.str(), res); cmd.str(""); - cmd << "bridge vlan del vid " << vlan_id << " dev " << DOT1Q_BRIDGE_NAME << " self"; + cmd << BRIDGE_CMD << " vlan del vid " << vlan_id << " dev " << DOT1Q_BRIDGE_NAME << " self"; swss::exec(cmd.str(), res); return true; @@ -97,7 +100,7 @@ bool VlanMgr::setHostVlanAdminState(int vlan_id, const string &admin_status) stringstream cmd; string res; - cmd << "ip link set " << VLAN_PREFIX << vlan_id << " " << admin_status; + cmd << IP_CMD << " link set " << VLAN_PREFIX << vlan_id << " " << admin_status; swss::exec(cmd.str(), res); return true; } @@ -107,7 +110,7 @@ bool VlanMgr::setHostVlanMtu(int vlan_id, uint32_t mtu) stringstream cmd; string res; - cmd << "ip link set " << VLAN_PREFIX << vlan_id << " mtu " << mtu; + cmd << IP_CMD << " link set " << VLAN_PREFIX << vlan_id << " mtu " << mtu; swss::exec(cmd.str(), res); return true; } @@ -118,23 +121,23 @@ bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const str string res; // Should be ok to run set master command more than one time. - cmd << "ip link set " << port_alias << " master " << DOT1Q_BRIDGE_NAME; + cmd << IP_CMD << " link set " << port_alias << " master " << DOT1Q_BRIDGE_NAME; swss::exec(cmd.str(), res); cmd.str(""); if (tagging_mode == "untagged" || tagging_mode == "priority_tagged") { // We are setting pvid as untagged vlan id. - cmd << "bridge vlan add vid " << vlan_id << " dev " << port_alias << " pvid untagged"; + cmd << BRIDGE_CMD << " vlan add vid " << vlan_id << " dev " << port_alias << " pvid untagged"; } else { - cmd << "bridge vlan add vid " << vlan_id << " dev " << port_alias; + cmd << BRIDGE_CMD << " vlan add vid " << vlan_id << " dev " << port_alias; } swss::exec(cmd.str(), res); cmd.str(""); // Bring up vlan member port and set MTU to 9100 by default - cmd << "ip link set " << port_alias << " up mtu 9100"; + cmd << IP_CMD << " link set " << port_alias << " up mtu " << MAX_MTU; swss::exec(cmd.str(), res); return true; } @@ -144,17 +147,17 @@ bool VlanMgr::removeHostVlanMember(int vlan_id, const string &port_alias) stringstream cmd; string res; - cmd << "bridge vlan del vid " << vlan_id << " dev " << port_alias; + cmd << BRIDGE_CMD << " vlan del vid " << vlan_id << " dev " << port_alias; swss::exec(cmd.str(), res); cmd.str(""); // When port is not member of any VLAN, it shall be detached from Dot1Q bridge! - cmd << "bridge vlan show dev " << port_alias << " | grep None"; + cmd << BRIDGE_CMD << " vlan show dev " << port_alias << " | " << GREP_CMD << " None"; swss::exec(cmd.str(), res); if (!res.empty()) { cmd.str(""); - cmd << "ip link set " << port_alias << " nomaster"; + cmd << IP_CMD << " link set " << port_alias << " nomaster"; swss::exec(cmd.str(), res); } @@ -349,7 +352,7 @@ void VlanMgr::processUntaggedVlanMembers(string vlan, const string &members) SWSS_LOG_DEBUG("%s", (dumpTuple(consumer, consumer.m_toSync[member_key])).c_str()); } /* - * There is pending task from consumber pipe, in this case just skip it. + * There is pending task from consumer pipe, in this case just skip it. */ else { @@ -414,7 +417,9 @@ void VlanMgr::doVlanMemberTask(Consumer &consumer) for (auto i : kfvFieldsValues(t)) { if (fvField(i) == "tagging_mode") + { tagging_mode = fvValue(i); + } } if (tagging_mode != "untagged" && @@ -459,9 +464,13 @@ void VlanMgr::doTask(Consumer &consumer) string table_name = consumer.m_consumer->getTableName(); if (table_name == CFG_VLAN_TABLE_NAME) + { doVlanTask(consumer); + } else if (table_name == CFG_VLAN_MEMBER_TABLE_NAME) + { doVlanMemberTask(consumer); + } else { SWSS_LOG_ERROR("Unknown config table %s ", table_name.c_str()); diff --git a/cfgagent/vlanmgrd.cpp b/cfgagent/vlanmgrd.cpp index a8ef83f7bfd..7c0cd6b9ad1 100644 --- a/cfgagent/vlanmgrd.cpp +++ b/cfgagent/vlanmgrd.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "dbconnector.h" #include "select.h" #include "exec.h" @@ -7,6 +8,7 @@ #include "macaddress.h" #include "producerstatetable.h" #include "vlanmgr.h" +#include "shellcmd.h" using namespace std; using namespace swss; @@ -24,7 +26,9 @@ int main(int argc, char **argv) SWSS_LOG_NOTICE("--- Starting vlanmgrd ---"); string mac_str; - swss::exec("ip link show eth0 | grep ether | awk '{print $2}'", mac_str); + stringstream cmd; + cmd << IP_CMD << " link show eth0 | " << GREP_CMD << " ether | " << AWK_CMD << " '{print $2}'"; + swss::exec(cmd.str(), mac_str); gMacAddress = mac_str; try From 0f2e58769a1b21ab51e5ffad6f9f4981f982a379 Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Tue, 31 Oct 2017 10:36:04 +0800 Subject: [PATCH 5/7] Optimize shell command execution error handling Signed-off-by: Jipan Yang --- cfgagent/shellcmd.h | 8 +++++ cfgagent/vlanmgr.cpp | 73 ++++++++++++++++++++++++++----------------- cfgagent/vlanmgrd.cpp | 2 +- 3 files changed, 53 insertions(+), 30 deletions(-) diff --git a/cfgagent/shellcmd.h b/cfgagent/shellcmd.h index 4cca97deae0..e73416ff367 100644 --- a/cfgagent/shellcmd.h +++ b/cfgagent/shellcmd.h @@ -12,4 +12,12 @@ #define PASTE_CMD "/usr/bin/paste" #define SED_CMD "/bin/sed" +#define EXEC_WITH_ERROR_THROW(cmd, res) ({ \ + int ret = swss::exec(cmd, res); \ + if (ret != 0) \ + { \ + throw runtime_error(cmd + " : " + res); \ + } \ +}) + #endif /* __SHELLCMD__ */ diff --git a/cfgagent/vlanmgr.cpp b/cfgagent/vlanmgr.cpp index 1dab4ff31c9..6a075695ad7 100644 --- a/cfgagent/vlanmgr.cpp +++ b/cfgagent/vlanmgr.cpp @@ -40,15 +40,15 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c cmd.str(""); cmd << IP_CMD << " link add " << DOT1Q_BRIDGE_NAME << " up type bridge"; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); cmd.str(""); cmd << ECHO_CMD << " 1 > /sys/class/net/" << DOT1Q_BRIDGE_NAME << "/bridge/vlan_filtering"; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); cmd.str(""); cmd << BRIDGE_CMD << " vlan del vid " << DEFAULT_VLAN_ID << " dev " << DOT1Q_BRIDGE_NAME << " self"; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); } void VlanMgr::syncCfgDB() @@ -63,20 +63,21 @@ bool VlanMgr::addHostVlan(int vlan_id) string res; cmd << BRIDGE_CMD << " vlan add vid " << vlan_id << " dev " << DOT1Q_BRIDGE_NAME << " self"; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); cmd.str(""); cmd << IP_CMD << " link add link " << DOT1Q_BRIDGE_NAME << " name " << VLAN_PREFIX << vlan_id << " type vlan id " << vlan_id; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); cmd.str(""); cmd << IP_CMD << " link set " << VLAN_PREFIX << vlan_id << " address " << gMacAddress.to_string(); - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); // Bring up vlan port by default cmd.str(""); cmd << IP_CMD << " link set " << VLAN_PREFIX << vlan_id << " up"; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); + return true; } @@ -86,11 +87,11 @@ bool VlanMgr::removeHostVlan(int vlan_id) string res; cmd << IP_CMD << " link del " << VLAN_PREFIX << vlan_id; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); cmd.str(""); cmd << BRIDGE_CMD << " vlan del vid " << vlan_id << " dev " << DOT1Q_BRIDGE_NAME << " self"; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); return true; } @@ -101,7 +102,7 @@ bool VlanMgr::setHostVlanAdminState(int vlan_id, const string &admin_status) string res; cmd << IP_CMD << " link set " << VLAN_PREFIX << vlan_id << " " << admin_status; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); return true; } @@ -111,8 +112,13 @@ bool VlanMgr::setHostVlanMtu(int vlan_id, uint32_t mtu) string res; cmd << IP_CMD << " link set " << VLAN_PREFIX << vlan_id << " mtu " << mtu; - swss::exec(cmd.str(), res); - return true; + int ret = swss::exec(cmd.str(), res); + if (ret == 0) + { + return true; + } + /* VLAN mtu should not be larger than member mtu */ + return false; } bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const string& tagging_mode) @@ -122,7 +128,7 @@ bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const str // Should be ok to run set master command more than one time. cmd << IP_CMD << " link set " << port_alias << " master " << DOT1Q_BRIDGE_NAME; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); cmd.str(""); if (tagging_mode == "untagged" || tagging_mode == "priority_tagged") { @@ -133,12 +139,13 @@ bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const str { cmd << BRIDGE_CMD << " vlan add vid " << vlan_id << " dev " << port_alias; } - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); cmd.str(""); // Bring up vlan member port and set MTU to 9100 by default cmd << IP_CMD << " link set " << port_alias << " up mtu " << MAX_MTU; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); + return true; } @@ -148,17 +155,17 @@ bool VlanMgr::removeHostVlanMember(int vlan_id, const string &port_alias) string res; cmd << BRIDGE_CMD << " vlan del vid " << vlan_id << " dev " << port_alias; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); cmd.str(""); // When port is not member of any VLAN, it shall be detached from Dot1Q bridge! cmd << BRIDGE_CMD << " vlan show dev " << port_alias << " | " << GREP_CMD << " None"; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); if (!res.empty()) { cmd.str(""); cmd << IP_CMD << " link set " << port_alias << " nomaster"; - swss::exec(cmd.str(), res); + EXEC_WITH_ERROR_THROW(cmd.str(), res); } return true; @@ -215,16 +222,23 @@ void VlanMgr::doVlanTask(Consumer &consumer) /* set up host env .... */ for (auto i : kfvFieldsValues(t)) { - /* Set port admin status */ - if (fvField(i) == "admin_status") { + /* Set vlan admin status */ + if (fvField(i) == "admin_status") + { admin_status = fvValue(i); setHostVlanAdminState(vlan_id, admin_status); fvVector.push_back(i); } - /* Set port mtu */ - else if (fvField(i) == "mtu") { + /* Set vlan mtu */ + else if (fvField(i) == "mtu") + { mtu = (uint32_t)stoul(fvValue(i)); - setHostVlanMtu(vlan_id, mtu); + /* + * TODO: support host VLAN mtu setting. + * Host VLAN mtu should be set only after member configured + * and VLAN state is not UNKOWN. + */ + SWSS_LOG_DEBUG("%s mtu %u: Host VLAN mtu setting to be supported.", key.c_str(), mtu); fvVector.push_back(i); } else if (fvField(i) == "members@") { @@ -431,12 +445,13 @@ void VlanMgr::doVlanMemberTask(Consumer &consumer) continue; } - addHostVlanMember(vlan_id, port_alias, tagging_mode); - - key = VLAN_PREFIX + to_string(vlan_id); - key += DEFAULT_KEY_SEPARATOR; - key += port_alias; - m_appVlanMemberTableProducer.set(key, kfvFieldsValues(t)); + if (addHostVlanMember(vlan_id, port_alias, tagging_mode)) + { + key = VLAN_PREFIX + to_string(vlan_id); + key += DEFAULT_KEY_SEPARATOR; + key += port_alias; + m_appVlanMemberTableProducer.set(key, kfvFieldsValues(t)); + } it = consumer.m_toSync.erase(it); } else if (op == DEL_COMMAND) diff --git a/cfgagent/vlanmgrd.cpp b/cfgagent/vlanmgrd.cpp index 7c0cd6b9ad1..c34c0e07c39 100644 --- a/cfgagent/vlanmgrd.cpp +++ b/cfgagent/vlanmgrd.cpp @@ -28,7 +28,7 @@ int main(int argc, char **argv) string mac_str; stringstream cmd; cmd << IP_CMD << " link show eth0 | " << GREP_CMD << " ether | " << AWK_CMD << " '{print $2}'"; - swss::exec(cmd.str(), mac_str); + EXEC_WITH_ERROR_THROW(cmd.str(), mac_str); gMacAddress = mac_str; try From 5b27bfa7d31f19d6f29c94cc75698626e58bfefd Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Thu, 2 Nov 2017 18:11:26 +0800 Subject: [PATCH 6/7] Use Orch class for vlanmgrd orchestration Signed-off-by: Jipan Yang --- .gitignore | 2 +- Makefile.am | 2 +- {cfgagent => cfgmgr}/Makefile.am | 2 +- {cfgagent => cfgmgr}/shellcmd.h | 0 {cfgagent => cfgmgr}/vlanmgr.cpp | 8 +------- {cfgagent => cfgmgr}/vlanmgr.h | 6 +++--- {cfgagent => cfgmgr}/vlanmgrd.cpp | 27 +++++++++++++++++++++++---- configure.ac | 2 +- orchagent/orch.cpp | 19 +++++++++++++++---- orchagent/orch.h | 8 ++++++-- orchagent/saihelper.cpp | 16 +--------------- portsyncd/linksync.cpp | 2 -- portsyncd/portsyncd.cpp | 1 - 13 files changed, 53 insertions(+), 42 deletions(-) rename {cfgagent => cfgmgr}/Makefile.am (93%) rename {cfgagent => cfgmgr}/shellcmd.h (100%) rename {cfgagent => cfgmgr}/vlanmgr.cpp (98%) rename {cfgagent => cfgmgr}/vlanmgr.h (94%) rename {cfgagent => cfgmgr}/vlanmgrd.cpp (75%) diff --git a/.gitignore b/.gitignore index 0bfa4d8bc15..2ac0196812a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,7 @@ deps/ teamsyncd/teamsyncd fpmsyncd/fpmsyncd intfsyncd/intfsyncd -cfgagent/vlanmgrd +cfgmgr/vlanmgrd neighsyncd/neighsyncd portsyncd/portsyncd orchagent/orchagent diff --git a/Makefile.am b/Makefile.am index 3811bdbc2be..a86163ae2b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig cfgagent +SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig cfgmgr if HAVE_LIBTEAM SUBDIRS += teamsyncd diff --git a/cfgagent/Makefile.am b/cfgmgr/Makefile.am similarity index 93% rename from cfgagent/Makefile.am rename to cfgmgr/Makefile.am index 3fd83db4551..c72672fedc2 100644 --- a/cfgagent/Makefile.am +++ b/cfgmgr/Makefile.am @@ -9,7 +9,7 @@ else DBGFLAGS = -g endif -vlanmgrd_SOURCES = vlanmgrd.cpp vlanmgr.cpp $(top_srcdir)/orchagent/orchbase.cpp shellcmd.h +vlanmgrd_SOURCES = vlanmgrd.cpp vlanmgr.cpp $(top_srcdir)/orchagent/orch.cpp shellcmd.h vlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) vlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) vlanmgrd_LDADD = -lswsscommon diff --git a/cfgagent/shellcmd.h b/cfgmgr/shellcmd.h similarity index 100% rename from cfgagent/shellcmd.h rename to cfgmgr/shellcmd.h diff --git a/cfgagent/vlanmgr.cpp b/cfgmgr/vlanmgr.cpp similarity index 98% rename from cfgagent/vlanmgr.cpp rename to cfgmgr/vlanmgr.cpp index 6a075695ad7..cdede8da0fb 100644 --- a/cfgagent/vlanmgr.cpp +++ b/cfgmgr/vlanmgr.cpp @@ -20,7 +20,7 @@ using namespace swss; extern MacAddress gMacAddress; VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector &tableNames) : - OrchBase(cfgDb, tableNames), + Orch(cfgDb, tableNames), m_cfgVlanTable(cfgDb, CFG_VLAN_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), m_cfgVlanMemberTable(cfgDb, CFG_VLAN_MEMBER_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), m_statePortTable(stateDb, STATE_PORT_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR), @@ -51,12 +51,6 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c EXEC_WITH_ERROR_THROW(cmd.str(), res); } -void VlanMgr::syncCfgDB() -{ - OrchBase::syncDB(CFG_VLAN_TABLE_NAME, m_cfgVlanTable); - OrchBase::syncDB(CFG_VLAN_MEMBER_TABLE_NAME, m_cfgVlanMemberTable); -} - bool VlanMgr::addHostVlan(int vlan_id) { stringstream cmd; diff --git a/cfgagent/vlanmgr.h b/cfgmgr/vlanmgr.h similarity index 94% rename from cfgagent/vlanmgr.h rename to cfgmgr/vlanmgr.h index 2ca8cb2a7af..eb486bb99b0 100644 --- a/cfgagent/vlanmgr.h +++ b/cfgmgr/vlanmgr.h @@ -3,7 +3,7 @@ #include "dbconnector.h" #include "producerstatetable.h" -#include "orchbase.h" +#include "orch.h" #include #include @@ -11,11 +11,11 @@ namespace swss { -class VlanMgr : public OrchBase +class VlanMgr : public Orch { public: VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector &tableNames); - void syncCfgDB(); + private: ProducerStateTable m_appVlanTableProducer, m_appVlanMemberTableProducer; Table m_cfgVlanTable, m_cfgVlanMemberTable; diff --git a/cfgagent/vlanmgrd.cpp b/cfgmgr/vlanmgrd.cpp similarity index 75% rename from cfgagent/vlanmgrd.cpp rename to cfgmgr/vlanmgrd.cpp index c34c0e07c39..b24e72da3bc 100644 --- a/cfgagent/vlanmgrd.cpp +++ b/cfgmgr/vlanmgrd.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include #include "dbconnector.h" #include "select.h" #include "exec.h" @@ -18,6 +21,22 @@ using namespace swss; MacAddress gMacAddress; +/* + * Following global variables are defined here for the purpose of + * using existing Orch class which is to be refactored soon to + * eliminate the direct exposure of the global variables. + * + * Once Orch class refactoring is done, these global variables + * should be removed from here. + */ +int gBatchSize = 0; +bool gSwssRecord = false; +bool gLogRotate = false; +ofstream gRecordOfs; +string gRecordFile; +/* Global database mutex */ +mutex gDbMutex; + int main(int argc, char **argv) { Logger::linkToDbNative("vlanmgrd"); @@ -44,10 +63,10 @@ int main(int argc, char **argv) VlanMgr vlanmgr(&cfgDb, &appDb, &stateDb, cfg_vlan_tables); - std::vector cfgOrchList = {&vlanmgr}; + std::vector cfgOrchList = {&vlanmgr}; swss::Select s; - for (OrchBase *o : cfgOrchList) + for (Orch *o : cfgOrchList) { s.addSelectables(o->getSelectables()); } @@ -66,11 +85,11 @@ int main(int argc, char **argv) } if (ret == Select::TIMEOUT) { - ((OrchBase *)&vlanmgr)->doTask(); + ((Orch *)&vlanmgr)->doTask(); continue; } - for (OrchBase *o : cfgOrchList) + for (Orch *o : cfgOrchList) { TableConsumable *c = (TableConsumable *)sel; if (o->hasSelectable(c)) diff --git a/configure.ac b/configure.ac index ae5b49a8b20..8f14f83c789 100644 --- a/configure.ac +++ b/configure.ac @@ -87,7 +87,7 @@ AC_CONFIG_FILES([ teamsyncd/Makefile swssconfig/Makefile tests/Makefile - cfgagent/Makefile + cfgmgr/Makefile ]) AC_OUTPUT diff --git a/orchagent/orch.cpp b/orchagent/orch.cpp index 1a69b6e12fa..6f875f8fa50 100644 --- a/orchagent/orch.cpp +++ b/orchagent/orch.cpp @@ -2,7 +2,7 @@ #include #include #include - +#include "timestamp.h" #include "orch.h" #include "subscriberstatetable.h" @@ -22,14 +22,13 @@ extern bool gSwssRecord; extern ofstream gRecordOfs; extern bool gLogRotate; extern string gRecordFile; -extern string getTimestamp(); -Orch::Orch(DBConnector *db, string tableName) +Orch::Orch(DBConnector *db, const string tableName) { addConsumer(db, tableName); } -Orch::Orch(DBConnector *db, vector &tableNames) +Orch::Orch(DBConnector *db, const vector &tableNames) { for(auto it : tableNames) { @@ -281,6 +280,18 @@ void Orch::recordTuple(Consumer &consumer, KeyOpFieldsValuesTuple &tuple) } } +string Orch::dumpTuple(Consumer &consumer, KeyOpFieldsValuesTuple &tuple) +{ + string s = consumer.m_consumer->getTableName() + ":" + kfvKey(tuple) + + "|" + kfvOp(tuple); + for (auto i = kfvFieldsValues(tuple).begin(); i != kfvFieldsValues(tuple).end(); i++) + { + s += "|" + fvField(*i) + ":" + fvValue(*i); + } + + return s; +} + ref_resolve_status Orch::resolveFieldRefArray( type_map &type_maps, const string &field_name, diff --git a/orchagent/orch.h b/orchagent/orch.h index 473f3a4b79e..3dc22c21c63 100644 --- a/orchagent/orch.h +++ b/orchagent/orch.h @@ -27,6 +27,9 @@ const char range_specifier = '-'; #define MLNX_PLATFORM_SUBSTRING "mellanox" #define BRCM_PLATFORM_SUBSTRING "broadcom" +#define CONFIGDB_KEY_SEPARATOR "|" +#define DEFAULT_KEY_SEPARATOR ":" + typedef enum { task_success, @@ -67,8 +70,8 @@ typedef pair> TablesConnector; class Orch { public: - Orch(DBConnector *db, string tableName); - Orch(DBConnector *db, vector &tableNames); + Orch(DBConnector *db, const string tableName); + Orch(DBConnector *db, const vector &tableNames); Orch(const vector& tables); virtual ~Orch(); @@ -86,6 +89,7 @@ class Orch virtual void doTask(Consumer &consumer) = 0; void logfileReopen(); void recordTuple(Consumer &consumer, KeyOpFieldsValuesTuple &tuple); + string dumpTuple(Consumer &consumer, KeyOpFieldsValuesTuple &tuple); ref_resolve_status resolveFieldRefValue(type_map&, const string&, KeyOpFieldsValuesTuple&, sai_object_id_t&); bool parseIndexRange(const string &input, sai_uint32_t &range_low, sai_uint32_t &range_high); bool parseReference(type_map &type_maps, string &ref, string &table_name, string &object_name); diff --git a/orchagent/saihelper.cpp b/orchagent/saihelper.cpp index 15cb600a6f2..d374d131212 100644 --- a/orchagent/saihelper.cpp +++ b/orchagent/saihelper.cpp @@ -5,11 +5,9 @@ extern "C" { #include #include -#include - #include #include - +#include "timestamp.h" #include "saihelper.h" using namespace std; @@ -152,18 +150,6 @@ void initSaiApi() sai_log_set(SAI_API_ACL, SAI_LOG_LEVEL_NOTICE); } -string getTimestamp() -{ - char buffer[64]; - struct timeval tv; - gettimeofday(&tv, NULL); - - size_t size = strftime(buffer, 32 ,"%Y-%m-%d.%T.", localtime(&tv.tv_sec)); - snprintf(&buffer[size], 32, "%06ld", tv.tv_usec); - - return string(buffer); -} - void initSaiRedis(const string &record_location) { /** diff --git a/portsyncd/linksync.cpp b/portsyncd/linksync.cpp index 6f4c7a9f03b..ff3bb8d0838 100644 --- a/portsyncd/linksync.cpp +++ b/portsyncd/linksync.cpp @@ -23,11 +23,9 @@ using namespace swss; #define TEAM_DRV_NAME "team" const string INTFS_PREFIX = "Ethernet"; -const string VLAN_PREFIX = "Vlan"; const string LAG_PREFIX = "PortChannel"; extern set g_portSet; -extern map> g_vlanMap; extern bool g_init; LinkSync::LinkSync(DBConnector *appl_db, DBConnector *state_db) : diff --git a/portsyncd/portsyncd.cpp b/portsyncd/portsyncd.cpp index 734bf31d73f..c45cdb7cd7e 100644 --- a/portsyncd/portsyncd.cpp +++ b/portsyncd/portsyncd.cpp @@ -29,7 +29,6 @@ using namespace swss; * command to be run only once. */ set g_portSet; -map> g_vlanMap; bool g_init = false; void usage() From 827e97ab640612f12a2fb7f84da77a7f8d09cb7c Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Fri, 3 Nov 2017 11:29:21 +0800 Subject: [PATCH 7/7] Support getting switch mac from configDB Signed-off-by: Jipan Yang --- cfgmgr/vlanmgr.cpp | 2 +- cfgmgr/vlanmgrd.cpp | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cfgmgr/vlanmgr.cpp b/cfgmgr/vlanmgr.cpp index cdede8da0fb..ff968a2e350 100644 --- a/cfgmgr/vlanmgr.cpp +++ b/cfgmgr/vlanmgr.cpp @@ -230,7 +230,7 @@ void VlanMgr::doVlanTask(Consumer &consumer) /* * TODO: support host VLAN mtu setting. * Host VLAN mtu should be set only after member configured - * and VLAN state is not UNKOWN. + * and VLAN state is not UNKNOWN. */ SWSS_LOG_DEBUG("%s mtu %u: Host VLAN mtu setting to be supported.", key.c_str(), mtu); fvVector.push_back(i); diff --git a/cfgmgr/vlanmgrd.cpp b/cfgmgr/vlanmgrd.cpp index b24e72da3bc..ced51a1585f 100644 --- a/cfgmgr/vlanmgrd.cpp +++ b/cfgmgr/vlanmgrd.cpp @@ -44,14 +44,19 @@ int main(int argc, char **argv) SWSS_LOG_NOTICE("--- Starting vlanmgrd ---"); - string mac_str; - stringstream cmd; - cmd << IP_CMD << " link show eth0 | " << GREP_CMD << " ether | " << AWK_CMD << " '{print $2}'"; - EXEC_WITH_ERROR_THROW(cmd.str(), mac_str); - gMacAddress = mac_str; - try { + /* + * swss service starts after interfaces-config.service which will have + * switch_mac set. + * Dynamic switch_mac update is not supported for now. + */ + string switch_mac_str; + stringstream cmd; + cmd << REDIS_CLI_CMD << " -n " << CONFIG_DB << " hget " << " \"SWITCH|SWITCH_ATTR\" " << " switch_mac"; + EXEC_WITH_ERROR_THROW(cmd.str(), switch_mac_str); + gMacAddress = MacAddress(switch_mac_str); + vector cfg_vlan_tables = { CFG_VLAN_TABLE_NAME, CFG_VLAN_MEMBER_TABLE_NAME,