From dd4e40924ffa5d8e2391655e9f966da0adf97167 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 28 Jan 2021 18:45:20 -0800 Subject: [PATCH] [MACsecMgr]: Add MACsec Manager (#1475) Add MACsec Manager for MACsec feature. MACsecMgr is a daemon in MACsec container, that receives the message from CONFIG DB and uses wpa_cli instructions to manage the functionality of MACsec in the specified port. The below figure is the flow chart of MACsecMgr which shows the MACsec profile management according to MACsec Profile Table and the functionality of MACsec in the specified port according to PortTable. The main functions are defined in class MACsecMgr as follow ``` task_process_status removeProfile(const std::string & profile_name, const TaskArgs & profile_attr); task_process_status loadProfile(const std::string & profile_name, const TaskArgs & profile_attr); task_process_status enableMACsec(const std::string & port_name, const TaskArgs & port_attr); task_process_status disableMACsec(const std::string & port_name, const TaskArgs & port_attr); ``` The HLD of MACsec Manager is at [MACsec HLD](https://github.com/Azure/SONiC/blob/master/doc/macsec/MACsec_hld.md#341-macsec-mgr) Signed-off-by: Ze Gan --- .gitignore | 1 + cfgmgr/Makefile.am | 6 +- cfgmgr/macsecmgr.cpp | 734 ++++++++++++++++++++++++++++++++++++++++++ cfgmgr/macsecmgr.h | 78 +++++ cfgmgr/macsecmgrd.cpp | 98 ++++++ 5 files changed, 916 insertions(+), 1 deletion(-) create mode 100644 cfgmgr/macsecmgr.cpp create mode 100644 cfgmgr/macsecmgr.h create mode 100644 cfgmgr/macsecmgrd.cpp diff --git a/.gitignore b/.gitignore index d020b570580e..439a0999f30d 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ cfgmgr/vrfmgrd cfgmgr/vxlanmgrd cfgmgr/natmgrd cfgmgr/sflowmgrd +cfgmgr/macsecmgrd fpmsyncd/fpmsyncd gearsyncd/gearsyncd mclagsyncd/mclagsyncd diff --git a/cfgmgr/Makefile.am b/cfgmgr/Makefile.am index 87902c36e554..3321f82a4cdd 100644 --- a/cfgmgr/Makefile.am +++ b/cfgmgr/Makefile.am @@ -3,7 +3,7 @@ CFLAGS_SAI = -I /usr/include/sai LIBNL_CFLAGS = -I/usr/include/libnl3 LIBNL_LIBS = -lnl-genl-3 -lnl-route-3 -lnl-3 -bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd +bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd macsecmgrd cfgmgrdir = $(datadir)/swss @@ -81,3 +81,7 @@ tunnelmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) tunnelmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) tunnelmgrd_LDADD = -lswsscommon +macsecmgrd_SOURCES = macsecmgrd.cpp macsecmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp shellcmd.h +macsecmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) +macsecmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) +macsecmgrd_LDADD = -lswsscommon diff --git a/cfgmgr/macsecmgr.cpp b/cfgmgr/macsecmgr.cpp new file mode 100644 index 000000000000..bf5344c8d0c0 --- /dev/null +++ b/cfgmgr/macsecmgr.cpp @@ -0,0 +1,734 @@ +#include "macsecmgr.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; +using namespace swss; + +#define WPA_SUPPLICANT_CMD "./wpa_supplicant" +#define WPA_CLI_CMD "./wpa_cli" +#define WPA_CONF "./wpa.conf" +// #define SOCK_DIR "/var/run/macsec/" +#define SOCK_DIR "./" + +constexpr std::uint64_t RETRY_TIME = 30; + +/* retry interval, in millisecond */ +constexpr std::uint64_t RETRY_INTERVAL = 100; + +static void lexical_convert(const std::string &policy_str, MACsecMgr::MACsecProfile::Policy & policy) +{ + SWSS_LOG_ENTER(); + + if (boost::iequals(policy_str, "integrity_only")) + { + policy = MACsecMgr::MACsecProfile::Policy::INTEGRITY_ONLY; + } + else if (boost::iequals(policy_str, "security")) + { + policy = MACsecMgr::MACsecProfile::Policy::SECURITY; + } + else + { + throw std::invalid_argument("Invalid policy : " + policy_str); + } +} + +template +static bool get_value( + const MACsecMgr::TaskArgs & ta, + const std::string & field, + T & value) +{ + SWSS_LOG_ENTER(); + + auto value_opt = swss::fvsGetValue(ta, field, true); + if (!value_opt) + { + SWSS_LOG_WARN("Cannot find field : %s", field.c_str()); + return false; + } + + lexical_convert(*value_opt, value); + + return false; +} + +static void wpa_cli_commands(std::ostringstream & ostream) +{ + // Intentionally emtpy function to adapt + // the recursively calling of wpa_cli_commands +} + +template +static void wpa_cli_commands( + std::ostringstream & ostream, + T && t, + Args && ... args) +{ + ostream << " " << t; + wpa_cli_commands(ostream, args...); +} + +template +static void wpa_cli_commands( + std::ostringstream & ostream, + const std::string & t, + Args && ... args) +{ + ostream << shellquote(t) << " "; + wpa_cli_commands(ostream, args...); +} + +template +static void wpa_cli_commands( + std::ostringstream & ostream, + const std::string & sock, + const std::string & port_name, + const std::string & network_id, + Args && ... args) +{ + ostream << WPA_CLI_CMD; + wpa_cli_commands(ostream, "-g", sock); + if (!port_name.empty()) + { + wpa_cli_commands(ostream, "IFNAME=" + port_name); + } + if (!network_id.empty()) + { + wpa_cli_commands(ostream, "set_network", port_name); + } + wpa_cli_commands(ostream, args...); +} + +template +static std::string wpa_cli_exec( + const std::string & sock, + const std::string & port_name, + const std::string & network_id, + Args && ... args) +{ + std::ostringstream ostream; + std::string res; + wpa_cli_commands( + ostream, + sock, + port_name, + network_id, + std::forward(args)...); + EXEC_WITH_ERROR_THROW(ostream.str(), res); + return res; +} + +template +static void wpa_cli_exec_and_check( + const std::string & sock, + const std::string & port_name, + const std::string & network_id, + Args && ... args) +{ + std::string res = wpa_cli_exec( + sock, + port_name, + network_id, + std::forward(args)...); + if (res.find("OK") != 0) + { + std::ostringstream ostream; + wpa_cli_commands( + ostream, + sock, + port_name, + network_id, + std::forward(args)...); + throw std::runtime_error( + "Wpa_cli command : " + ostream.str() + " -> " +res); + } +} + +MACsecMgr::MACsecMgr( + DBConnector *cfgDb, + DBConnector *stateDb, + const vector &tables) : + Orch(cfgDb, tables), + m_statePortTable(stateDb, STATE_PORT_TABLE_NAME) +{ +} + +MACsecMgr::~MACsecMgr() +{ + // Disable MACsec for all ports + while (!m_macsec_ports.empty()) + { + auto port = m_macsec_ports.begin(); + const TaskArgs temp; + disableMACsec(port->first, temp); + } +} + +void MACsecMgr::doTask(Consumer &consumer) +{ + SWSS_LOG_ENTER(); + + using TaskType = std::tuple; + using TaskFunc = task_process_status (MACsecMgr::*)(const std::string &, const TaskArgs &); + const static std::map TaskMap = { + { { CFG_MACSEC_PROFILE_TABLE_NAME, SET_COMMAND }, &MACsecMgr::loadProfile}, + { { CFG_MACSEC_PROFILE_TABLE_NAME, DEL_COMMAND }, &MACsecMgr::removeProfile}, + { { CFG_PORT_TABLE_NAME, SET_COMMAND }, &MACsecMgr::enableMACsec}, + { { CFG_PORT_TABLE_NAME, DEL_COMMAND }, &MACsecMgr::disableMACsec}, + }; + + const std::string & table_name = consumer.getTableName(); + auto itr = consumer.m_toSync.begin(); + while (itr != consumer.m_toSync.end()) + { + task_process_status task_done = task_failed; + auto & message = itr->second; + const std::string & op = kfvOp(message); + + auto task = TaskMap.find(std::make_tuple(table_name, op)); + if (task != TaskMap.end()) + { + task_done = (this->*task->second)( + kfvKey(message), + kfvFieldsValues(message)); + } + else + { + SWSS_LOG_ERROR( + "Unknown task : %s - %s", + table_name.c_str(), + op.c_str()); + } + + if (task_done == task_need_retry) + { + SWSS_LOG_DEBUG( + "Task %s - %s need retry", + table_name.c_str(), + op.c_str()); + ++itr; + } + else + { + if (task_done != task_success) + { + SWSS_LOG_WARN("Task %s - %s fail", + table_name.c_str(), + op.c_str()); + } + else + { + SWSS_LOG_DEBUG( + "Task %s - %s success", + table_name.c_str(), + op.c_str()); + } + + itr = consumer.m_toSync.erase(itr); + } + } +} + +#define GetValue(args, name) (get_value(args, #name, name)) + +bool MACsecMgr::MACsecProfile::update(const TaskArgs & ta) +{ + SWSS_LOG_ENTER(); + + // The following fields are optional + if (GetValue(ta, fallback_cak) && !GetValue(ta, fallback_ckn)) + { + return false; + } + if (!GetValue(ta, enable_replay_protect)) + { + enable_replay_protect = false; + } + if (!GetValue(ta, replay_window)) + { + replay_window = 0; + } + if (!GetValue(ta, send_sci)) + { + send_sci = true; + } + if (!GetValue(ta, rekey_period)) + { + rekey_period = 0; + } + if (!GetValue(ta, priority)) + { + priority = 255; + } + if (!GetValue(ta, policy)) + { + policy = Policy::SECURITY; + } + + // The following fields are necessary + return GetValue(ta, cipher_suite) + && GetValue(ta, primary_cak) + && GetValue(ta, primary_ckn); +} + +task_process_status MACsecMgr::loadProfile( + const std::string & profile_name, + const TaskArgs & profile_attr) +{ + SWSS_LOG_ENTER(); + + auto profile = m_profiles.emplace( + std::piecewise_construct, + std::make_tuple(profile_name), + std::make_tuple()); + try + { + if (profile.first->second.update(profile_attr)) + { + SWSS_LOG_NOTICE( + "The MACsec profile '%s' is loaded", + profile_name.c_str()); + } + // If the profile has been used + if (profile.second) + { + for (auto & port : m_macsec_ports) + { + if (port.second.profile_name == profile_name) + { + // Hot update + SWSS_LOG_DEBUG("Hot update"); + } + } + } + return task_success; + } + catch(const std::invalid_argument & e) + { + SWSS_LOG_WARN("%s", e.what()); + return task_failed; + } +} + +task_process_status MACsecMgr::removeProfile( + const std::string & profile_name, + const TaskArgs & profile_attr) +{ + SWSS_LOG_ENTER(); + + auto profile = m_profiles.find(profile_name); + if (profile == m_profiles.end()) + { + SWSS_LOG_WARN( + "The MACsec profile '%s' wasn't loaded", + profile_name.c_str()); + return task_invalid_entry; + } + + // The MACsec profile cannot be removed if it is occupied + auto port = std::find_if( + m_macsec_ports.begin(), + m_macsec_ports.end(), + [&](const decltype(m_macsec_ports)::value_type & pair) + { + return pair.second.profile_name == profile_name; + }); + if (port != m_macsec_ports.end()) + { + // This MACsec profile is occupied by some ports + // remove it after all ports disable MACsec + SWSS_LOG_DEBUG( + "The MACsec profile '%s' is used by the port '%s'", + profile_name.c_str(), + port->first.c_str()); + return task_need_retry; + } + SWSS_LOG_NOTICE("The MACsec profile '%s' is removed", profile_name.c_str()); + m_profiles.erase(profile); + return task_success; +} + +task_process_status MACsecMgr::enableMACsec( + const std::string & port_name, + const TaskArgs & port_attr) +{ + SWSS_LOG_ENTER(); + + std::string profile_name; + if (!get_value(port_attr, "macsec", profile_name) + || profile_name.empty()) + { + SWSS_LOG_DEBUG("MACsec field of port '%s' is empty", port_name.c_str()); + return disableMACsec(port_name, port_attr); + } + + // If the MACsec profile is ready + auto itr = m_profiles.find(profile_name); + if (itr == m_profiles.end()) + { + SWSS_LOG_DEBUG( + "The MACsec profile '%s' for the port '%s' isn't ready", + profile_name.c_str(), + port_name.c_str()); + return task_need_retry; + } + auto & profile = itr->second; + + // If the port is ready + if (!isPortStateOk(port_name)) + { + SWSS_LOG_DEBUG("The port '%s' isn't ready", port_name.c_str()); + return task_need_retry; + } + + // Create MKA Session object + auto port = m_macsec_ports.emplace( + std::piecewise_construct, + std::make_tuple(port_name), + std::make_tuple()); + if (!port.second) + { + if (port.first->second.profile_name == profile_name) + { + SWSS_LOG_NOTICE( + "The MACsec profile '%s' on the port '%s' has been loaded", + profile_name.c_str(), + port_name.c_str()); + return task_success; + } + else + { + SWSS_LOG_NOTICE( + "The MACsec profile '%s' on the port '%s' " + "will be replaced by the MACsec profile '%s'", + port.first->second.profile_name.c_str(), + port_name.c_str(), + profile_name.c_str()); + auto result = disableMACsec(port_name, port_attr); + if (result != task_success) + { + return result; + } + } + } + auto & session = port.first->second; + session.profile_name = profile_name; + ostringstream ostream; + ostream << SOCK_DIR << port_name; + session.sock = ostream.str(); + session.wpa_supplicant_pid = startWPASupplicant(session.sock); + if (session.wpa_supplicant_pid < 0) + { + SWSS_LOG_WARN("Cannot start the wpa_supplicant of the port '%s' : %s", + port_name.c_str(), + strerror(errno)); + m_macsec_ports.erase(port.first); + return task_need_retry; + } + else if (session.wpa_supplicant_pid == 0) + { + SWSS_LOG_WARN("Cannot start the wpa_supplicant of the port '%s' : %s", + port_name.c_str(), + strerror(errno)); + m_macsec_ports.erase(port.first); + return task_failed; + } + + // Enable MACsec + if (!configureMACsec(port_name, session, profile)) + { + SWSS_LOG_WARN("The MACsec profile '%s' on the port '%s' loading fail", + profile_name.c_str(), + port_name.c_str()); + return disableMACsec(port_name, port_attr); + } + SWSS_LOG_NOTICE("The MACsec profile '%s' on the port '%s' loading success", + profile_name.c_str(), + port_name.c_str()); + return task_success; +} + +task_process_status MACsecMgr::disableMACsec( + const std::string & port_name, + const TaskArgs & port_attr) +{ + SWSS_LOG_ENTER(); + + auto itr = m_macsec_ports.find(port_name); + if (itr == m_macsec_ports.end()) + { + SWSS_LOG_NOTICE("The MACsec was not enabled on the port '%s'", + port_name.c_str()); + return task_success; + } + auto & session = itr->second; + task_process_status ret = task_success; + if (!unconfigureMACsec(port_name, session)) + { + SWSS_LOG_WARN( + "Cannot stop MKA session on the port '%s'", + port_name.c_str()); + ret = task_failed; + } + if (!stopWPASupplicant(session.wpa_supplicant_pid)) + { + SWSS_LOG_WARN( + "Cannot stop WPA_SUPPLICANT process of the port '%s'", + port_name.c_str()); + ret = task_failed; + } + if (ret == task_success) + { + SWSS_LOG_NOTICE("The MACsec profile '%s' on the port '%s' is removed", + itr->second.profile_name.c_str(), + port_name.c_str()); + } + m_macsec_ports.erase(itr); + return ret; +} + +bool MACsecMgr::isPortStateOk(const std::string & port_name) +{ + SWSS_LOG_ENTER(); + + std::vector temp; + std::string state; + + if (m_statePortTable.get(port_name, temp) + && get_value(temp, "state", state) + && state == "ok") + { + SWSS_LOG_DEBUG("Port '%s' is ready", port_name.c_str()); + return true; + } + SWSS_LOG_DEBUG("Port '%s' is not ready", port_name.c_str()); + return false; +} + +pid_t MACsecMgr::startWPASupplicant(const std::string & sock) const +{ + SWSS_LOG_ENTER(); + + pid_t wpa_supplicant_pid = fork(); + if (wpa_supplicant_pid == 0) + { + exit(execl( + WPA_SUPPLICANT_CMD, + WPA_SUPPLICANT_CMD, + "-s", + "-D", "macsec_sonic", + "-g", sock.c_str(), + NULL)); + } + else if (wpa_supplicant_pid > 0) + { + // Wait wpa_supplicant ready + bool wpa_supplicant_loading = false; + auto retry_time = RETRY_TIME; + while(!wpa_supplicant_loading && retry_time > 0) + { + try + { + wpa_cli_exec(sock, "", "", "status"); + wpa_supplicant_loading = true; + } + catch(const std::runtime_error&) + { + retry_time--; + std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_INTERVAL)); + } + } + if (wpa_supplicant_loading) + { + SWSS_LOG_DEBUG("Start wpa_supplicant success"); + } + else + { + stopWPASupplicant(wpa_supplicant_pid); + wpa_supplicant_pid = 0; + SWSS_LOG_WARN("Cannot connect to wpa_supplicant."); + } + } + return wpa_supplicant_pid; +} + +bool MACsecMgr::stopWPASupplicant(pid_t pid) const +{ + SWSS_LOG_ENTER(); + + if(kill(pid, SIGINT) != 0) + { + SWSS_LOG_WARN("Cannot stop wpa_supplicant(%d)", pid); + return false; + } + int status = 0; + waitpid(pid, &status, 0); + SWSS_LOG_DEBUG( + "Stop wpa_supplicant(%d) with return value (%d)", + pid, + status); + return status == 0; +} + +bool MACsecMgr::configureMACsec( + const std::string & port_name, + const MKASession & session, + const MACsecProfile & profile) const +{ + SWSS_LOG_ENTER(); + + try + { + wpa_cli_exec_and_check( + session.sock, + "", + "", + "interface_add", + port_name, + WPA_CONF, + "macsec_sonic"); + + const std::string res = wpa_cli_exec( + session.sock, + port_name, + "", + "add_network"); + const std::string network_id( + res.begin(), + std::find_if_not( + res.begin(), + res.end(), + [](unsigned char c) + { + return std::isdigit(c); + } + ) + ); + if (network_id.empty()) + { + throw std::runtime_error("Cannot add network : " + res); + } + + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "key_mgmt", + "NONE"); + + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "eapol_flags", + 0); + + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "macsec_policy", + 1); + + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "macsec_integ_only", + (profile.policy == MACsecProfile::Policy::INTEGRITY_ONLY ? 1 : 0)); + + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "mka_cak", + profile.primary_cak); + + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "mka_ckn", + profile.primary_ckn); + + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "mka_priority", + profile.priority); + + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "macsec_replay_protect", + (profile.enable_replay_protect ? 1 : 0)); + + if (profile.enable_replay_protect) + { + wpa_cli_exec_and_check( + session.sock, + port_name, + network_id, + "macsec_replay_window", + profile.replay_window); + } + + wpa_cli_exec_and_check( + session.sock, + port_name, + "", + "enable_network", + network_id); + } + catch(const std::runtime_error & e) + { + SWSS_LOG_WARN("Enable MACsec fail : %s", e.what()); + return false; + } + return true; +} + +bool MACsecMgr::unconfigureMACsec( + const std::string & port_name, + const MKASession & session) const +{ + SWSS_LOG_ENTER(); + try + { + wpa_cli_exec_and_check( + session.sock, + "", + "", + "interface_remove", + port_name); + } + catch(const std::runtime_error & e) + { + SWSS_LOG_WARN("Disable MACsec fail : %s", e.what()); + return false; + } + return true; +} diff --git a/cfgmgr/macsecmgr.h b/cfgmgr/macsecmgr.h new file mode 100644 index 000000000000..50bd04bbcfa9 --- /dev/null +++ b/cfgmgr/macsecmgr.h @@ -0,0 +1,78 @@ +#ifndef __MACSECMGR__ +#define __MACSECMGR__ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace swss { + +class MACsecMgr : public Orch +{ +public: + using Orch::doTask; + MACsecMgr(DBConnector *cfgDb, DBConnector *stateDb, const std::vector &tableNames); + ~MACsecMgr(); +private: + void doTask(Consumer &consumer); + +public: + using TaskArgs = std::vector; + struct MACsecProfile + { + std::uint8_t priority; + std::string cipher_suite; + std::string primary_cak; + std::string primary_ckn; + std::string fallback_cak; + std::string fallback_ckn; + enum Policy + { + INTEGRITY_ONLY, + SECURITY, + } policy; + swss::AlphaBoolean enable_replay_protect; + std::uint32_t replay_window; + swss::AlphaBoolean send_sci; + std::uint32_t rekey_period; + bool update(const TaskArgs & ta); + }; + + struct MKASession + { + std::string profile_name; + // wpa_supplicant communication socket + std::string sock; + // wpa_supplicant process id + pid_t wpa_supplicant_pid; + }; + +private: + std::map m_profiles; + std::map m_macsec_ports; + + task_process_status removeProfile(const std::string & profile_name, const TaskArgs & profile_attr); + task_process_status loadProfile(const std::string & profile_name, const TaskArgs & profile_attr); + task_process_status enableMACsec(const std::string & port_name, const TaskArgs & port_attr); + task_process_status disableMACsec(const std::string & port_name, const TaskArgs & port_attr); + + + Table m_statePortTable; + + bool isPortStateOk(const std::string & port_name); + pid_t startWPASupplicant(const std::string & sock) const; + bool stopWPASupplicant(pid_t pid) const; + bool configureMACsec(const std::string & port_name, const MKASession & session, const MACsecProfile & profile) const; + bool unconfigureMACsec(const std::string & port_name, const MKASession & session) const; +}; + +} + +#endif diff --git a/cfgmgr/macsecmgrd.cpp b/cfgmgr/macsecmgrd.cpp new file mode 100644 index 000000000000..2cad8fc56eea --- /dev/null +++ b/cfgmgr/macsecmgrd.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "macsecmgr.h" + +using namespace std; +using namespace swss; + +/* select() function timeout retry time, in millisecond */ +#define SELECT_TIMEOUT 1000 + +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) +{ + + try + { + // Logger::linkToDbNative("macsecmgrd"); + SWSS_LOG_NOTICE("--- Starting macsecmgrd ---"); + + swss::DBConnector cfgDb("CONFIG_DB", 0); + swss::DBConnector stateDb("STATE_DB", 0); + + std::vector cfg_macsec_tables = { + CFG_MACSEC_PROFILE_TABLE_NAME, + CFG_PORT_TABLE_NAME, + }; + + MACsecMgr macsecmgr(&cfgDb, &stateDb, cfg_macsec_tables); + + std::vector cfgOrchList = {&macsecmgr}; + + swss::Select s; + for (Orch *o : cfgOrchList) + { + s.addSelectables(o->getSelectables()); + } + + SWSS_LOG_NOTICE("starting main loop"); + 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) + { + macsecmgr.doTask(); + continue; + } + + auto *c = (Executor *)sel; + c->execute(); + } + } + catch(const std::exception &e) + { + SWSS_LOG_ERROR("Runtime error: %s", e.what()); + } + return -1; +}