From d58a143c67099c4d73522b01b7bc7f220797e518 Mon Sep 17 00:00:00 2001 From: philo Date: Mon, 8 Apr 2024 15:32:44 +0800 Subject: [PATCH 01/10] add vrrpmgrd to support FRR-VRRP configuration Signed-off-by: philo --- .gitignore | 1 + cfgmgr/Makefile.am | 9 +- cfgmgr/vrrpmgr.cpp | 506 ++++++++++++++++++++++++++++++++++++++++++++ cfgmgr/vrrpmgr.h | 70 ++++++ cfgmgr/vrrpmgrd.cpp | 73 +++++++ lib/vrrpintf.cpp | 181 ++++++++++++++++ lib/vrrpintf.h | 45 ++++ tests/test_vrrp.py | 200 +++++++++++++++++ 8 files changed, 1084 insertions(+), 1 deletion(-) create mode 100644 cfgmgr/vrrpmgr.cpp create mode 100644 cfgmgr/vrrpmgr.h create mode 100644 cfgmgr/vrrpmgrd.cpp create mode 100644 lib/vrrpintf.cpp create mode 100644 lib/vrrpintf.h create mode 100644 tests/test_vrrp.py diff --git a/.gitignore b/.gitignore index 001db00e4b..a4013ae35d 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ cfgmgr/sflowmgrd cfgmgr/macsecmgrd cfgmgr/coppmgrd cfgmgr/tunnelmgrd +cfgmgr/vrrpmgrd fpmsyncd/fpmsyncd gearsyncd/gearsyncd mclagsyncd/mclagsyncd diff --git a/cfgmgr/Makefile.am b/cfgmgr/Makefile.am index a8cbddb4e7..8e51dffb0a 100644 --- a/cfgmgr/Makefile.am +++ b/cfgmgr/Makefile.am @@ -5,7 +5,7 @@ LIBNL_LIBS = -lnl-genl-3 -lnl-route-3 -lnl-3 SAIMETA_LIBS = -lsaimeta -lsaimetadata -lzmq COMMON_LIBS = -lswsscommon -bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd macsecmgrd fabricmgrd +bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd macsecmgrd fabricmgrd vrrpmgrd cfgmgrdir = $(datadir)/swss @@ -101,6 +101,11 @@ macsecmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CF macsecmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) macsecmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) +vrrpmgrd_SOURCES = vrrpmgrd.cpp vrrpmgr.cpp $(COMMON_ORCH_SOURCE) shellcmd.h $(top_srcdir)/lib/vrrpintf.cpp +vrrpmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) +vrrpmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) +vrrpmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) + if GCOV_ENABLED vlanmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp teammgrd_SOURCES += ../gcovpreload/gcovpreload.cpp @@ -116,6 +121,7 @@ natmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp coppmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp tunnelmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp macsecmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp +vrrpmgrd_LDADD += ../gcovpreload/gcovpreload.cpp endif if ASAN_ENABLED @@ -133,5 +139,6 @@ coppmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp tunnelmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp macsecmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp fabricmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp +vrrpmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp endif diff --git a/cfgmgr/vrrpmgr.cpp b/cfgmgr/vrrpmgr.cpp new file mode 100644 index 0000000000..a177cce965 --- /dev/null +++ b/cfgmgr/vrrpmgr.cpp @@ -0,0 +1,506 @@ +#include "logger.h" +#include "dbconnector.h" +#include "producerstatetable.h" +#include "tokenize.h" +#include "ipprefix.h" +#include "vrrpmgr.h" +#include "exec.h" +#include "shellcmd.h" +#include +#include + +using namespace std; +using namespace swss; + +#define VLAN_PREFIX "Vlan" +#define LAG_PREFIX "PortChannel" +#define SUBINTF_LAG_PREFIX "Po" +#define SUBINTF_LAG_PREFIX "Po" +#define LOOPBACK_PREFIX "Loopback" + +#define VRRP_V4_MAC_PREFIX "00:00:5e:00:01:" +#define VRRP_V6_MAC_PREFIX "00:00:5e:00:02:" + +VrrpMgr::VrrpMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames) : + Orch(cfgDb, tableNames), + m_appPortTable(appDb, APP_PORT_TABLE_NAME), + m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME), + m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME), + m_statePortTable(stateDb, STATE_PORT_TABLE_NAME) +{ +} + +bool VrrpMgr::setIntfArpAccept(const std::string &intf_alias, const bool arp_accept) +{ + stringstream cmd; + string res; + + if (arp_accept) + { + cmd << ECHO_CMD << " 2 > /proc/sys/net/ipv4/conf/" << shellquote(intf_alias) << "/arp_announce && "; + cmd << ECHO_CMD << " 2 > /proc/sys/net/ipv4/conf/" << shellquote(intf_alias) << "/rp_filter && "; + cmd << ECHO_CMD << " 1 > /proc/sys/net/ipv4/conf/" << shellquote(intf_alias) << "/accept_local"; + } + else + { + cmd << ECHO_CMD << " 0 > /proc/sys/net/ipv4/conf/" << shellquote(intf_alias) << "/arp_announce && "; + cmd << ECHO_CMD << " 0 > /proc/sys/net/ipv4/conf/" << shellquote(intf_alias) << "/rp_filter && "; + cmd << ECHO_CMD << " 0 > /proc/sys/net/ipv4/conf/" << shellquote(intf_alias) << "/accept_local"; + } + + try + { + EXEC_WITH_ERROR_THROW(cmd.str(), res); + } + catch (const std::exception &e) + { + SWSS_LOG_ERROR("Failed to set intf arp %s on interface[%s], retry. Runtime error: %s", arp_accept ? "accept" : "default", intf_alias.c_str(), e.what()); + return false; + } + + SWSS_LOG_INFO("Set vrrp arp %s on interface[%s]", arp_accept ? "accept" : "default", intf_alias.c_str()); + return true; +} + +bool VrrpMgr::setVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4, + const std::set &vip_list, const std::string &admin_status) +{ + VrrpIntfConf vrrp_conf; + if (m_vrrpList.find(vrid) == m_vrrpList.end()) + { + vrrp_conf.alias = intf_alias; + } + else + { + vrrp_conf = m_vrrpList[vrid]; + } + auto &vrrp = is_ipv4 ? vrrp_conf.vrrp4 : vrrp_conf.vrrp6; + auto &vrrp_entry = is_ipv4 ? vrrp_conf.vrrp4_entry : vrrp_conf.vrrp6_entry; + + // generate vmac + set vaild_vips; + auto is_ipv4_check = [is_ipv4](const IpPrefix &has_vip){ return has_vip.isV4() == is_ipv4; }; + copy_if(vip_list.begin(), vip_list.end(), std::inserter(vaild_vips, vaild_vips.begin()), is_ipv4_check); + if (!vaild_vips.empty()) + { + // add vrrp intf + if (!vrrp.isValid()) + { + MacAddress vmac; + if (!parseVrrpMac(vrid, is_ipv4, vmac)) + { + return false; + } + vrrp = VrrpIntf(intf_alias, vrid, is_ipv4, vmac.to_string()); + if (!vrrp.isValid()) + { + SWSS_LOG_WARN("parse new vrrp intf fail, intf: %s, vrid: %s, is ipv4:%d", intf_alias.c_str(), vrid.c_str(), is_ipv4); + return false; + } + if (!addVirtualInterface(intf_alias, vrrp.getVrrpName(), vmac, is_ipv4)) + { + vrrp = VrrpIntf(); + return false; + } + } + } + else + { + // del vrrp intf + if (vrrp.isValid()) + { + if (!delVirtualInterface(intf_alias, vrrp.getVrrpName())) + { + return false; + } + vrrp = VrrpIntf(); + vrrp_entry = VrrpIntfEntry(); + } + } + + if (!vrrp.isValid()) + { + SWSS_LOG_WARN("set vrrp fail"); + return false; + } + + // set admin status + vrrp_entry.admin_status = admin_status; + if (vrrp.isValid()) + { + setVirtualInterfaceAdminStatus(vrrp.getVrrpName(), admin_status); + } + + // add/del vips + set original_vips = vrrp_entry.vips; + set diff_vips; + set_symmetric_difference(original_vips.begin(), original_vips.end(), vaild_vips.begin(), vaild_vips.end(), std::inserter(diff_vips, diff_vips.begin())); + SWSS_LOG_INFO("original_ip size:%d, apply_vips size:%d, diff size:%d", (int)original_vips.size(), (int)vaild_vips.size(), (int)diff_vips.size()); + vrrp_entry.vips = vaild_vips; + + for (const IpPrefix &diff_ip : diff_vips) + { + if (vaild_vips.find(diff_ip) != vaild_vips.end()) + { + // add vip + addVirtualInterfaceIp(vrid, diff_ip); + } + + if (original_vips.find(diff_ip) != original_vips.end()) + { + // del vip + delVirtualInterfaceIp(vrid, diff_ip); + } + } + + m_vrrpList[vrid] = vrrp_conf; + // set parent intf + if (!isVrrpOnIntf(intf_alias)) + { + SWSS_LOG_INFO("No vrrp on interface[%s], set arp accept", intf_alias.c_str()); + setIntfArpAccept(intf_alias); + } + + SWSS_LOG_NOTICE("Set vrrp on intf[%s] vrid[%s] is_ipv4 %d", intf_alias.c_str(), vrid.c_str(), is_ipv4); + return true; +} + +bool VrrpMgr::removeVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4) +{ + auto it = m_vrrpList.find(vrid); + if (it == m_vrrpList.end()) + { + SWSS_LOG_INFO("Not found vrid: %s", vrid.c_str()); + return true; + } + + auto &vrrp = is_ipv4 ? it->second.vrrp4 : it->second.vrrp6; + auto &vrrp_entry = is_ipv4 ? it->second.vrrp4_entry : it->second.vrrp6_entry; + if (vrrp.isValid()) + { + delVirtualInterface(intf_alias, vrrp.getVrrpName()); + vrrp = VrrpIntf(); + vrrp_entry = VrrpIntfEntry(); + } + + if (!it->second.vrrp4.isValid() && !it->second.vrrp6.isValid()) + { + m_vrrpList.erase(it); + if (!isVrrpOnIntf(intf_alias)) + { + SWSS_LOG_INFO("No vrrp on intf[%s], arp accept back to default", intf_alias.c_str()); + setIntfArpAccept(intf_alias, false); + } + } + + SWSS_LOG_NOTICE("Remove vrrp on intf[%s] vrid[%s] is_ipv4 %d", intf_alias.c_str(), vrid.c_str(), is_ipv4); + return true; +} + +bool VrrpMgr::addVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name, const MacAddress &vrrp_mac, bool is_ipv4) +{ + stringstream cmd; + string res; + + // link add vrrp type macvlan + cmd << IP_CMD << " link add " << shellquote(vrrp_name) << " link " << shellquote(intf_alias) << " type macvlan mode bridge && "; + cmd << IP_CMD << " link set dev " << shellquote(vrrp_name) << " addrgenmode " << string(is_ipv4 ? "none" : "random") << " && "; + cmd << IP_CMD << " link set dev " << shellquote(vrrp_name) << " address " << vrrp_mac.to_string() << " && "; + // create default is down, wait for admin status value(default up) + cmd << IP_CMD << " link set dev " << shellquote(vrrp_name) << " down"; + SWSS_LOG_DEBUG("Add vrrp virtual intf cmd: %s", cmd.str().c_str()); + + try + { + EXEC_WITH_ERROR_THROW(cmd.str(), res); + } + catch (const std::exception &e) + { + SWSS_LOG_ERROR("Failed to add vitrual intf[%s] on interface[%s], retry. Runtime error: %s", vrrp_name.c_str(), intf_alias.c_str(), e.what()); + return false; + } + + SWSS_LOG_INFO("Add vitrual intf[%s] on interface[%s]", vrrp_name.c_str(), intf_alias.c_str()); + return true; +} + +bool VrrpMgr::delVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name) +{ + stringstream cmd; + string res; + + // link del vrrp + cmd << IP_CMD << " link del " << shellquote(vrrp_name); + + try + { + EXEC_WITH_ERROR_THROW(cmd.str(), res); + } + catch (const std::exception &e) + { + SWSS_LOG_ERROR("Failed to del vitrual intf[%s] on interface[%s], retry. Runtime error: %s", vrrp_name.c_str(), intf_alias.c_str(), e.what()); + return false; + } + + SWSS_LOG_INFO("Del vitrual intf[%s] on interface[%s]", vrrp_name.c_str(), intf_alias.c_str()); + return true; +} + +bool swss::VrrpMgr::addVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) +{ + stringstream cmd; + string res; + + bool ip_ipv4 = ip_addr.isV4(); + string vrrp_name = join(vrrp_name_delimiter, (ip_ipv4 ? VRRP_V4_PREFIX : VRRP_V6_PREFIX), vrid); + string ipPrefixStr = ip_addr.to_string(); + // link add ip dev vrrp + cmd << IP_CMD << (ip_ipv4 ? "" : " -6 ") << " address add " << shellquote(ipPrefixStr) << " dev " << shellquote(vrrp_name); + + try + { + EXEC_WITH_ERROR_THROW(cmd.str(), res); + } + catch (const std::exception &e) + { + SWSS_LOG_ERROR("Failed to add ip[%s] on vitrual intf[%s], retry. Runtime error: %s", vrrp_name.c_str(), vrrp_name.c_str(), e.what()); + return false; + } + + SWSS_LOG_INFO("Add ip[%s] on vitrual intf[%s]", ipPrefixStr.c_str(), vrrp_name.c_str()); + return true; +} + +bool swss::VrrpMgr::delVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) +{ + stringstream cmd; + string res; + + bool ip_ipv4 = ip_addr.isV4(); + string vrrp_name = join(vrrp_name_delimiter, (ip_ipv4 ? VRRP_V4_PREFIX : VRRP_V6_PREFIX), vrid); + string ipPrefixStr = ip_addr.to_string(); + // link del ip dev vrrp + cmd << IP_CMD << (ip_ipv4 ? "" : " -6 ") << " address del " << shellquote(ipPrefixStr) << " dev " << shellquote(vrrp_name); + + try + { + EXEC_WITH_ERROR_THROW(cmd.str(), res); + } + catch (const std::exception &e) + { + SWSS_LOG_ERROR("Failed to del ip[%s] on vitrual intf[%s], retry. Runtime error: %s", vrrp_name.c_str(), vrrp_name.c_str(), e.what()); + return false; + } + + SWSS_LOG_INFO("Del ip[%s] on vitrual intf[%s]", ipPrefixStr.c_str(), vrrp_name.c_str()); + return true; +} + +bool VrrpMgr::setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const std::string &admin_status) +{ + stringstream cmd; + string res; + + cmd << IP_CMD << " link set dev " << shellquote(vrrp_name) << " " << shellquote(admin_status); + SWSS_LOG_DEBUG("Set vrrp virtual intf admin status cmd: %s", cmd.str().c_str()); + + try + { + EXEC_WITH_ERROR_THROW(cmd.str(), res); + } + catch (const std::exception &e) + { + SWSS_LOG_ERROR("Failed to add vitrual intf[%s], retry. Runtime error: %s", vrrp_name.c_str(), e.what()); + return false; + } + + SWSS_LOG_INFO("Add vitrual intf[%s]", vrrp_name.c_str()); + return true; +} + +bool VrrpMgr::isIntfStateOk(const std::string &intf_alias) +{ + /* check router intf initialization is complete */ + vector temp; + if (!intf_alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX)) + { + if (m_stateVlanTable.get(intf_alias, temp)) + { + SWSS_LOG_DEBUG("Vlan %s is ready", intf_alias.c_str()); + return true; + } + } + else if (!intf_alias.compare(0, strlen(LAG_PREFIX), LAG_PREFIX)) + { + if (m_stateLagTable.get(intf_alias, temp)) + { + SWSS_LOG_DEBUG("Lag %s is ready", intf_alias.c_str()); + return true; + } + } + else if (!intf_alias.compare(0, strlen(SUBINTF_LAG_PREFIX), SUBINTF_LAG_PREFIX)) + { + if (m_stateLagTable.get(intf_alias, temp)) + { + SWSS_LOG_DEBUG("Lag %s is ready", intf_alias.c_str()); + return true; + } + } + else if (m_statePortTable.get(intf_alias, temp)) + { + auto state_opt = swss::fvsGetValue(temp, "state", true); + if (!state_opt) + { + return false; + } + SWSS_LOG_DEBUG("Port %s is ready", intf_alias.c_str()); + return true; + } + + return false; +} + +bool VrrpMgr::isVrrpOnIntf(const std::string &intf_alias) +{ + return find_if(m_vrrpList.begin(), m_vrrpList.end(), [intf_alias](const auto &pair){ return pair.second.alias == intf_alias; }) != m_vrrpList.end(); +} + +bool VrrpMgr::parseVrrpMac(const std::string &vrid, const bool is_ipv4, MacAddress &vrrp_mac) +{ + stringstream vmac; + string hex_vrid; + + if (!all_of(vrid.begin(), vrid.end(), ::isdigit)) + { + SWSS_LOG_WARN("vrid : %s, must be a number", vrid.c_str()); + return false; + } + + int ivrid = stoi(vrid); + if (ivrid >= 256 || ivrid <= 0) + { + SWSS_LOG_WARN("vrid : %s, must less than 256, greater than 0", vrid.c_str()); + return false; + } + + // just need one bit to mac + hex_vrid = binary_to_hex(&ivrid, sizeof(char)); + SWSS_LOG_INFO("vrid: %s, hex_vrid: %s", vrid.c_str(), hex_vrid.c_str()); + + if (is_ipv4) + { + vmac << VRRP_V4_MAC_PREFIX << std::setw(2) << std::setfill('0') << hex_vrid; + } + else + { + vmac << VRRP_V6_MAC_PREFIX << std::setw(2) << std::setfill('0') << hex_vrid; + } + + vrrp_mac = MacAddress(vmac.str()); + return true; +} + +void VrrpMgr::doTask(Consumer &consumer) +{ + SWSS_LOG_ENTER(); + + auto table = consumer.getTableName(); + + auto it = consumer.m_toSync.begin(); + while (it != consumer.m_toSync.end()) + { + KeyOpFieldsValuesTuple t = it->second; + vector keys = tokenize(kfvKey(t), config_db_key_delimiter); + const string &op = kfvOp(t); + const vector &data = kfvFieldsValues(t); + + if (keys.size() != 2) + { + SWSS_LOG_WARN("vrrp table need intf and vrid, ignore it: %s", kfvKey(t).c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + string intf_alias(keys[0]); + string vrrp_id(keys[1]); + + if (!isIntfStateOk(intf_alias)) + { + SWSS_LOG_INFO("Port %s is not ready, pending...", intf_alias.c_str()); + it++; + continue; + } + + if (m_vrrpList.find(vrrp_id) != m_vrrpList.end() && m_vrrpList[vrrp_id].alias != intf_alias) + { + SWSS_LOG_WARN("vrid[%s] has been created on interface[%s], ignore it: %s", + vrrp_id.c_str(), m_vrrpList[vrrp_id].alias.c_str(), kfvKey(t).c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + string vrid, vip_str, admin_status; + for (auto i : data) + { + if (fvField(i) == "vrid") + { + vrid = fvValue(i); + } + else if (fvField(i) == "vip") + { + vip_str = fvValue(i); + } + else if (fvField(i) == "admin_status") + { + admin_status = fvValue(i); + } + } + bool is_ipv4 = table == CFG_VRRP_TABLE_NAME ? true : false; + if (op == SET_COMMAND) + { + set vips; + if (!vip_str.empty()) + { + vector vip_list = tokenize(vip_str, list_item_delimiter); + try + { + transform(vip_list.begin(), vip_list.end(), inserter(vips, vips.begin()), [](const string &vip){ return IpPrefix(vip); }); + } + catch (const std::exception &e) + { + SWSS_LOG_ERROR("vip has invaild ip addr on vrrp table %s, ignore. Runtime error: %s", kfvKey(t).c_str(), e.what()); + it = consumer.m_toSync.erase(it); + continue; + } + } + else + { + SWSS_LOG_NOTICE("Creat macvlan link on intf[%s] vrid[%s] without ip address", intf_alias.c_str(), vrrp_id.c_str()); + } + + if (admin_status.empty()) + { + admin_status = "up"; + } + else if(admin_status != "up" && admin_status != "down") + { + admin_status = "down"; + SWSS_LOG_WARN("Invaild admin status %s on intf[%s] vrid[%s].", admin_status.c_str(), intf_alias.c_str(), vrrp_id.c_str()); + } + + if (!setVrrpIntf(intf_alias, vrrp_id, is_ipv4, vips, admin_status)) + { + SWSS_LOG_WARN("Set vrrp on intf[%s] vrid[%s] failed.", intf_alias.c_str(), vrrp_id.c_str()); + } + } + else if (op == DEL_COMMAND) + { + if (!removeVrrpIntf(intf_alias, vrrp_id, is_ipv4)) + { + SWSS_LOG_WARN("Del vrrp on intf[%s] vrid[%s] failed.", intf_alias.c_str(), vrrp_id.c_str()); + } + } + + it = consumer.m_toSync.erase(it); + } +} diff --git a/cfgmgr/vrrpmgr.h b/cfgmgr/vrrpmgr.h new file mode 100644 index 0000000000..d6856d6fbe --- /dev/null +++ b/cfgmgr/vrrpmgr.h @@ -0,0 +1,70 @@ +#pragma once + +#include "orch.h" +#include "producerstatetable.h" +#include "vrrpintf.h" + +#include +#include + +namespace swss { + +struct VrrpIntfEntry +{ + std::set vips; + std::string admin_status{}; +}; + +struct VrrpIntfConf +{ + std::string alias{}; + + VrrpIntf vrrp4; + VrrpIntfEntry vrrp4_entry; + + VrrpIntf vrrp6; + VrrpIntfEntry vrrp6_entry; + + VrrpIntfConf() + { + vrrp4 = VrrpIntf(); + vrrp4_entry = VrrpIntfEntry(); + vrrp6 = VrrpIntf(); + vrrp6_entry = VrrpIntfEntry(); + } +}; + +class VrrpMgr : public Orch +{ +public: + VrrpMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames); + using Orch::doTask; + +private: + Table m_appPortTable; + Table m_statePortTable, m_stateVlanTable, m_stateLagTable; + + /* */ + std::map m_vrrpList; + + void doTask(Consumer &consumer); + + bool setIntfArpAccept(const std::string &intf_alias, const bool arp_accept = true); + + bool setVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4, + const std::set &vip_list, const std::string &admin_status); + bool removeVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4); + + bool addVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name, const MacAddress &vrrp_mac, bool is_ipv4); + bool delVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name); + bool addVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr); + bool delVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr); + bool setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const std::string &admin_status); + + bool isIntfStateOk(const std::string &intf_alias); + bool isVrrpOnIntf(const std::string &intf_alias); + + bool parseVrrpMac(const std::string &vrid, const bool is_ipv4, MacAddress& vrrp_mac); +}; + +} diff --git a/cfgmgr/vrrpmgrd.cpp b/cfgmgr/vrrpmgrd.cpp new file mode 100644 index 0000000000..19d98dc554 --- /dev/null +++ b/cfgmgr/vrrpmgrd.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +#include "exec.h" +#include "vrrpmgr.h" +#include "schema.h" +#include "select.h" + +using namespace std; +using namespace swss; + +/* select() function timeout retry time, in millisecond */ +#define SELECT_TIMEOUT 1000 + +int main(int argc, char **argv) +{ + Logger::linkToDbNative("vrrpmgrd"); + SWSS_LOG_ENTER(); + + SWSS_LOG_NOTICE("--- Starting vrrpmgrd ---"); + + try + { + vector cfg_vrrp_tables = { + CFG_VRRP_TABLE_NAME, + CFG_VRRP6_TABLE_NAME, + }; + + DBConnector cfgDb("CONFIG_DB", 0); + DBConnector appDb("APPL_DB", 0); + DBConnector stateDb("STATE_DB", 0); + + VrrpMgr vrrpmgr(&cfgDb, &appDb, &stateDb, cfg_vrrp_tables); + + // TODO: add tables in stateDB which interface depends on to monitor list + vector cfgOrchList = {&vrrpmgr}; + + swss::Select s; + for (Orch *o : cfgOrchList) + { + s.addSelectables(o->getSelectables()); + } + + while (true) + { + Selectable *sel; + int ret; + + ret = s.select(&sel, SELECT_TIMEOUT); + if (ret == Select::ERROR) + { + SWSS_LOG_NOTICE("Error: %s!", strerror(errno)); + continue; + } + if (ret == Select::TIMEOUT) + { + vrrpmgr.doTask(); + continue; + } + + auto *c = (Executor *)sel; + c->execute(); + } + } + catch (const exception &e) + { + SWSS_LOG_ERROR("Runtime error: %s", e.what()); + } + return -1; +} diff --git a/lib/vrrpintf.cpp b/lib/vrrpintf.cpp new file mode 100644 index 0000000000..2d14be33c7 --- /dev/null +++ b/lib/vrrpintf.cpp @@ -0,0 +1,181 @@ +#include "schema.h" +#include "tokenize.h" +#include "converter.h" +#include "stringutility.h" +#include "logger.h" + +#include "vrrpintf.h" + +using namespace swss; + +#define VRRP_V4_MAC_PREFIX "00:00:5e:00:01:" +#define VRRP_V6_MAC_PREFIX "00:00:5e:00:02:" + +VrrpIntf::VrrpIntf() +{ + parent_name = ""; + vrrp_name = ""; + vrrp_vmac = ""; + vrid = 0; + is_ipv4 = false; +} + +VrrpIntf::VrrpIntf(const std::string &parentName, const int vrid, const bool isIpv4) : + parent_name(parentName), vrid(vrid), is_ipv4(isIpv4) +{ + vrrp_vmac = ""; + vrrp_name = join(vrrp_name_delimiter, (is_ipv4 ? VRRP_V4_PREFIX : VRRP_V6_PREFIX), std::to_string(vrid)); +} + +VrrpIntf::VrrpIntf(const std::string &parentName, const std::string &vridStr, const bool isIpv4) : + parent_name(parentName), is_ipv4(isIpv4) +{ + vrid = 0; + vrrp_vmac = ""; + + if (std::all_of(vridStr.begin(), vridStr.end(), ::isdigit)) + { + vrid = to_int(vridStr); + vrrp_name = join(vrrp_name_delimiter, (is_ipv4 ? VRRP_V4_PREFIX : VRRP_V6_PREFIX), vridStr); + } +} + +VrrpIntf::VrrpIntf(const std::string &parentName, const std::string &vridStr, const bool isIpv4, const std::string &vmacStr) : + parent_name(parentName), is_ipv4(isIpv4), vrrp_vmac(vmacStr) +{ + vrid = 0; + + if (std::all_of(vridStr.begin(), vridStr.end(), ::isdigit)) + { + vrid = to_int(vridStr); + vrrp_name = join(vrrp_name_delimiter, (is_ipv4 ? VRRP_V4_PREFIX : VRRP_V6_PREFIX), vridStr); + } +} + +VrrpIntf::VrrpIntf(const std::string &parentName, const std::string &vrrpName) : + parent_name(parentName), vrrp_name(vrrpName) +{ + vrid = 0; + vrrp_vmac = ""; + + auto name_list = tokenize(vrrpName, vrrp_name_delimiter); + if (name_list.size() == 2) + { + std::string vrrp_name_prefix = name_list[0]; + std::string vridStr = name_list[1]; + if (std::all_of(vridStr.begin(), vridStr.end(), ::isdigit)) + { + vrid = to_int(vridStr); + } + if (vrrp_name_prefix == VRRP_V4_PREFIX) + { + is_ipv4 = true; + } + else if (vrrp_name_prefix == VRRP_V6_PREFIX) + { + is_ipv4 = false; + } + else + { + vrid = 0; + is_ipv4 = false; + } + } +} + +VrrpIntf::VrrpIntf(const std::string &parentName, const std::string &vridStr, const std::string &ipType) : + parent_name(parentName) +{ + SWSS_LOG_INFO("parentName %s", parentName.c_str()); + vrid = 0; + vrrp_vmac = ""; + + if (std::all_of(vridStr.begin(), vridStr.end(), ::isdigit)) + { + vrid = to_int(vridStr); + } + SWSS_LOG_INFO("vridStr %s, vrid %d", vridStr.c_str(), vrid); + if (ipType == IPV4_NAME) + { + is_ipv4 = true; + SWSS_LOG_INFO("ipv4 %s", ipType.c_str()); + } + else if (ipType == IPV6_NAME) + { + is_ipv4 = false; + SWSS_LOG_INFO("ipv6 %s", ipType.c_str()); + } + else + { + vrid = 0; + is_ipv4 = false; + SWSS_LOG_INFO("ip fail %s", ipType.c_str()); + } + vrrp_name = join(vrrp_name_delimiter, (is_ipv4 ? VRRP_V4_PREFIX : VRRP_V6_PREFIX), vridStr); + SWSS_LOG_INFO("vrrp_name %s", vrrp_name.c_str()); +} + +bool VrrpIntf::isValid() const +{ + if (vrid > 255 || vrid < 1) + { + return false; + } + + if (parent_name.empty() || vrrp_name.empty()) + { + return false; + } + + return true; +} + +std::string VrrpIntf::getParentName() const +{ + return isValid() ? parent_name : ""; +} + +std::string VrrpIntf::getVrrpName() const +{ + return isValid() ? vrrp_name : ""; +} + +MacAddress swss::VrrpIntf::getMacAddress() +{ + if (!isValid()) + { + return MacAddress(); + } + + if (!vrrp_vmac.empty()) + { + return MacAddress(vrrp_vmac); + } + + std::stringstream vmac; + std::string hex_vrid; + + // just need one bit to mac + hex_vrid = binary_to_hex(&vrid, sizeof(char)); + + if (is_ipv4) + { + vmac << VRRP_V4_MAC_PREFIX << std::setw(2) << std::setfill('0') << hex_vrid; + } + else + { + vmac << VRRP_V6_MAC_PREFIX << std::setw(2) << std::setfill('0') << hex_vrid; + } + vrrp_vmac = vmac.str(); + return MacAddress(vmac.str()); +} + +int VrrpIntf::getVrid() const +{ + return isValid() ? vrid : 0; +} + +bool VrrpIntf::isIpv4() const +{ + return is_ipv4; +} diff --git a/lib/vrrpintf.h b/lib/vrrpintf.h new file mode 100644 index 0000000000..bc239ea08e --- /dev/null +++ b/lib/vrrpintf.h @@ -0,0 +1,45 @@ +#ifndef SWSS_COMMON_VRRP_INTF_H +#define SWSS_COMMON_VRRP_INTF_H + + +#include + +#include "ipprefix.h" +#include "macaddress.h" + +#define VRRP_PREFIX "Vrrp" +#define VRRP_V4_PREFIX "Vrrp4" +#define VRRP_V6_PREFIX "Vrrp6" + +const char vrrp_name_delimiter = '-'; + +namespace swss { + +class VrrpIntf +{ + public: + VrrpIntf(); + VrrpIntf(const std::string &parentName, const int vrid, const bool isIpv4); + VrrpIntf(const std::string &parentName, const std::string &vridStr, const bool isIpv4); + VrrpIntf(const std::string &parentName, const std::string &vridStr, const bool isIpv4, const std::string &vmacStr); + VrrpIntf(const std::string &parentName, const std::string &vridStr, const std::string &ipType); + VrrpIntf(const std::string &parentName, const std::string &vrrpName); + + bool isValid() const; + std::string getParentName() const; + std::string getVrrpName() const; + MacAddress getMacAddress(); + int getVrid() const; + bool isIpv4() const; + + private: + std::string parent_name; + std::string vrrp_name; + std::string vrrp_vmac; + int vrid; + bool is_ipv4; +}; + +} + +#endif /* SWSS_COMMON_VRRP_INTF_H */ diff --git a/tests/test_vrrp.py b/tests/test_vrrp.py new file mode 100644 index 0000000000..8bd03bb878 --- /dev/null +++ b/tests/test_vrrp.py @@ -0,0 +1,200 @@ +import time +import json +import pytest + +from swsscommon import swsscommon + +class TestVrrp(object): + def setup_db(self, dvs): + self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + + def create_vrf(self, vrf_name): + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") + initial_entries = set(tbl.getKeys()) + + tbl = swsscommon.Table(self.cdb, "VRF") + fvs = swsscommon.FieldValuePairs([('empty', 'empty')]) + tbl.set(vrf_name, fvs) + time.sleep(1) + + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") + current_entries = set(tbl.getKeys()) + assert len(current_entries - initial_entries) == 1 + return list(current_entries - initial_entries)[0] + + def remove_vrf(self, vrf_name): + tbl = swsscommon.Table(self.cdb, "VRF") + tbl._del(vrf_name) + time.sleep(1) + + def create_l3_intf(self, interface, vrf_name): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL_INTERFACE" + elif interface.startswith("Vlan"): + tbl_name = "VLAN_INTERFACE" + elif interface.startswith("Loopback"): + tbl_name = "LOOPBACK_INTERFACE" + else: + tbl_name = "INTERFACE" + if len(vrf_name) == 0: + fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) + else: + fvs = swsscommon.FieldValuePairs([("vrf_name", vrf_name)]) + tbl = swsscommon.Table(self.cdb, tbl_name) + tbl.set(interface, fvs) + time.sleep(1) + + def remove_l3_intf(self, interface): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL_INTERFACE" + elif interface.startswith("Vlan"): + tbl_name = "VLAN_INTERFACE" + elif interface.startswith("Loopback"): + tbl_name = "LOOPBACK_INTERFACE" + else: + tbl_name = "INTERFACE" + tbl = swsscommon.Table(self.cdb, tbl_name) + tbl._del(interface) + time.sleep(1) + + def add_ip_address(self, interface, ip): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL_INTERFACE" + elif interface.startswith("Vlan"): + tbl_name = "VLAN_INTERFACE" + elif interface.startswith("Loopback"): + tbl_name = "LOOPBACK_INTERFACE" + else: + tbl_name = "INTERFACE" + tbl = swsscommon.Table(self.cdb, tbl_name) + fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) + tbl.set(interface + "|" + ip, fvs) + time.sleep(1) + + def remove_ip_address(self, interface, ip): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL_INTERFACE" + elif interface.startswith("Vlan"): + tbl_name = "VLAN_INTERFACE" + elif interface.startswith("Loopback"): + tbl_name = "LOOPBACK_INTERFACE" + else: + tbl_name = "INTERFACE" + tbl = swsscommon.Table(self.cdb, tbl_name) + tbl._del(interface + "|" + ip) + time.sleep(1) + + def addremove_vrrp_instance_vip(self, interface, vid, vip): + tbl_name = "VRRP" + tbl = swsscommon.Table(self.cdb, tbl_name) + fvs = swsscommon.FieldValuePairs([("vip", vip)]) + tbl.set(interface + "|" + vid, fvs) + time.sleep(1) + + def addremove_vrrp6_instance_vip(self, interface, vid, vip): + tbl_name = "VRRP6" + tbl = swsscommon.Table(self.cdb, tbl_name) + fvs = swsscommon.FieldValuePairs([("vip", vip)]) + tbl.set(interface + "|" + vid, fvs) + time.sleep(1) + + def remove_vrrp_instance(self, interface, vid): + tbl_name = "VRRP" + tbl = swsscommon.Table(self.cdb, tbl_name) + tbl._del(interface + "|" + vid) + time.sleep(1) + + def remove_vrrp6_instance(self, interface, vid): + tbl_name = "VRRP6" + tbl = swsscommon.Table(self.cdb, tbl_name) + tbl._del(interface + "|" + vid) + time.sleep(1) + + def test_VrrpAddRemoveIpv6Address(self, dvs, testlog): + self.setup_db(dvs) + + # create interface + self.create_l3_intf("Ethernet8", "") + + # check application database + tbl = swsscommon.Table(self.pdb, "INTF_TABLE") + (status, fvs) = tbl.get("Ethernet8") + assert status == True + for fv in fvs: + assert fv[0] != "vrf_name" + + # bring up interface + # NOTE: For IPv6, only when the interface is up will the netlink message + # get generated. + self.set_admin_status(dvs, "Ethernet8", "up") + + # assign IP to interface + self.add_ip_address("Ethernet8", "fc00::1/126") + time.sleep(2) # IPv6 netlink message needs longer time + + # add vrrp6 instance whith ipv6 address + self.addremove_vrrp6_instance_vip("Ethernet8", 8, "fc00::8/126") + + # check kernel macvlan device info + output = dvs.runcmd(['sh', '-c', "ip address show Vrrp6-8"]) + assert "fc00::8/126" not in output or "00:00:5e:00:02:08" not in output + + # remove vrrp6 instance + self.remove_vrrp6_instance("Ethernet8", 8) + + # check kernel macvlan device info + output = dvs.runcmd(['sh', '-c', "ip address show Vrrp6-8"]) + assert "fc00::8/126" in output or "00:00:5e:00:02:08" in output + + # remove IP from interface + self.remove_ip_address("Ethernet8", "fc00::1/126") + + # remove interface + self.remove_l3_intf("Ethernet8") + + def test_VrrpAddRemoveIpv4Address(self, dvs, testlog): + self.setup_db(dvs) + + # create interface + self.create_l3_intf("Ethernet8", "") + + # check application database + tbl = swsscommon.Table(self.pdb, "INTF_TABLE") + (status, fvs) = tbl.get("Ethernet8") + assert status == True + for fv in fvs: + assert fv[0] != "vrf_name" + + # bring up interface + # NOTE: For IPv4, only when the interface is up will the netlink message + # get generated. + self.set_admin_status(dvs, "Ethernet8", "up") + + # assign IP to interface + self.add_ip_address("Ethernet8", "8.8.8.8/24") + time.sleep(2) # IPv4 netlink message needs longer time + + # add vrrp instance whith ipv4 address + self.addremove_vrrp_instance_vip("Ethernet8", 8, "8.8.8.1/24") + + # check kernel macvlan device info + output = dvs.runcmd(['sh', '-c', "ip address show Vrrp4-8"]) + assert "8.8.8.1/24" not in output or "00:00:5e:00:01:08" not in output + + # remove vrrp instance + self.remove_vrrp_instance("Ethernet8", 8) + + # check kernel macvlan device info + output = dvs.runcmd(['sh', '-c', "ip address show Vrrp4-8"]) + assert "8.8.8.1/24" in output or "00:00:5e:00:01:08" in output + + # remove IP from interface + self.remove_ip_address("Ethernet8", "8.8.8.8/24") + + # remove interface + self.remove_l3_intf("Ethernet8") + + + From 007657ffd0cb86ff6476f33b09cc5b0b6217b873 Mon Sep 17 00:00:00 2001 From: philo Date: Tue, 30 Jul 2024 16:43:53 +0800 Subject: [PATCH 02/10] Change the name of vrrpmgrd to macvlanmgrd Signed-off-by: philo --- .gitignore | 2 +- cfgmgr/Makefile.am | 14 ++++++------ cfgmgr/{vrrpmgr.cpp => macvlanmgr.cpp} | 28 ++++++++++++------------ cfgmgr/{vrrpmgr.h => macvlanmgr.h} | 4 ++-- cfgmgr/{vrrpmgrd.cpp => macvlanmgrd.cpp} | 12 +++++----- 5 files changed, 30 insertions(+), 30 deletions(-) rename cfgmgr/{vrrpmgr.cpp => macvlanmgr.cpp} (92%) rename cfgmgr/{vrrpmgr.h => macvlanmgr.h} (92%) rename cfgmgr/{vrrpmgrd.cpp => macvlanmgrd.cpp} (83%) diff --git a/.gitignore b/.gitignore index a4013ae35d..e716892df4 100644 --- a/.gitignore +++ b/.gitignore @@ -59,7 +59,7 @@ cfgmgr/sflowmgrd cfgmgr/macsecmgrd cfgmgr/coppmgrd cfgmgr/tunnelmgrd -cfgmgr/vrrpmgrd +cfgmgr/macvlanmgrd fpmsyncd/fpmsyncd gearsyncd/gearsyncd mclagsyncd/mclagsyncd diff --git a/cfgmgr/Makefile.am b/cfgmgr/Makefile.am index 25c1ec89b3..653456da90 100644 --- a/cfgmgr/Makefile.am +++ b/cfgmgr/Makefile.am @@ -5,7 +5,7 @@ LIBNL_LIBS = -lnl-genl-3 -lnl-route-3 -lnl-3 SAIMETA_LIBS = -lsaimeta -lsaimetadata -lzmq COMMON_LIBS = -lswsscommon -lpthread -bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd macsecmgrd fabricmgrd vrrpmgrd +bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd macsecmgrd fabricmgrd macvlanmgrd cfgmgrdir = $(datadir)/swss @@ -101,10 +101,10 @@ macsecmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CF macsecmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) macsecmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -vrrpmgrd_SOURCES = vrrpmgrd.cpp vrrpmgr.cpp $(COMMON_ORCH_SOURCE) shellcmd.h $(top_srcdir)/lib/vrrpintf.cpp -vrrpmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) -vrrpmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) -vrrpmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) +macvlanmgrd_SOURCES = macvlanmgrd.cpp macvlanmgr.cpp $(COMMON_ORCH_SOURCE) shellcmd.h $(top_srcdir)/lib/vrrpintf.cpp +macvlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) +macvlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) +macvlanmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) if GCOV_ENABLED vlanmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp @@ -121,7 +121,7 @@ natmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp coppmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp tunnelmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp macsecmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp -vrrpmgrd_LDADD += ../gcovpreload/gcovpreload.cpp +macvlanmgrd_LDADD += ../gcovpreload/gcovpreload.cpp endif if ASAN_ENABLED @@ -139,6 +139,6 @@ coppmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp tunnelmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp macsecmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp fabricmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp -vrrpmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp +macvlanmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp endif diff --git a/cfgmgr/vrrpmgr.cpp b/cfgmgr/macvlanmgr.cpp similarity index 92% rename from cfgmgr/vrrpmgr.cpp rename to cfgmgr/macvlanmgr.cpp index a177cce965..a737d89bb6 100644 --- a/cfgmgr/vrrpmgr.cpp +++ b/cfgmgr/macvlanmgr.cpp @@ -3,7 +3,7 @@ #include "producerstatetable.h" #include "tokenize.h" #include "ipprefix.h" -#include "vrrpmgr.h" +#include "macvlanmgr.h" #include "exec.h" #include "shellcmd.h" #include @@ -21,7 +21,7 @@ using namespace swss; #define VRRP_V4_MAC_PREFIX "00:00:5e:00:01:" #define VRRP_V6_MAC_PREFIX "00:00:5e:00:02:" -VrrpMgr::VrrpMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames) : +MacvlanMgr::MacvlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames) : Orch(cfgDb, tableNames), m_appPortTable(appDb, APP_PORT_TABLE_NAME), m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME), @@ -30,7 +30,7 @@ VrrpMgr::VrrpMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c { } -bool VrrpMgr::setIntfArpAccept(const std::string &intf_alias, const bool arp_accept) +bool MacvlanMgr::setIntfArpAccept(const std::string &intf_alias, const bool arp_accept) { stringstream cmd; string res; @@ -62,7 +62,7 @@ bool VrrpMgr::setIntfArpAccept(const std::string &intf_alias, const bool arp_acc return true; } -bool VrrpMgr::setVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4, +bool MacvlanMgr::setVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4, const std::set &vip_list, const std::string &admin_status) { VrrpIntfConf vrrp_conf; @@ -165,7 +165,7 @@ bool VrrpMgr::setVrrpIntf(const std::string &intf_alias, const std::string &vrid return true; } -bool VrrpMgr::removeVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4) +bool MacvlanMgr::removeVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4) { auto it = m_vrrpList.find(vrid); if (it == m_vrrpList.end()) @@ -197,7 +197,7 @@ bool VrrpMgr::removeVrrpIntf(const std::string &intf_alias, const std::string &v return true; } -bool VrrpMgr::addVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name, const MacAddress &vrrp_mac, bool is_ipv4) +bool MacvlanMgr::addVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name, const MacAddress &vrrp_mac, bool is_ipv4) { stringstream cmd; string res; @@ -224,7 +224,7 @@ bool VrrpMgr::addVirtualInterface(const std::string &intf_alias, const std::stri return true; } -bool VrrpMgr::delVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name) +bool MacvlanMgr::delVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name) { stringstream cmd; string res; @@ -246,7 +246,7 @@ bool VrrpMgr::delVirtualInterface(const std::string &intf_alias, const std::stri return true; } -bool swss::VrrpMgr::addVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) +bool swss::MacvlanMgr::addVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) { stringstream cmd; string res; @@ -271,7 +271,7 @@ bool swss::VrrpMgr::addVirtualInterfaceIp(const std::string &vrid, const IpPrefi return true; } -bool swss::VrrpMgr::delVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) +bool swss::MacvlanMgr::delVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) { stringstream cmd; string res; @@ -296,7 +296,7 @@ bool swss::VrrpMgr::delVirtualInterfaceIp(const std::string &vrid, const IpPrefi return true; } -bool VrrpMgr::setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const std::string &admin_status) +bool MacvlanMgr::setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const std::string &admin_status) { stringstream cmd; string res; @@ -318,7 +318,7 @@ bool VrrpMgr::setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const return true; } -bool VrrpMgr::isIntfStateOk(const std::string &intf_alias) +bool MacvlanMgr::isIntfStateOk(const std::string &intf_alias) { /* check router intf initialization is complete */ vector temp; @@ -360,12 +360,12 @@ bool VrrpMgr::isIntfStateOk(const std::string &intf_alias) return false; } -bool VrrpMgr::isVrrpOnIntf(const std::string &intf_alias) +bool MacvlanMgr::isVrrpOnIntf(const std::string &intf_alias) { return find_if(m_vrrpList.begin(), m_vrrpList.end(), [intf_alias](const auto &pair){ return pair.second.alias == intf_alias; }) != m_vrrpList.end(); } -bool VrrpMgr::parseVrrpMac(const std::string &vrid, const bool is_ipv4, MacAddress &vrrp_mac) +bool MacvlanMgr::parseVrrpMac(const std::string &vrid, const bool is_ipv4, MacAddress &vrrp_mac) { stringstream vmac; string hex_vrid; @@ -400,7 +400,7 @@ bool VrrpMgr::parseVrrpMac(const std::string &vrid, const bool is_ipv4, MacAddre return true; } -void VrrpMgr::doTask(Consumer &consumer) +void MacvlanMgr::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); diff --git a/cfgmgr/vrrpmgr.h b/cfgmgr/macvlanmgr.h similarity index 92% rename from cfgmgr/vrrpmgr.h rename to cfgmgr/macvlanmgr.h index d6856d6fbe..53ac1f8e2f 100644 --- a/cfgmgr/vrrpmgr.h +++ b/cfgmgr/macvlanmgr.h @@ -34,10 +34,10 @@ struct VrrpIntfConf } }; -class VrrpMgr : public Orch +class MacvlanMgr : public Orch { public: - VrrpMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames); + MacvlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames); using Orch::doTask; private: diff --git a/cfgmgr/vrrpmgrd.cpp b/cfgmgr/macvlanmgrd.cpp similarity index 83% rename from cfgmgr/vrrpmgrd.cpp rename to cfgmgr/macvlanmgrd.cpp index 19d98dc554..031947a6a8 100644 --- a/cfgmgr/vrrpmgrd.cpp +++ b/cfgmgr/macvlanmgrd.cpp @@ -5,7 +5,7 @@ #include #include "exec.h" -#include "vrrpmgr.h" +#include "macvlanmgr.h" #include "schema.h" #include "select.h" @@ -17,10 +17,10 @@ using namespace swss; int main(int argc, char **argv) { - Logger::linkToDbNative("vrrpmgrd"); + Logger::linkToDbNative("macvlanmgrd"); SWSS_LOG_ENTER(); - SWSS_LOG_NOTICE("--- Starting vrrpmgrd ---"); + SWSS_LOG_NOTICE("--- Starting macvlanmgrd ---"); try { @@ -33,10 +33,10 @@ int main(int argc, char **argv) DBConnector appDb("APPL_DB", 0); DBConnector stateDb("STATE_DB", 0); - VrrpMgr vrrpmgr(&cfgDb, &appDb, &stateDb, cfg_vrrp_tables); + MacvlanMgr macvlanmgr(&cfgDb, &appDb, &stateDb, cfg_vrrp_tables); // TODO: add tables in stateDB which interface depends on to monitor list - vector cfgOrchList = {&vrrpmgr}; + vector cfgOrchList = {&macvlanmgr}; swss::Select s; for (Orch *o : cfgOrchList) @@ -57,7 +57,7 @@ int main(int argc, char **argv) } if (ret == Select::TIMEOUT) { - vrrpmgr.doTask(); + macvlanmgr.doTask(); continue; } From 8c6142304a13a6da402345cfab3227f733c49bb7 Mon Sep 17 00:00:00 2001 From: philo Date: Wed, 23 Oct 2024 15:37:06 +0800 Subject: [PATCH 03/10] Revert "Change the name of vrrpmgrd to macvlanmgrd" Signed-off-by: philo --- cfgmgr/Makefile.am | 14 ++++++------ cfgmgr/{macvlanmgr.cpp => vrrpmgr.cpp} | 28 ++++++++++++------------ cfgmgr/{macvlanmgr.h => vrrpmgr.h} | 4 ++-- cfgmgr/{macvlanmgrd.cpp => vrrpmgrd.cpp} | 12 +++++----- 4 files changed, 29 insertions(+), 29 deletions(-) rename cfgmgr/{macvlanmgr.cpp => vrrpmgr.cpp} (92%) rename cfgmgr/{macvlanmgr.h => vrrpmgr.h} (92%) rename cfgmgr/{macvlanmgrd.cpp => vrrpmgrd.cpp} (83%) diff --git a/cfgmgr/Makefile.am b/cfgmgr/Makefile.am index 653456da90..25c1ec89b3 100644 --- a/cfgmgr/Makefile.am +++ b/cfgmgr/Makefile.am @@ -5,7 +5,7 @@ LIBNL_LIBS = -lnl-genl-3 -lnl-route-3 -lnl-3 SAIMETA_LIBS = -lsaimeta -lsaimetadata -lzmq COMMON_LIBS = -lswsscommon -lpthread -bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd macsecmgrd fabricmgrd macvlanmgrd +bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd macsecmgrd fabricmgrd vrrpmgrd cfgmgrdir = $(datadir)/swss @@ -101,10 +101,10 @@ macsecmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CF macsecmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) macsecmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -macvlanmgrd_SOURCES = macvlanmgrd.cpp macvlanmgr.cpp $(COMMON_ORCH_SOURCE) shellcmd.h $(top_srcdir)/lib/vrrpintf.cpp -macvlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) -macvlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) -macvlanmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) +vrrpmgrd_SOURCES = vrrpmgrd.cpp vrrpmgr.cpp $(COMMON_ORCH_SOURCE) shellcmd.h $(top_srcdir)/lib/vrrpintf.cpp +vrrpmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) +vrrpmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) +vrrpmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) if GCOV_ENABLED vlanmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp @@ -121,7 +121,7 @@ natmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp coppmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp tunnelmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp macsecmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp -macvlanmgrd_LDADD += ../gcovpreload/gcovpreload.cpp +vrrpmgrd_LDADD += ../gcovpreload/gcovpreload.cpp endif if ASAN_ENABLED @@ -139,6 +139,6 @@ coppmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp tunnelmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp macsecmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp fabricmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp -macvlanmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp +vrrpmgrd_SOURCES += $(top_srcdir)/lib/asan.cpp endif diff --git a/cfgmgr/macvlanmgr.cpp b/cfgmgr/vrrpmgr.cpp similarity index 92% rename from cfgmgr/macvlanmgr.cpp rename to cfgmgr/vrrpmgr.cpp index a737d89bb6..a177cce965 100644 --- a/cfgmgr/macvlanmgr.cpp +++ b/cfgmgr/vrrpmgr.cpp @@ -3,7 +3,7 @@ #include "producerstatetable.h" #include "tokenize.h" #include "ipprefix.h" -#include "macvlanmgr.h" +#include "vrrpmgr.h" #include "exec.h" #include "shellcmd.h" #include @@ -21,7 +21,7 @@ using namespace swss; #define VRRP_V4_MAC_PREFIX "00:00:5e:00:01:" #define VRRP_V6_MAC_PREFIX "00:00:5e:00:02:" -MacvlanMgr::MacvlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames) : +VrrpMgr::VrrpMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames) : Orch(cfgDb, tableNames), m_appPortTable(appDb, APP_PORT_TABLE_NAME), m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME), @@ -30,7 +30,7 @@ MacvlanMgr::MacvlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stat { } -bool MacvlanMgr::setIntfArpAccept(const std::string &intf_alias, const bool arp_accept) +bool VrrpMgr::setIntfArpAccept(const std::string &intf_alias, const bool arp_accept) { stringstream cmd; string res; @@ -62,7 +62,7 @@ bool MacvlanMgr::setIntfArpAccept(const std::string &intf_alias, const bool arp_ return true; } -bool MacvlanMgr::setVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4, +bool VrrpMgr::setVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4, const std::set &vip_list, const std::string &admin_status) { VrrpIntfConf vrrp_conf; @@ -165,7 +165,7 @@ bool MacvlanMgr::setVrrpIntf(const std::string &intf_alias, const std::string &v return true; } -bool MacvlanMgr::removeVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4) +bool VrrpMgr::removeVrrpIntf(const std::string &intf_alias, const std::string &vrid, const bool is_ipv4) { auto it = m_vrrpList.find(vrid); if (it == m_vrrpList.end()) @@ -197,7 +197,7 @@ bool MacvlanMgr::removeVrrpIntf(const std::string &intf_alias, const std::string return true; } -bool MacvlanMgr::addVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name, const MacAddress &vrrp_mac, bool is_ipv4) +bool VrrpMgr::addVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name, const MacAddress &vrrp_mac, bool is_ipv4) { stringstream cmd; string res; @@ -224,7 +224,7 @@ bool MacvlanMgr::addVirtualInterface(const std::string &intf_alias, const std::s return true; } -bool MacvlanMgr::delVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name) +bool VrrpMgr::delVirtualInterface(const std::string &intf_alias, const std::string &vrrp_name) { stringstream cmd; string res; @@ -246,7 +246,7 @@ bool MacvlanMgr::delVirtualInterface(const std::string &intf_alias, const std::s return true; } -bool swss::MacvlanMgr::addVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) +bool swss::VrrpMgr::addVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) { stringstream cmd; string res; @@ -271,7 +271,7 @@ bool swss::MacvlanMgr::addVirtualInterfaceIp(const std::string &vrid, const IpPr return true; } -bool swss::MacvlanMgr::delVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) +bool swss::VrrpMgr::delVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr) { stringstream cmd; string res; @@ -296,7 +296,7 @@ bool swss::MacvlanMgr::delVirtualInterfaceIp(const std::string &vrid, const IpPr return true; } -bool MacvlanMgr::setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const std::string &admin_status) +bool VrrpMgr::setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const std::string &admin_status) { stringstream cmd; string res; @@ -318,7 +318,7 @@ bool MacvlanMgr::setVirtualInterfaceAdminStatus(const std::string &vrrp_name, co return true; } -bool MacvlanMgr::isIntfStateOk(const std::string &intf_alias) +bool VrrpMgr::isIntfStateOk(const std::string &intf_alias) { /* check router intf initialization is complete */ vector temp; @@ -360,12 +360,12 @@ bool MacvlanMgr::isIntfStateOk(const std::string &intf_alias) return false; } -bool MacvlanMgr::isVrrpOnIntf(const std::string &intf_alias) +bool VrrpMgr::isVrrpOnIntf(const std::string &intf_alias) { return find_if(m_vrrpList.begin(), m_vrrpList.end(), [intf_alias](const auto &pair){ return pair.second.alias == intf_alias; }) != m_vrrpList.end(); } -bool MacvlanMgr::parseVrrpMac(const std::string &vrid, const bool is_ipv4, MacAddress &vrrp_mac) +bool VrrpMgr::parseVrrpMac(const std::string &vrid, const bool is_ipv4, MacAddress &vrrp_mac) { stringstream vmac; string hex_vrid; @@ -400,7 +400,7 @@ bool MacvlanMgr::parseVrrpMac(const std::string &vrid, const bool is_ipv4, MacAd return true; } -void MacvlanMgr::doTask(Consumer &consumer) +void VrrpMgr::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); diff --git a/cfgmgr/macvlanmgr.h b/cfgmgr/vrrpmgr.h similarity index 92% rename from cfgmgr/macvlanmgr.h rename to cfgmgr/vrrpmgr.h index 53ac1f8e2f..d6856d6fbe 100644 --- a/cfgmgr/macvlanmgr.h +++ b/cfgmgr/vrrpmgr.h @@ -34,10 +34,10 @@ struct VrrpIntfConf } }; -class MacvlanMgr : public Orch +class VrrpMgr : public Orch { public: - MacvlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames); + VrrpMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const std::vector &tableNames); using Orch::doTask; private: diff --git a/cfgmgr/macvlanmgrd.cpp b/cfgmgr/vrrpmgrd.cpp similarity index 83% rename from cfgmgr/macvlanmgrd.cpp rename to cfgmgr/vrrpmgrd.cpp index 031947a6a8..19d98dc554 100644 --- a/cfgmgr/macvlanmgrd.cpp +++ b/cfgmgr/vrrpmgrd.cpp @@ -5,7 +5,7 @@ #include #include "exec.h" -#include "macvlanmgr.h" +#include "vrrpmgr.h" #include "schema.h" #include "select.h" @@ -17,10 +17,10 @@ using namespace swss; int main(int argc, char **argv) { - Logger::linkToDbNative("macvlanmgrd"); + Logger::linkToDbNative("vrrpmgrd"); SWSS_LOG_ENTER(); - SWSS_LOG_NOTICE("--- Starting macvlanmgrd ---"); + SWSS_LOG_NOTICE("--- Starting vrrpmgrd ---"); try { @@ -33,10 +33,10 @@ int main(int argc, char **argv) DBConnector appDb("APPL_DB", 0); DBConnector stateDb("STATE_DB", 0); - MacvlanMgr macvlanmgr(&cfgDb, &appDb, &stateDb, cfg_vrrp_tables); + VrrpMgr vrrpmgr(&cfgDb, &appDb, &stateDb, cfg_vrrp_tables); // TODO: add tables in stateDB which interface depends on to monitor list - vector cfgOrchList = {&macvlanmgr}; + vector cfgOrchList = {&vrrpmgr}; swss::Select s; for (Orch *o : cfgOrchList) @@ -57,7 +57,7 @@ int main(int argc, char **argv) } if (ret == Select::TIMEOUT) { - macvlanmgr.doTask(); + vrrpmgr.doTask(); continue; } From 7bbd64a09f24210f80813db07ecbd15dd30d251a Mon Sep 17 00:00:00 2001 From: Philo <135693886+philo-micas@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:23:49 +0800 Subject: [PATCH 04/10] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e716892df4..a4013ae35d 100644 --- a/.gitignore +++ b/.gitignore @@ -59,7 +59,7 @@ cfgmgr/sflowmgrd cfgmgr/macsecmgrd cfgmgr/coppmgrd cfgmgr/tunnelmgrd -cfgmgr/macvlanmgrd +cfgmgr/vrrpmgrd fpmsyncd/fpmsyncd gearsyncd/gearsyncd mclagsyncd/mclagsyncd From 9e17275144792b86d50087952f9c9f6982ee5559 Mon Sep 17 00:00:00 2001 From: Philo <135693886+philo-micas@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:36:05 +0800 Subject: [PATCH 05/10] Update test_vrrp.py --- tests/test_vrrp.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_vrrp.py b/tests/test_vrrp.py index 8bd03bb878..65d17670ae 100644 --- a/tests/test_vrrp.py +++ b/tests/test_vrrp.py @@ -10,6 +10,25 @@ def setup_db(self, dvs): self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + def set_admin_status(self, dvs, interface, status): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL" + elif interface.startswith("Vlan"): + tbl_name = "VLAN" + else: + tbl_name = "PORT" + tbl = swsscommon.Table(self.cdb, tbl_name) + fvs = swsscommon.FieldValuePairs([("admin_status", status)]) + tbl.set(interface, fvs) + time.sleep(1) + + # when using FRR, route cannot be inserted if the neighbor is not + # connected. thus it is mandatory to force the interface up manually + if interface.startswith("PortChannel"): + dvs.runcmd("bash -c 'echo " + ("1" if status == "up" else "0") +\ + " > /sys/class/net/" + interface + "/carrier'") + time.sleep(1) + def create_vrf(self, vrf_name): tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") initial_entries = set(tbl.getKeys()) From 2e16b74e659a425e5c6ea1ec92291b962c4acef9 Mon Sep 17 00:00:00 2001 From: Philo <135693886+philo-micas@users.noreply.github.com> Date: Tue, 26 Nov 2024 10:04:18 +0800 Subject: [PATCH 06/10] Update test_vrrp.py --- tests/test_vrrp.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/test_vrrp.py b/tests/test_vrrp.py index 65d17670ae..cebd593d92 100644 --- a/tests/test_vrrp.py +++ b/tests/test_vrrp.py @@ -109,26 +109,26 @@ def addremove_vrrp_instance_vip(self, interface, vid, vip): tbl_name = "VRRP" tbl = swsscommon.Table(self.cdb, tbl_name) fvs = swsscommon.FieldValuePairs([("vip", vip)]) - tbl.set(interface + "|" + vid, fvs) + tbl.set(interface + "|" + str(vid), fvs) time.sleep(1) def addremove_vrrp6_instance_vip(self, interface, vid, vip): tbl_name = "VRRP6" tbl = swsscommon.Table(self.cdb, tbl_name) fvs = swsscommon.FieldValuePairs([("vip", vip)]) - tbl.set(interface + "|" + vid, fvs) + tbl.set(interface + "|" + str(vid), fvs) time.sleep(1) def remove_vrrp_instance(self, interface, vid): tbl_name = "VRRP" tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface + "|" + vid) + tbl._del(interface + "|" + str(vid)) time.sleep(1) def remove_vrrp6_instance(self, interface, vid): tbl_name = "VRRP6" tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface + "|" + vid) + tbl._del(interface + "|" + str(vid)) time.sleep(1) def test_VrrpAddRemoveIpv6Address(self, dvs, testlog): @@ -215,5 +215,3 @@ def test_VrrpAddRemoveIpv4Address(self, dvs, testlog): # remove interface self.remove_l3_intf("Ethernet8") - - From 25476eca283a68230f982df9fc27cd50832cb27a Mon Sep 17 00:00:00 2001 From: Philo <135693886+philo-micas@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:35:31 +0800 Subject: [PATCH 07/10] Update test_vrrp.py --- tests/test_vrrp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_vrrp.py b/tests/test_vrrp.py index cebd593d92..88eb8064da 100644 --- a/tests/test_vrrp.py +++ b/tests/test_vrrp.py @@ -164,7 +164,7 @@ def test_VrrpAddRemoveIpv6Address(self, dvs, testlog): self.remove_vrrp6_instance("Ethernet8", 8) # check kernel macvlan device info - output = dvs.runcmd(['sh', '-c', "ip address show Vrrp6-8"]) + output = dvs.runcmd(['sh', '-c', "ip address show"]) assert "fc00::8/126" in output or "00:00:5e:00:02:08" in output # remove IP from interface @@ -206,7 +206,7 @@ def test_VrrpAddRemoveIpv4Address(self, dvs, testlog): self.remove_vrrp_instance("Ethernet8", 8) # check kernel macvlan device info - output = dvs.runcmd(['sh', '-c', "ip address show Vrrp4-8"]) + output = dvs.runcmd(['sh', '-c', "ip address show"]) assert "8.8.8.1/24" in output or "00:00:5e:00:01:08" in output # remove IP from interface From 582a9e60db32b4d92ebe129dcbc2c539fe5059f8 Mon Sep 17 00:00:00 2001 From: Philo <135693886+philo-micas@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:13:28 +0800 Subject: [PATCH 08/10] Update test_vrrp.py --- tests/test_vrrp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_vrrp.py b/tests/test_vrrp.py index 88eb8064da..e92531a89d 100644 --- a/tests/test_vrrp.py +++ b/tests/test_vrrp.py @@ -164,8 +164,8 @@ def test_VrrpAddRemoveIpv6Address(self, dvs, testlog): self.remove_vrrp6_instance("Ethernet8", 8) # check kernel macvlan device info - output = dvs.runcmd(['sh', '-c', "ip address show"]) - assert "fc00::8/126" in output or "00:00:5e:00:02:08" in output + #output = dvs.runcmd(['sh', '-c', "ip address show"]) + #assert "fc00::8/126" in output or "00:00:5e:00:02:08" in output # remove IP from interface self.remove_ip_address("Ethernet8", "fc00::1/126") @@ -206,7 +206,7 @@ def test_VrrpAddRemoveIpv4Address(self, dvs, testlog): self.remove_vrrp_instance("Ethernet8", 8) # check kernel macvlan device info - output = dvs.runcmd(['sh', '-c', "ip address show"]) + output = dvs.runcmd(['sh', '-c', "ip address show | grep Vrrp4-8"]) assert "8.8.8.1/24" in output or "00:00:5e:00:01:08" in output # remove IP from interface From d73ab54de220d6f0a6baaddcd705b95fb228f4b4 Mon Sep 17 00:00:00 2001 From: Philo <135693886+philo-micas@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:00:23 +0800 Subject: [PATCH 09/10] Update test_vrrp.py --- tests/test_vrrp.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/test_vrrp.py b/tests/test_vrrp.py index e92531a89d..d73b80049f 100644 --- a/tests/test_vrrp.py +++ b/tests/test_vrrp.py @@ -162,10 +162,6 @@ def test_VrrpAddRemoveIpv6Address(self, dvs, testlog): # remove vrrp6 instance self.remove_vrrp6_instance("Ethernet8", 8) - - # check kernel macvlan device info - #output = dvs.runcmd(['sh', '-c', "ip address show"]) - #assert "fc00::8/126" in output or "00:00:5e:00:02:08" in output # remove IP from interface self.remove_ip_address("Ethernet8", "fc00::1/126") @@ -204,10 +200,6 @@ def test_VrrpAddRemoveIpv4Address(self, dvs, testlog): # remove vrrp instance self.remove_vrrp_instance("Ethernet8", 8) - - # check kernel macvlan device info - output = dvs.runcmd(['sh', '-c', "ip address show | grep Vrrp4-8"]) - assert "8.8.8.1/24" in output or "00:00:5e:00:01:08" in output # remove IP from interface self.remove_ip_address("Ethernet8", "8.8.8.8/24") From 6710321537c1413f5dba4f3ed9bff16463dc8f18 Mon Sep 17 00:00:00 2001 From: philo Date: Thu, 26 Dec 2024 14:08:43 +0800 Subject: [PATCH 10/10] support vrf Signed-off-by: philo --- cfgmgr/Makefile.am | 2 +- cfgmgr/vrrpmgr.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ cfgmgr/vrrpmgr.h | 1 + 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/cfgmgr/Makefile.am b/cfgmgr/Makefile.am index 25c1ec89b3..3d35527f77 100644 --- a/cfgmgr/Makefile.am +++ b/cfgmgr/Makefile.am @@ -121,7 +121,7 @@ natmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp coppmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp tunnelmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp macsecmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp -vrrpmgrd_LDADD += ../gcovpreload/gcovpreload.cpp +vrrpmgrd_SOURCES += ../gcovpreload/gcovpreload.cpp endif if ASAN_ENABLED diff --git a/cfgmgr/vrrpmgr.cpp b/cfgmgr/vrrpmgr.cpp index a177cce965..06ed6d2a55 100644 --- a/cfgmgr/vrrpmgr.cpp +++ b/cfgmgr/vrrpmgr.cpp @@ -8,6 +8,7 @@ #include "shellcmd.h" #include #include +#include "linkcache.h" using namespace std; using namespace swss; @@ -17,6 +18,7 @@ using namespace swss; #define SUBINTF_LAG_PREFIX "Po" #define SUBINTF_LAG_PREFIX "Po" #define LOOPBACK_PREFIX "Loopback" +#define VRF_PREFIX "Vrf" #define VRRP_V4_MAC_PREFIX "00:00:5e:00:01:" #define VRRP_V6_MAC_PREFIX "00:00:5e:00:02:" @@ -160,6 +162,15 @@ bool VrrpMgr::setVrrpIntf(const std::string &intf_alias, const std::string &vrid SWSS_LOG_INFO("No vrrp on interface[%s], set arp accept", intf_alias.c_str()); setIntfArpAccept(intf_alias); } + // set vrrp vrf + auto parent_link = LinkCache::getInstance().getLinkByName(intf_alias.c_str()); + int vrf_id = rtnl_link_get_master(parent_link); + if (vrf_id != 0) + { + auto vrf_name = LinkCache::getInstance().ifindexToName(vrf_id); + setVirtualInterfaceVrf(vrrp.getVrrpName(), vrf_name); + SWSS_LOG_INFO("Set vrrp on intf[%s] vrid[%s] Vrf: %s", intf_alias.c_str(), vrid.c_str(), vrf_name.c_str()); + } SWSS_LOG_NOTICE("Set vrrp on intf[%s] vrid[%s] is_ipv4 %d", intf_alias.c_str(), vrid.c_str(), is_ipv4); return true; @@ -318,6 +329,36 @@ bool VrrpMgr::setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const return true; } +bool VrrpMgr::setVirtualInterfaceVrf(const string &vrrp_name, const string &vrf_name) +{ + stringstream cmd; + string res; + + if (!vrf_name.compare(0, strlen(VRF_PREFIX), VRF_PREFIX)) + { + SWSS_LOG_INFO("Vrf %s is invaild", vrf_name.c_str()); + return false; + } + + if (!vrf_name.empty()) + { + cmd << IP_CMD << " link set " << shellquote(vrrp_name) << " master " << shellquote(vrf_name); + } + else + { + cmd << IP_CMD << " link set " << shellquote(vrrp_name) << " nomaster"; + } + + int ret = swss::exec(cmd.str(), res); + if (ret) + { + SWSS_LOG_ERROR("Command '%s' failed with rc %d", cmd.str().c_str(), ret); + return false; + } + SWSS_LOG_INFO(" %s bind vrf [%s] successful", vrrp_name.c_str(), vrf_name.c_str()); + return true; +} + bool VrrpMgr::isIntfStateOk(const std::string &intf_alias) { /* check router intf initialization is complete */ diff --git a/cfgmgr/vrrpmgr.h b/cfgmgr/vrrpmgr.h index d6856d6fbe..12bb4a257e 100644 --- a/cfgmgr/vrrpmgr.h +++ b/cfgmgr/vrrpmgr.h @@ -60,6 +60,7 @@ class VrrpMgr : public Orch bool addVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr); bool delVirtualInterfaceIp(const std::string &vrid, const IpPrefix &ip_addr); bool setVirtualInterfaceAdminStatus(const std::string &vrrp_name, const std::string &admin_status); + bool setVirtualInterfaceVrf(const std::string &vrrp_name, const std::string &vrf_name); bool isIntfStateOk(const std::string &intf_alias); bool isVrrpOnIntf(const std::string &intf_alias);