From 28072f7cc5dbf6257b8d8e01245f03a9c4153a83 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 27 Aug 2020 20:46:32 +0800 Subject: [PATCH 01/31] MACsec Orch init Signed-off-by: Ze Gan --- orchagent/Makefile.am | 3 +- orchagent/macsecorch.cpp | 1274 ++++++++++++++++++++++++++++++++++++++ orchagent/macsecorch.h | 158 +++++ orchagent/orchdaemon.cpp | 13 +- orchagent/orchdaemon.h | 1 + orchagent/port.h | 2 + orchagent/portsorch.cpp | 1 + orchagent/saihelper.cpp | 3 + 8 files changed, 1453 insertions(+), 2 deletions(-) create mode 100644 orchagent/macsecorch.cpp create mode 100644 orchagent/macsecorch.h diff --git a/orchagent/Makefile.am b/orchagent/Makefile.am index ac8db06be3..de3284117b 100644 --- a/orchagent/Makefile.am +++ b/orchagent/Makefile.am @@ -59,7 +59,8 @@ orchagent_SOURCES = \ sfloworch.cpp \ chassisorch.cpp \ debugcounterorch.cpp \ - natorch.cpp + natorch.cpp \ + macsecorch.cpp orchagent_SOURCES += flex_counter/flex_counter_manager.cpp flex_counter/flex_counter_stat_manager.cpp orchagent_SOURCES += debug_counter/debug_counter.cpp debug_counter/drop_counter.cpp diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp new file mode 100644 index 0000000000..e170291ce2 --- /dev/null +++ b/orchagent/macsecorch.cpp @@ -0,0 +1,1274 @@ +#include "macsecorch.h" +#include "gearboxutils.h" +#include "sai_serialize.h" + +#include +#include +#include + +extern sai_macsec_api_t* sai_macsec_api; +extern sai_acl_api_t* sai_acl_api; + +template +static bool split(const std::string & input, char delimiter, T & output) +{ + if (input.find(delimiter) != std::string::npos) + { + return false; + } + std::istringstream istream(input); + istream >> output; + return true; +} + +template +static bool split(const std::string & input, char delimiter, T & output, Args & ... args) +{ + auto pos = input.find(delimiter); + if (pos == std::string::npos) + { + return false; + } + std::istringstream istream(input.substr(0, pos)); + istream >> output; + return split(input.substr(pos + 1, input.length() - pos - 1), delimiter, args...); +} + +template +static std::string join(const T & input) +{ + std::ostringstream ostream; + ostream << input; + return ostream.str(); +} + +template +static std::string join(char delimiter, const T & input) +{ + return join(input); +} + +template +static std::string join(char delimiter, const T & input, const Args & ... args) +{ + std::ostringstream ostream; + ostream << input << delimiter << join(delimiter, args...); + return ostream.str(); +} + +template +static bool get_value( + const MACsecOrch::TaskArgs & ta, + const std::string & field, + T & value) +{ + SWSS_LOG_ENTER(); + + std::string target_field = field; + std::transform( + target_field.begin(), + target_field.end(), + target_field.begin(), + ::tolower); + auto itr = std::find_if( + ta.begin(), + ta.end(), + [&](const MACsecOrch::TaskArgs::value_type & entry) + { + std::string field = fvField(entry); + std::transform( + field.begin(), + field.end(), + field.begin(), + ::tolower); + return field == target_field; + }); + if (itr != ta.end()) + { + std::istringstream istream(fvValue(*itr)); + istream >> value; + SWSS_LOG_DEBUG( + "Set field '%s' as '%s'", + field.c_str(), + fvValue(*itr).c_str()); + return true; + } + SWSS_LOG_WARN("Cannot find field : %s", field.c_str()); + return false; +} + +static std::istringstream& operator>>( + std::istringstream &istream, + bool & b) +{ + std::string buffer = istream.str(); + std::transform( + buffer.begin(), + buffer.end(), + buffer.begin(), + ::tolower); + if (buffer == "true" || buffer == "1") + { + b = true; + } + else if (buffer == "false" || buffer == "0") + { + b = false; + } + else + { + throw std::invalid_argument("Invalid bool string : " + buffer); + } + + return istream; +} + +static bool hex_to_binary( + const std::string & hex_str, + std::uint8_t * buffer, + size_t buffer_length) +{ + size_t buffer_cur = 0; + size_t hex_cur = 0; + while (buffer_cur < buffer_length) + { + if ((hex_cur + 1) >= hex_str.length()) + { + return false; + } + std::stringstream stream; + stream << std::hex; + stream << hex_str[hex_cur++]; + stream << hex_str[hex_cur++]; + stream >> buffer[buffer_cur++]; + } + return hex_cur == hex_str.length(); +} + +struct MACsecSAK +{ + sai_macsec_sak_t m_sak; + bool m_sak_256_enable; +}; + +static std::istringstream& operator>>( + std::istringstream &istream, + MACsecSAK & sak) +{ + SWSS_LOG_ENTER(); + const std::string & buffer = istream.str(); + bool convert_done = false; + if (buffer.length() == sizeof(sak.m_sak)) + { + sak.m_sak_256_enable = false; + convert_done = hex_to_binary(buffer, &sak.m_sak[8], sizeof(sak.m_sak) / 2); + } + else if (buffer.length() == sizeof(sak.m_sak) * 2) + { + sak.m_sak_256_enable = true; + convert_done = hex_to_binary(buffer, sak.m_sak, sizeof(sak.m_sak)); + } + if (!convert_done) + { + throw std::invalid_argument("Invalid SAK : " + buffer); + } + return istream; +} + +struct MACsecSalt +{ + sai_macsec_salt_t m_salt; +}; + +static std::istringstream& operator>>( + std::istringstream &istream, + MACsecSalt & salt) +{ + SWSS_LOG_ENTER(); + const std::string & buffer = istream.str(); + + if ( + (buffer.length() != sizeof(salt.m_salt) * 2) + || (!hex_to_binary(buffer, salt.m_salt, sizeof(salt.m_salt)))) + { + throw std::invalid_argument("Invalid SALT : " + buffer); + } + return istream; +} + +struct MACsecAuthKey +{ + sai_macsec_auth_key_t m_auth_key; +}; + +static std::istringstream& operator>>( + std::istringstream &istream, + MACsecAuthKey & auth_key) +{ + SWSS_LOG_ENTER(); + const std::string & buffer = istream.str(); + + if ( + (buffer.length() != sizeof(auth_key.m_auth_key) * 2) + || (!hex_to_binary(buffer, auth_key.m_auth_key, sizeof(auth_key.m_auth_key)))) + { + throw std::invalid_argument("Invalid Auth Key : " + buffer); + } + return istream; +} + +MACsecOrch::MACsecOrch( + DBConnector *appDb, + DBConnector *state_db, + const std::vector &tables, + PortsOrch * port_orch) : + Orch(appDb, tables), + m_port_orch(port_orch), + m_state_macsec_port(state_db, STATE_MACSEC_PORT_TABLE_NAME), + m_state_macsec_egress_sc(state_db, STATE_MACSEC_EGRESS_SC_TABLE_NAME), + m_state_macsec_ingress_sc(state_db, STATE_MACSEC_INGRESS_SC_TABLE_NAME), + m_state_macsec_egress_sa(state_db, STATE_MACSEC_EGRESS_SA_TABLE_NAME), + m_state_macsec_ingress_sa(state_db, STATE_MACSEC_INGRESS_SA_TABLE_NAME), + m_gearbox_table(appDb, "_GEARBOX_TABLE"), + m_gearbox_enabled(false) +{ +} + +MACsecOrch::~MACsecOrch() +{ + while (!m_macsec_ports.empty()) + { + auto port = m_macsec_ports.begin(); + const TaskArgs temp; + disableMACsecPort(port->first, temp); + } +} + +void MACsecOrch::doTask(Consumer &consumer) +{ + SWSS_LOG_ENTER(); + + if (!m_gearbox_enabled) + { + if (!initGearbox()) + { + SWSS_LOG_WARN("Gearbox cannot be initialized."); + return; + } + } + + using TaskType = std::tuple; + using TaskFunc = task_process_status (MACsecOrch::*)( + const std::string &, + const TaskArgs &); + const static std::map TaskMap = { + { { APP_MACSEC_PORT_TABLE_NAME, SET_COMMAND }, + &MACsecOrch::enableMACsecPort }, + { { APP_MACSEC_PORT_TABLE_NAME, DEL_COMMAND }, + &MACsecOrch::disableMACsecPort }, + { { APP_MACSEC_EGRESS_SC_TABLE_NAME, SET_COMMAND }, + &MACsecOrch::updateEgressSC }, + { { APP_MACSEC_EGRESS_SC_TABLE_NAME, DEL_COMMAND }, + &MACsecOrch::deleteEgressSC }, + { { APP_MACSEC_INGRESS_SC_TABLE_NAME, SET_COMMAND }, + &MACsecOrch::updateIngressSC }, + { { APP_MACSEC_INGRESS_SC_TABLE_NAME, DEL_COMMAND }, + &MACsecOrch::deleteIngressSC }, + { { APP_MACSEC_EGRESS_SA_TABLE_NAME, SET_COMMAND }, + &MACsecOrch::updateEgressSA }, + { { APP_MACSEC_EGRESS_SA_TABLE_NAME, DEL_COMMAND }, + &MACsecOrch::deleteEgressSA }, + { { APP_MACSEC_INGRESS_SA_TABLE_NAME, SET_COMMAND }, + &MACsecOrch::updateIngressSA }, + { { APP_MACSEC_INGRESS_SA_TABLE_NAME, DEL_COMMAND }, + &MACsecOrch::deleteIngressSA }, + }; + + 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); + } + } +} + +task_process_status MACsecOrch::enableMACsecPort( + const std::string & port_name, + const TaskArgs & port_attr) +{ + SWSS_LOG_ENTER(); + + Port port; + if (!m_port_orch->getPort(port_name, port)) + { + SWSS_LOG_WARN("Port %s cannot be found.", port_name.c_str()); + return task_failed; + } + sai_object_id_t switch_id = 0; + if (!getGearboxSwitchId(port, switch_id)) + { + SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); + return task_failed; + } + auto macsec_obj = initMACsecObject(switch_id); + if (macsec_obj == m_macsec_objs.end()) + { + SWSS_LOG_WARN("Cannot init MACsec at the port %s.", port_name.c_str()); + return task_failed; + } + auto macsec_port = createMACsecPort(port, switch_id); + if (macsec_port == nullptr) + { + SWSS_LOG_WARN("Cannot init MACsec port at the port %s.", port_name.c_str()); + return task_failed; + } + + // Set flex counter + + macsec_port->m_enable_encrypt = true; + get_value(port_attr, "enable_encrypt", macsec_port->m_enable_encrypt); + + macsec_obj->second.m_ports[port_name] = macsec_port; + + std::vector fvVector; + fvVector.emplace_back("state", "ok"); + m_state_macsec_port.set(port_name, fvVector); + + return task_success; +} + +task_process_status MACsecOrch::disableMACsecPort( + const std::string & port_name, + const TaskArgs & port_attr) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t switch_id = 0; + if (!getGearboxSwitchId(port_name, switch_id)) + { + SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); + return task_failed; + } + + task_process_status result = task_success; + if (!deleteMACsecPort(port_name)) + { + SWSS_LOG_WARN("Cannot delete macsec port at the port %s.", port_name.c_str()); + result = task_failed; + } + + // Delete flex counter + + auto macsec_obj = m_macsec_objs.find(switch_id); + if (macsec_obj != m_macsec_objs.end()) + { + macsec_obj->second.m_ports.erase(port_name); + // All ports on this macsec object have been deleted. + if (macsec_obj->second.m_ports.empty()) + { + if (!deinitMACsecObject(macsec_obj)) + { + SWSS_LOG_WARN("Cannot deinit macsec at the port %s.", port_name.c_str()); + result = task_failed; + } + } + } + + m_state_macsec_port.del(port_name); + + return result; +} + +task_process_status MACsecOrch::updateEgressSC( + const std::string & port_sci, + const TaskArgs & sc_attr) +{ + SWSS_LOG_ENTER(); + return updateMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_EGRESS); +} + +task_process_status MACsecOrch::deleteEgressSC( + const std::string & port_sci, + const TaskArgs & sc_attr) +{ + SWSS_LOG_ENTER(); + return deleteMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_EGRESS); +} + +task_process_status MACsecOrch::updateIngressSC( + const std::string & port_sci, + const TaskArgs & sc_attr) +{ + SWSS_LOG_ENTER(); + return updateMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_INGRESS); +} + +task_process_status MACsecOrch::deleteIngressSC( + const std::string & port_sci, + const TaskArgs & sc_attr) +{ + SWSS_LOG_ENTER(); + return deleteMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_INGRESS); +} + +task_process_status MACsecOrch::updateEgressSA( + const std::string & port_sci_an, + const TaskArgs & sa_attr) +{ + SWSS_LOG_ENTER(); + std::string port_name; + sai_uint64_t sci; + sai_uint8_t an; + if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) + { + SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); + return task_failed; + } + auto port = m_macsec_ports.find(port_name); + if (port == m_macsec_ports.end()) + { + SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); + return task_need_retry; + } + auto sc = port->second->m_egress_scs.find(sci); + if (sc == port->second->m_egress_scs.end()) + { + SWSS_LOG_INFO("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); + return task_need_retry; + } + if (sc->second.m_encoding_an == an) + { + return createMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_EGRESS); + } + return task_need_retry; +} + +task_process_status MACsecOrch::deleteEgressSA( + const std::string & port_sci_an, + const TaskArgs & sa_attr) +{ + SWSS_LOG_ENTER(); + return deleteMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_EGRESS);; +} + +task_process_status MACsecOrch::updateIngressSA( + const std::string & port_sci_an, + const TaskArgs & sa_attr) +{ + SWSS_LOG_ENTER(); + bool active = false; + if (!get_value(sa_attr, "active", active)) + { + SWSS_LOG_WARN("Active filed isn't existed at the SA %s.", port_sci_an.c_str()); + return task_failed; + } + if (active) + { + return createMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_INGRESS); + } + else + { + return deleteMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_INGRESS); + } + + return task_success; +} + +task_process_status MACsecOrch::deleteIngressSA( + const std::string & port_sci_an, + const TaskArgs & sa_attr) +{ + SWSS_LOG_ENTER(); + return task_success; +} + +bool MACsecOrch::initGearbox() +{ + SWSS_LOG_ENTER(); + + GearboxUtils gearbox; + m_gearbox_enabled = gearbox.isGearboxEnabled(&m_gearbox_table); + if (m_gearbox_enabled) + { + m_gearbox_phy_map = gearbox.loadPhyMap(&m_gearbox_table); + m_gearbox_interface_map = gearbox.loadInterfaceMap(&m_gearbox_table); + + SWSS_LOG_NOTICE("BOX: m_gearbox_phy_map size = %d.", static_cast(m_gearbox_phy_map.size())); + SWSS_LOG_NOTICE("BOX: m_gearbox_interface_map size = %d.", static_cast(m_gearbox_interface_map.size())); + } + return m_gearbox_enabled; +} + +bool MACsecOrch::getGearboxSwitchId(const std::string & port_name, sai_object_id_t & switch_id) const +{ + SWSS_LOG_ENTER(); + + Port port; + if (!m_port_orch->getPort(port_name, port)) + { + SWSS_LOG_WARN("Port %s cannot be found.", port_name.c_str()); + return false; + } + return getGearboxSwitchId(port, switch_id); +} + +bool MACsecOrch::getGearboxSwitchId(const Port & port, sai_object_id_t & switch_id) const +{ + SWSS_LOG_ENTER(); + + auto phy_id = m_gearbox_interface_map.find(port.m_index); + if (phy_id == m_gearbox_interface_map.end()) + { + SWSS_LOG_INFO("The port %s doesn't bind to any gearbox.", port.m_alias.c_str()); + return false; + } + auto phy_oid_str = m_gearbox_phy_map.find(phy_id->second.phy_id); + if (phy_oid_str == m_gearbox_phy_map.end()) + { + SWSS_LOG_ERROR("Cannot find phy object (%d).", phy_id->second.phy_id); + return false; + } + if (phy_oid_str->second.phy_oid.size() == 0) + { + SWSS_LOG_ERROR("BOX: Gearbox PHY phy_id:%d has an invalid phy_oid", phy_id->second.phy_id); + return false; + } + sai_deserialize_object_id(phy_oid_str->second.phy_oid, switch_id); + return true; +} + +map::iterator MACsecOrch::initMACsecObject(sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + auto macsec_obj = m_macsec_objs.emplace(switch_id, MACsecObject()); + if (!macsec_obj.second) + { + SWSS_LOG_INFO("The MACsec has been initialized at the switch %lu", switch_id); + return macsec_obj.first; + } + + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.value.s32 = SAI_MACSEC_DIRECTION_EGRESS; + attrs.push_back(attr); + if(sai_macsec_api->create_macsec( + &macsec_obj.first->second.m_egress_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot initialize MACsec egress object at the switch %lu", switch_id); + m_macsec_objs.erase(macsec_obj.first); + return m_macsec_objs.end(); + } + + attrs.clear(); + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.value.s32 = SAI_MACSEC_DIRECTION_INGRESS; + attrs.push_back(attr); + if(sai_macsec_api->create_macsec( + &macsec_obj.first->second.m_ingress_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot initialize MACsec ingress object at the switch %lu", switch_id); + sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_egress_id); + m_macsec_objs.erase(macsec_obj.first); + return m_macsec_objs.end(); + } + + return macsec_obj.first; +} + +bool MACsecOrch::deinitMACsecObject(sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + auto macsec_obj = m_macsec_objs.find(switch_id); + if (macsec_obj == m_macsec_objs.end()) + { + SWSS_LOG_INFO("The MACsec wasn't initialized at the switch %lu", switch_id); + return true; + } + return deinitMACsecObject(macsec_obj); +} + +bool MACsecOrch::deinitMACsecObject(map::iterator macsec_obj) +{ + SWSS_LOG_ENTER(); + + bool result = true; + + if(sai_macsec_api->remove_macsec( + macsec_obj->second.m_egress_id) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot deinitialize MACsec egress object at the switch %lu", macsec_obj->first); + result &= false; + } + + if(sai_macsec_api->remove_macsec( + macsec_obj->second.m_ingress_id) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot deinitialize MACsec ingress object at the switch %lu", macsec_obj->first); + result &= false; + } + + m_macsec_objs.erase(macsec_obj); + return result; +} + +std::shared_ptr MACsecOrch::createMACsecPort( + const Port & port, + sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + auto macsec_port = m_macsec_ports.emplace(port.m_alias, std::make_shared()); + if (!macsec_port.second) + { + SWSS_LOG_INFO("The MACsec port has been initialized at the port %s", port.m_alias.c_str()); + return macsec_port.first->second; + } + + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.value.s32 = SAI_MACSEC_DIRECTION_EGRESS; + attrs.push_back(attr); + attr.id = SAI_MACSEC_PORT_ATTR_PORT_ID; + attr.value.oid = port.m_line_port_id; + attrs.push_back(attr); + if (sai_macsec_api->create_macsec_port( + &macsec_port.first->second->m_egress_port_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot create MACsec egress port at the port %s", port.m_alias.c_str()); + m_macsec_ports.erase(macsec_port.first); + return nullptr; + } + + attrs.clear(); + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.value.s32 = SAI_MACSEC_DIRECTION_INGRESS; + attrs.push_back(attr); + attr.id = SAI_MACSEC_PORT_ATTR_PORT_ID; + attr.value.oid = port.m_line_port_id; + attrs.push_back(attr); + if (sai_macsec_api->create_macsec_port( + &macsec_port.first->second->m_ingress_port_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot create MACsec ingress port at the port %s", port.m_alias.c_str()); + sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); + m_macsec_ports.erase(macsec_port.first); + return nullptr; + } + + attrs.clear(); + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.value.s32 = SAI_MACSEC_DIRECTION_EGRESS; + attrs.push_back(attr); + if (sai_macsec_api->create_macsec_flow( + &macsec_port.first->second->m_egress_flow_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot create MACsec egress flow at the port %s", port.m_alias.c_str()); + sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); + sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_ingress_port_id); + m_macsec_ports.erase(macsec_port.first); + return nullptr; + } + + attrs.clear(); + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.value.s32 = SAI_MACSEC_DIRECTION_INGRESS; + attrs.push_back(attr); + if (sai_macsec_api->create_macsec_flow( + &macsec_port.first->second->m_ingress_flow_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot create MACsec ingress flow at the port %s", port.m_alias.c_str()); + sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); + sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_ingress_port_id); + sai_macsec_api->remove_macsec_flow(macsec_port.first->second->m_ingress_flow_id); + m_macsec_ports.erase(macsec_port.first); + return nullptr; + } + + return macsec_port.first->second; +} + +bool MACsecOrch::deleteMACsecPort(const std::string & port_name) +{ + SWSS_LOG_ENTER(); + + auto macsec_port = m_macsec_ports.find(port_name); + if (macsec_port == m_macsec_ports.end()) + { + SWSS_LOG_INFO("The MACsec port wasn't initialized at the port %s", port_name.c_str()); + return true; + } + + bool result = true; + + if(sai_macsec_api->remove_macsec_port( + macsec_port->second->m_egress_port_id) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot delete MACsec egress port at the port %s", port_name.c_str()); + result &= false; + } + + if(sai_macsec_api->remove_macsec_port( + macsec_port->second->m_ingress_port_id) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot delete MACsec ingress port at the port %s", port_name.c_str()); + result &= false; + } + + if(sai_macsec_api->remove_macsec_flow( + macsec_port->second->m_egress_flow_id) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot delete MACsec egress flow at the port %s", port_name.c_str()); + result &= false; + } + + if(sai_macsec_api->remove_macsec_flow( + macsec_port->second->m_ingress_flow_id) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Cannot delete MACsec ingress flow at the port %s", port_name.c_str()); + result &= false; + } + + m_macsec_ports.erase(macsec_port); + return true; +} + +task_process_status MACsecOrch::updateMACsecSC( + const std::string & port_sci, + const TaskArgs & sc_attr, + sai_int32_t direction) +{ + SWSS_LOG_ENTER(); + + std::string port_name; + sai_uint64_t sci; + if (!split(port_sci, ':', port_name, sci)) + { + SWSS_LOG_WARN("The key %s isn't correct.", port_sci.c_str()); + return task_failed; + } + + auto port = m_macsec_ports.find(port_name); + if (port == m_macsec_ports.end()) + { + SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); + return task_need_retry; + } + sai_object_id_t switch_id = 0; + if (!getGearboxSwitchId(port_name, switch_id)) + { + SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); + return task_failed; + } + + auto & scs = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_scs + : + port->second->m_ingress_scs; + auto sc = scs.emplace(sci, MACsecSC()); + // If SC has been created + if (!sc.second) + { + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + if (!get_value(sc_attr, "encoding_an", sc.first->second.m_encoding_an)) + { + return task_failed; + } + } + return task_success; + } + sai_uint32_t ssci; + sc.first->second.m_xpn64_enable = false; + if (get_value(sc_attr, "ssci", ssci)) + { + sc.first->second.m_xpn64_enable = true; + } + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + get_value(sc_attr, "encoding_an", sc.first->second.m_encoding_an); + } + sai_object_id_t flow_id= + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_flow_id + : + port->second->m_ingress_flow_id; + if (!createMACsecSC( + sc.first->second.m_sc_id, + switch_id, + direction, + flow_id, + sci, + ssci, + sc.first->second.m_xpn64_enable)) + { + SWSS_LOG_WARN("Create MACsec SC %s fail.", port_sci.c_str()); + return task_failed; + } + + SWSS_LOG_NOTICE("MACsec SC %s is created.", port_sci.c_str()); + + std::vector fvVector; + fvVector.emplace_back("state", "ok"); + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + m_state_macsec_egress_sc.set(join('|', port_name, sci), fvVector); + } + else + { + m_state_macsec_ingress_sc.set(join('|', port_name, sci), fvVector); + } + + return task_success; +} + +task_process_status MACsecOrch::deleteMACsecSC( + const std::string & port_sci, + const TaskArgs & sc_attr, + sai_int32_t direction) +{ + SWSS_LOG_ENTER(); + + std::string port_name; + sai_uint64_t sci; + if (!split(port_sci, ':', port_name, sci)) + { + SWSS_LOG_WARN("The key %s isn't correct.", port_sci.c_str()); + return task_failed; + } + + auto port = m_macsec_ports.find(port_name); + if (port == m_macsec_ports.end()) + { + SWSS_LOG_WARN("The MACsec port hasn't been created at the port %s.", port_name.c_str()); + return task_failed; + } + + auto & scs = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_scs + : + port->second->m_ingress_scs; + auto sc = scs.find(sci); + if (sc == scs.end()) + { + SWSS_LOG_WARN("The MACsec SC %s wasn't created", port_sci.c_str()); + return task_failed; + } + auto ret = task_success; + if (!deleteMACsecSC(sc->second.m_sc_id)) + { + SWSS_LOG_WARN("The MACsec SC %s cannot be deleted", port_sci.c_str()); + ret = task_failed; + } + port->second->m_egress_scs.erase(sc); + SWSS_LOG_NOTICE("MACsec SC %s is deleted.", port_sci.c_str()); + + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + m_state_macsec_egress_sc.del(join('|', port_name, sci)); + } + else + { + m_state_macsec_ingress_sc.del(join('|', port_name, sci)); + } + + return ret; +} + +bool MACsecOrch::createMACsecSC( + sai_object_id_t & sc_id, + sai_object_id_t switch_id, + sai_int32_t direction, + sai_object_id_t flow_id, + sai_uint64_t sci, + sai_uint32_t ssci, + bool xpn64_enable) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_DIRECTION; + attr.value.s32 = direction; + attrs.push_back(attr); + attr.id = SAI_MACSEC_SC_ATTR_FLOW_ID; + attr.value.oid = flow_id; + attrs.push_back(attr); + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_SCI; + attr.value.u64 = sci; + attrs.push_back(attr); + if (xpn64_enable) + { + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_SSCI; + attr.value.u32 = ssci; + attrs.push_back(attr); + } + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_XPN64_ENABLE; + attr.value.booldata = xpn64_enable; + attrs.push_back(attr); + + if (sai_macsec_api->create_macsec_sc( + &sc_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { + SWSS_LOG_WARN("Cannot create MACsec egress SC %lu", sci); + return false; + } + return true; +} + +bool MACsecOrch::deleteMACsecSC(sai_object_id_t sc_id) +{ + SWSS_LOG_ENTER(); + + if (sai_macsec_api->remove_macsec_sc( + sc_id) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} + +task_process_status MACsecOrch::createMACsecSA( + const std::string & port_sci_an, + const TaskArgs & sa_attr, + sai_int32_t direction) +{ + SWSS_LOG_ENTER(); + + std::string port_name; + sai_uint64_t sci; + sai_uint8_t an; + if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) + { + SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); + return task_failed; + } + + auto port = m_macsec_ports.find(port_name); + if (port == m_macsec_ports.end()) + { + SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); + return task_need_retry; + } + sai_object_id_t switch_id = 0; + if (!getGearboxSwitchId(port_name, switch_id)) + { + SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); + return task_failed; + } + + auto & scs = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_scs + : + port->second->m_ingress_scs; + auto sc = scs.find(sci); + if (sc == scs.end()) + { + SWSS_LOG_INFO("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); + return task_need_retry; + } + + MACsecSAK sak; + MACsecSalt salt; + MACsecAuthKey auth_key; + try + { + if (!get_value(sa_attr, "sak", sak)) + { + SWSS_LOG_WARN("The SAK isn't existed at SA %s", port_sci_an.c_str()); + return task_failed; + } + if (sc->second.m_xpn64_enable) + { + if (!get_value(sa_attr, "salt", salt)) + { + SWSS_LOG_WARN("The salt isn't existed at SA %s", port_sci_an.c_str()); + return task_failed; + } + } + if (!get_value(sa_attr, "auth_key", auth_key)) + { + SWSS_LOG_WARN("The auth key isn't existed at SA %s", port_sci_an.c_str()); + return task_failed; + } + } + catch(std::invalid_argument & e) + { + SWSS_LOG_WARN("Invalid argument : %s", e.what()); + return task_failed; + } + sai_uint64_t pn; + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + if (!get_value(sa_attr, "init_pn", pn)) + { + SWSS_LOG_WARN("The init pn isn't existed at SA %s", port_sci_an.c_str()); + return task_failed; + } + } + else + { + if (!get_value(sa_attr, "lowest_acceptable_pn", pn)) + { + SWSS_LOG_WARN("The init pn isn't existed at SA %s", port_sci_an.c_str()); + return task_failed; + } + } + + if (!createMACsecSA( + sc->second.m_sa_ids[an], + switch_id, + direction, + sc->second.m_sc_id, + an, + port->second->m_enable_encrypt, + sak.m_sak_256_enable, + sak.m_sak, + sc->second.m_xpn64_enable, + salt.m_salt, + auth_key.m_auth_key, + pn)) + { + SWSS_LOG_WARN("Cannot create the SA %s", port_sci_an.c_str()); + return task_failed; + } + + std::vector fvVector; + fvVector.emplace_back("state", "ok"); + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + m_state_macsec_egress_sa.set(join('|', port_name, sci, an), fvVector); + } + else + { + m_state_macsec_ingress_sa.set(join('|', port_name, sci, an), fvVector); + } + + SWSS_LOG_NOTICE("MACsec SA %s is created.", port_sci_an.c_str()); + return task_success; +} + +task_process_status MACsecOrch::deleteMACsecSA( + const std::string & port_sci_an, + const TaskArgs & sa_attr, + sai_int32_t direction) +{ + SWSS_LOG_ENTER(); + + std::string port_name; + sai_uint64_t sci; + sai_uint8_t an; + if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) + { + SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); + return task_failed; + } + + auto port = m_macsec_ports.find(port_name); + if (port == m_macsec_ports.end()) + { + SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); + return task_need_retry; + } + + auto & scs = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_scs + : + port->second->m_ingress_scs; + auto sc = scs.find(sci); + if (sc == scs.end()) + { + SWSS_LOG_INFO("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); + return task_need_retry; + } + + if (sc->second.m_sa_ids[an] == 0) + { + SWSS_LOG_WARN("The MACsec SA %s hasn't been created.", port_sci_an.c_str()); + return task_failed; + } + if (!deleteMACsecSA(sc->second.m_sa_ids[an])) + { + SWSS_LOG_WARN("Cannot delete the MACsec SA %s.", port_sci_an.c_str()); + } + + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + m_state_macsec_egress_sa.del(join('|', port_name, sci, an)); + } + else + { + m_state_macsec_ingress_sa.del(join('|', port_name, sci, an)); + } + + SWSS_LOG_NOTICE("MACsec SA %s is deleted.", port_sci_an.c_str()); + return task_success; +} + +bool MACsecOrch::createMACsecSA( + sai_object_id_t & sa_id, + sai_object_id_t switch_id, + sai_int32_t direction, + sai_object_id_t sc_id, + sai_uint8_t an, + bool encryption_enable, + bool sak_256_bit, + sai_macsec_sak_t sak, + bool xpn64_enable, + sai_macsec_salt_t salt, + sai_macsec_auth_key_t auth_key, + sai_uint64_t pn + ) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.value.s32 = direction; + attrs.push_back(attr); + + attr.id = SAI_MACSEC_SA_ATTR_SC_ID; + attr.value.oid = sc_id; + attrs.push_back(attr); + + attr.id = SAI_MACSEC_SA_ATTR_AN; + attr.value.u8 = an; + attrs.push_back(attr); + + attr.id = SAI_MACSEC_SA_ATTR_ENCRYPTION_ENABLE; + attr.value.u8 = encryption_enable; + attrs.push_back(attr); + + attr.id = SAI_MACSEC_SA_ATTR_SAK_256_BITS; + attr.value.u8 = sak_256_bit; + attrs.push_back(attr); + + attr.id = SAI_MACSEC_SA_ATTR_SAK; + std::copy(sak, sak + sizeof(attr.value.macsecsak), attr.value.macsecsak); + attrs.push_back(attr); + + if (xpn64_enable) + { + attr.id = SAI_MACSEC_SA_ATTR_SALT; + std::copy(salt, salt + sizeof(attr.value.macsecsalt), attr.value.macsecsalt); + attrs.push_back(attr); + } + + attr.id = SAI_MACSEC_SA_ATTR_AUTH_KEY; + std::copy(auth_key, auth_key + sizeof(attr.value.macsecauthkey), attr.value.macsecauthkey); + attrs.push_back(attr); + + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + attr.id = SAI_MACSEC_SA_ATTR_XPN; + attr.value.u64 = pn; + attrs.push_back(attr); + } + else + { + attr.id = SAI_MACSEC_SA_ATTR_MINIMUM_XPN; + attr.value.u64 = pn; + attrs.push_back(attr); + } + + if (sai_macsec_api->create_macsec_sa( + &sa_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + return false; + } + return true; +} + +bool MACsecOrch::deleteMACsecSA(sai_object_id_t sa_id) +{ + SWSS_LOG_ENTER(); + if (sai_macsec_api->remove_macsec_sa( + sa_id) != SAI_STATUS_SUCCESS) + { + return false; + } + return true; +} diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h new file mode 100644 index 0000000000..eeb2423852 --- /dev/null +++ b/orchagent/macsecorch.h @@ -0,0 +1,158 @@ +#ifndef SWSS_MACSECSORCH_H +#define SWSS_MACSECSORCH_H + +// The following definitions should be moved to schema.h + +#define APP_MACSEC_PORT_TABLE_NAME "MACSEC_PORT_TABLE" +#define APP_MACSEC_EGRESS_SC_TABLE_NAME "MACSEC_EGRESS_SC_TABLE" +#define APP_MACSEC_INGRESS_SC_TABLE_NAME "MACSEC_INGRESS_SC_TABLE" +#define APP_MACSEC_EGRESS_SA_TABLE_NAME "MACSEC_EGRESS_SA_TABLE" +#define APP_MACSEC_INGRESS_SA_TABLE_NAME "MACSEC_INGRESS_SA_TABLE" + +#define STATE_MACSEC_PORT_TABLE_NAME "MACSEC_PORT_TABLE" +#define STATE_MACSEC_EGRESS_SC_TABLE_NAME "MACSEC_EGRESS_SC_TABLE" +#define STATE_MACSEC_INGRESS_SC_TABLE_NAME "MACSEC_INGRESS_SC_TABLE" +#define STATE_MACSEC_EGRESS_SA_TABLE_NAME "MACSEC_EGRESS_SA_TABLE" +#define STATE_MACSEC_INGRESS_SA_TABLE_NAME "MACSEC_INGRESS_SA_TABLE" + +#define COUNTERS_MACSEC_NAME_MAP "COUNTERS_MACSEC_NAME_MAP" +#define COUNTERS_MACSEC_TABLE "COUNTERS_MACSEC" + +// End define + +#include "orch.h" + +#include "portsorch.h" + +#include + +#include +#include +#include + +using namespace swss; + +// AN is a 2 bit number, it can only be 0, 1, 2 or 3 +#define MAX_SA_NUMBER (3) + +class MACsecOrch : public Orch +{ +public: + MACsecOrch(DBConnector *app_db, DBConnector *state_db, const std::vector &tables, PortsOrch * port_orch); + ~MACsecOrch(); + +private: + void doTask(Consumer &consumer); + +public: + using TaskArgs = std::vector; + +private: + + task_process_status enableMACsecPort(const std::string & port_name, const TaskArgs & port_attr); + task_process_status disableMACsecPort(const std::string & port_name, const TaskArgs & port_attr); + task_process_status updateEgressSC(const std::string & port_sci, const TaskArgs & sc_attr); + task_process_status deleteEgressSC(const std::string & port_sci, const TaskArgs & sc_attr); + task_process_status updateIngressSC(const std::string & port_sci, const TaskArgs & sc_attr); + task_process_status deleteIngressSC(const std::string & port_sci, const TaskArgs & sc_attr); + task_process_status updateEgressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); + task_process_status deleteEgressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); + task_process_status updateIngressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); + task_process_status deleteIngressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); + + PortsOrch * m_port_orch; + + Table m_state_macsec_port; + Table m_state_macsec_egress_sc; + Table m_state_macsec_ingress_sc; + Table m_state_macsec_egress_sa; + Table m_state_macsec_ingress_sa; + + Table m_gearbox_table; + bool m_gearbox_enabled; + map m_gearbox_phy_map; + map m_gearbox_interface_map; + struct MACsecSC + { + sai_uint8_t m_encoding_an; + bool m_xpn64_enable; + sai_object_id_t m_sc_id; + sai_object_id_t m_sa_ids[MAX_SA_NUMBER + 1]; + }; + struct MACsecPort + { + sai_object_id_t m_egress_port_id; + sai_object_id_t m_ingress_port_id; + sai_object_id_t m_egress_flow_id; + sai_object_id_t m_ingress_flow_id; + std::map m_egress_scs; + std::map m_ingress_scs; + bool m_enable_encrypt; + }; + struct MACsecObject + { + sai_object_id_t m_egress_id; + sai_object_id_t m_ingress_id; + map > m_ports; + }; + map m_macsec_objs; + map > m_macsec_ports; + + bool initGearbox(); + bool getGearboxSwitchId(const Port & port, sai_object_id_t & switch_id) const; + bool getGearboxSwitchId(const std::string & port_name, sai_object_id_t & switch_id) const; + + map::iterator initMACsecObject(sai_object_id_t switch_id); + bool deinitMACsecObject(map::iterator switch_id); + bool deinitMACsecObject(sai_object_id_t switch_id); + + std::shared_ptr createMACsecPort(const Port & port, sai_object_id_t switch_id); + bool deleteMACsecPort(const std::string & port_name); + + // bool createACL; + // bool deleteACL; + + task_process_status updateMACsecSC( + const std::string & port_sci, + const TaskArgs & sc_attr, + sai_int32_t direction); + task_process_status deleteMACsecSC( + const std::string & port_sci, + const TaskArgs & sc_attr, + sai_int32_t direction); + bool createMACsecSC( + sai_object_id_t & sc_id, + sai_object_id_t switch_id, + sai_int32_t direction, + sai_object_id_t flow_id, + sai_uint64_t sci, + sai_uint32_t ssci, + bool xpn64_enable); + bool deleteMACsecSC(sai_object_id_t sc_id); + + task_process_status createMACsecSA( + const std::string & port_sci_an, + const TaskArgs & sa_attr, + sai_int32_t direction); + task_process_status deleteMACsecSA( + const std::string & port_sci_an, + const TaskArgs & sa_attr, + sai_int32_t direction); + bool createMACsecSA( + sai_object_id_t & sa_id, + sai_object_id_t switch_id, + sai_int32_t direction, + sai_object_id_t sc_id, + sai_uint8_t an, + bool encryption_enable, + bool sak_256_bit, + sai_macsec_sak_t sak, + bool xpn64_enable, + sai_macsec_salt_t salt, + sai_macsec_auth_key_t auth_key, + sai_uint64_t pn + ); + bool deleteMACsecSA(sai_object_id_t sa_id); +}; + +#endif diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 99fbc0a7f6..d8398cc6d3 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -36,6 +36,7 @@ BufferOrch *gBufferOrch; SwitchOrch *gSwitchOrch; Directory gDirectory; NatOrch *gNatOrch; +MACsecOrch *gMacsecOrch; bool gIsNatSupported = false; @@ -228,6 +229,16 @@ bool OrchDaemon::init() gNatOrch = new NatOrch(m_applDb, m_stateDb, nat_tables, gRouteOrch, gNeighOrch); + vector macsec_app_tables = { + APP_MACSEC_PORT_TABLE_NAME, + APP_MACSEC_EGRESS_SC_TABLE_NAME, + APP_MACSEC_INGRESS_SC_TABLE_NAME, + APP_MACSEC_EGRESS_SA_TABLE_NAME, + APP_MACSEC_INGRESS_SA_TABLE_NAME, + }; + + gMacsecOrch = new MACsecOrch(m_applDb, m_stateDb, macsec_app_tables, gPortsOrch); + /* * The order of the orch list is important for state restore of warm start and * the queued processing in m_toSync map after gPortsOrch->allPortsReady() is set. @@ -236,7 +247,7 @@ bool OrchDaemon::init() * when iterating ConsumerMap. This is ensured implicitly by the order of keys in ordered map. * For cases when Orch has to process tables in specific order, like PortsOrch during warm start, it has to override Orch::doTask() */ - m_orchList = { gSwitchOrch, gCrmOrch, gPortsOrch, gBufferOrch, gIntfsOrch, gNeighOrch, gRouteOrch, copp_orch, tunnel_decap_orch, qos_orch, wm_orch, policer_orch, sflow_orch, debug_counter_orch}; + m_orchList = { gSwitchOrch, gCrmOrch, gPortsOrch, gBufferOrch, gIntfsOrch, gNeighOrch, gRouteOrch, copp_orch, tunnel_decap_orch, qos_orch, wm_orch, policer_orch, sflow_orch, debug_counter_orch, gMacsecOrch}; bool initialize_dtel = false; if (platform == BFN_PLATFORM_SUBSTRING || platform == VS_PLATFORM_SUBSTRING) diff --git a/orchagent/orchdaemon.h b/orchagent/orchdaemon.h index 3094692df6..d3f3accb57 100644 --- a/orchagent/orchdaemon.h +++ b/orchagent/orchdaemon.h @@ -31,6 +31,7 @@ #include "debugcounterorch.h" #include "directory.h" #include "natorch.h" +#include "macsecorch.h" using namespace swss; diff --git a/orchagent/port.h b/orchagent/port.h index 74f805ddec..e0e945f131 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -114,6 +114,8 @@ class Port std::unordered_set m_ingress_acl_tables_uset; std::unordered_set m_egress_acl_tables_uset; + + sai_object_id_t m_line_port_id = 0; }; } diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 05b1156dbf..ce1e7705c4 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -4420,6 +4420,7 @@ bool PortsOrch::initGearboxPort(Port &port) port.m_alias.c_str(), port.m_port_id, port.m_index, status); return false; } + port.m_line_port_id = linePort; SWSS_LOG_NOTICE("BOX: Created Gearbox line-side port 0x%lx for alias:%s index:%d", linePort, port.m_alias.c_str(), port.m_index); diff --git a/orchagent/saihelper.cpp b/orchagent/saihelper.cpp index a776ca701d..c8f750acc8 100644 --- a/orchagent/saihelper.cpp +++ b/orchagent/saihelper.cpp @@ -51,6 +51,7 @@ sai_bmtor_api_t* sai_bmtor_api; sai_samplepacket_api_t* sai_samplepacket_api; sai_debug_counter_api_t* sai_debug_counter_api; sai_nat_api_t* sai_nat_api; +sai_macsec_api_t* sai_macsec_api; extern sai_object_id_t gSwitchId; extern bool gSairedisRecord; @@ -170,6 +171,7 @@ void initSaiApi() sai_api_query(SAI_API_SAMPLEPACKET, (void **)&sai_samplepacket_api); sai_api_query(SAI_API_DEBUG_COUNTER, (void **)&sai_debug_counter_api); sai_api_query(SAI_API_NAT, (void **)&sai_nat_api); + sai_api_query(SAI_API_MACSEC, (void **)&sai_macsec_api); sai_log_set(SAI_API_SWITCH, SAI_LOG_LEVEL_NOTICE); sai_log_set(SAI_API_BRIDGE, SAI_LOG_LEVEL_NOTICE); @@ -199,6 +201,7 @@ void initSaiApi() sai_log_set(SAI_API_SAMPLEPACKET, SAI_LOG_LEVEL_NOTICE); sai_log_set(SAI_API_DEBUG_COUNTER, SAI_LOG_LEVEL_NOTICE); sai_log_set((sai_api_t)SAI_API_NAT, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_NAT, SAI_LOG_LEVEL_NOTICE); } void initSaiRedis(const string &record_location) From 8023b21920e921097d6ee4b83168156284250b27 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Wed, 2 Sep 2020 10:57:13 +0800 Subject: [PATCH 02/31] Add flex counter and ACL table Signed-off-by: Ze Gan --- .../flex_counter/flex_counter_manager.cpp | 3 +- orchagent/flex_counter/flex_counter_manager.h | 3 +- orchagent/macsecorch.cpp | 669 ++++++++++++++++-- orchagent/macsecorch.h | 89 ++- 4 files changed, 692 insertions(+), 72 deletions(-) diff --git a/orchagent/flex_counter/flex_counter_manager.cpp b/orchagent/flex_counter/flex_counter_manager.cpp index 000ead1882..4df2c7a0ed 100644 --- a/orchagent/flex_counter/flex_counter_manager.cpp +++ b/orchagent/flex_counter/flex_counter_manager.cpp @@ -35,7 +35,8 @@ const unordered_map FlexCounterManager::counter_id_field_lo { CounterType::PORT_DEBUG, PORT_DEBUG_COUNTER_ID_LIST }, { CounterType::SWITCH_DEBUG, SWITCH_DEBUG_COUNTER_ID_LIST }, { CounterType::PORT, PORT_COUNTER_ID_LIST }, - { CounterType::QUEUE, QUEUE_COUNTER_ID_LIST } + { CounterType::QUEUE, QUEUE_COUNTER_ID_LIST }, + { CounterType::MACSEC, "MACSEC_COUNTER_ID_LIST" }, }; FlexCounterManager::FlexCounterManager( diff --git a/orchagent/flex_counter/flex_counter_manager.h b/orchagent/flex_counter/flex_counter_manager.h index 1561236019..12a0c65529 100644 --- a/orchagent/flex_counter/flex_counter_manager.h +++ b/orchagent/flex_counter/flex_counter_manager.h @@ -22,7 +22,8 @@ enum class CounterType PORT, QUEUE, PORT_DEBUG, - SWITCH_DEBUG + SWITCH_DEBUG, + MACSEC, }; // FlexCounterManager allows users to manage a group of flex counters. diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index e170291ce2..a8b25a877c 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -2,12 +2,36 @@ #include "gearboxutils.h" #include "sai_serialize.h" +#include +#include +#include + #include #include #include +#include +#include + +/* Global Variables*/ + +#define EAPOL_ETHER_TYPE 0x888e +#define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000 extern sai_macsec_api_t* sai_macsec_api; extern sai_acl_api_t* sai_acl_api; +extern sai_port_api_t* sai_port_api; + +static const std::vector macsec_egress_sa_stats = +{ + "SAI_MACSEC_SA_ATTR_XPN", +}; + +static const std::vector macsec_ingress_sa_stats = +{ + "SAI_MACSEC_SA_ATTR_MINIMUM_XPN", +}; + +/* Helpers */ template static bool split(const std::string & input, char delimiter, T & output) @@ -161,12 +185,18 @@ static std::istringstream& operator>>( if (buffer.length() == sizeof(sak.m_sak)) { sak.m_sak_256_enable = false; - convert_done = hex_to_binary(buffer, &sak.m_sak[8], sizeof(sak.m_sak) / 2); + convert_done = hex_to_binary( + buffer, + &sak.m_sak[8], + sizeof(sak.m_sak) / 2); } else if (buffer.length() == sizeof(sak.m_sak) * 2) { sak.m_sak_256_enable = true; - convert_done = hex_to_binary(buffer, sak.m_sak, sizeof(sak.m_sak)); + convert_done = hex_to_binary( + buffer, + sak.m_sak, + sizeof(sak.m_sak)); } if (!convert_done) { @@ -210,28 +240,70 @@ static std::istringstream& operator>>( if ( (buffer.length() != sizeof(auth_key.m_auth_key) * 2) - || (!hex_to_binary(buffer, auth_key.m_auth_key, sizeof(auth_key.m_auth_key)))) + || (!hex_to_binary( + buffer, + auth_key.m_auth_key, + sizeof(auth_key.m_auth_key)))) { throw std::invalid_argument("Invalid Auth Key : " + buffer); } return istream; } +class RecoverStack +{ +public: + ~RecoverStack() + { + pop_all(true); + } + void clear() + { + pop_all(); + } + void add_action(std::function action) + { + m_recover_actions.push(action); + } +private: + void pop_all(bool do_recover = false) + { + while (!m_recover_actions.empty()) + { + if (do_recover) + { + m_recover_actions.top()(); + } + m_recover_actions.pop(); + } + } + std::stack > m_recover_actions; +}; + +/* MACsec Orchagent */ + MACsecOrch::MACsecOrch( - DBConnector *appDb, + DBConnector *app_db, DBConnector *state_db, const std::vector &tables, PortsOrch * port_orch) : - Orch(appDb, tables), + Orch(app_db, tables), m_port_orch(port_orch), m_state_macsec_port(state_db, STATE_MACSEC_PORT_TABLE_NAME), m_state_macsec_egress_sc(state_db, STATE_MACSEC_EGRESS_SC_TABLE_NAME), m_state_macsec_ingress_sc(state_db, STATE_MACSEC_INGRESS_SC_TABLE_NAME), m_state_macsec_egress_sa(state_db, STATE_MACSEC_EGRESS_SA_TABLE_NAME), m_state_macsec_ingress_sa(state_db, STATE_MACSEC_INGRESS_SA_TABLE_NAME), - m_gearbox_table(appDb, "_GEARBOX_TABLE"), + m_counter_db("COUNTERS_DB", 0), + m_macsec_counters_map(&m_counter_db, COUNTERS_MACSEC_NAME_MAP), + m_macsec_stat_manager( + COUNTERS_MACSEC_TABLE, + StatsMode::READ, + MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true), + m_gearbox_table(app_db, "_GEARBOX_TABLE"), m_gearbox_enabled(false) { + SWSS_LOG_ENTER(); } MACsecOrch::~MACsecOrch() @@ -239,7 +311,7 @@ MACsecOrch::~MACsecOrch() while (!m_macsec_ports.empty()) { auto port = m_macsec_ports.begin(); - const TaskArgs temp; + const MACsecOrch::TaskArgs temp; disableMACsecPort(port->first, temp); } } @@ -342,32 +414,64 @@ task_process_status MACsecOrch::enableMACsecPort( { SWSS_LOG_ENTER(); + RecoverStack recover; + Port port; if (!m_port_orch->getPort(port_name, port)) { SWSS_LOG_WARN("Port %s cannot be found.", port_name.c_str()); - return task_failed; + return task_need_retry; } - sai_object_id_t switch_id = 0; + sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; if (!getGearboxSwitchId(port, switch_id)) { SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); return task_failed; } + auto macsec_obj = initMACsecObject(switch_id); if (macsec_obj == m_macsec_objs.end()) { SWSS_LOG_WARN("Cannot init MACsec at the port %s.", port_name.c_str()); return task_failed; } + recover.add_action([&]() + { + if (macsec_obj->second.m_ports.empty()) + { + deinitMACsecObject(macsec_obj); + } + }); + auto macsec_port = createMACsecPort(port, switch_id); if (macsec_port == nullptr) { SWSS_LOG_WARN("Cannot init MACsec port at the port %s.", port_name.c_str()); return task_failed; } + recover.add_action([&]() { deleteMACsecPort(port_name); }); - // Set flex counter + if (!initACLTable( + macsec_port->m_egress_acl_table, + port, + switch_id, + SAI_MACSEC_DIRECTION_EGRESS)) + { + SWSS_LOG_WARN("Cannot init the ACL Table at the port %s.", port_name.c_str()); + return task_failed; + } + recover.add_action([&]() { deinitACLTable(macsec_port->m_egress_acl_table, port); }); + + if (!initACLTable( + macsec_port->m_ingress_acl_table, + port, + switch_id, + SAI_MACSEC_DIRECTION_INGRESS)) + { + SWSS_LOG_WARN("Cannot init the ACL Table at the port %s.", port_name.c_str()); + return task_failed; + } + recover.add_action([&]() { deinitACLTable(macsec_port->m_ingress_acl_table, port); }); macsec_port->m_enable_encrypt = true; get_value(port_attr, "enable_encrypt", macsec_port->m_enable_encrypt); @@ -378,6 +482,8 @@ task_process_status MACsecOrch::enableMACsecPort( fvVector.emplace_back("state", "ok"); m_state_macsec_port.set(port_name, fvVector); + recover.clear(); + return task_success; } @@ -387,22 +493,47 @@ task_process_status MACsecOrch::disableMACsecPort( { SWSS_LOG_ENTER(); - sai_object_id_t switch_id = 0; + sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; if (!getGearboxSwitchId(port_name, switch_id)) { SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); return task_failed; } + auto macsec_port = m_macsec_ports.find(port_name); + if (macsec_port == m_macsec_ports.end()) + { + SWSS_LOG_INFO("The MACsec wasn't enabled at the port %s", port_name.c_str()); + return task_success; + } + + Port port; + if (!m_port_orch->getPort(port_name, port)) + { + SWSS_LOG_WARN("Port %s cannot be found.", port_name.c_str()); + return task_failed; + } + task_process_status result = task_success; + + if (!deinitACLTable(macsec_port->second->m_ingress_acl_table, port)) + { + SWSS_LOG_WARN("Cannot deinit ingress ACL table at the port %s.", port_name.c_str()); + result = task_failed; + } + + if (!deinitACLTable(macsec_port->second->m_egress_acl_table, port)) + { + SWSS_LOG_WARN("Cannot deinit egress ACL table at the port %s.", port_name.c_str()); + result = task_failed; + } + if (!deleteMACsecPort(port_name)) { SWSS_LOG_WARN("Cannot delete macsec port at the port %s.", port_name.c_str()); result = task_failed; } - // Delete flex counter - auto macsec_obj = m_macsec_objs.find(switch_id); if (macsec_obj != m_macsec_objs.end()) { @@ -436,7 +567,7 @@ task_process_status MACsecOrch::deleteEgressSC( const TaskArgs & sc_attr) { SWSS_LOG_ENTER(); - return deleteMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_EGRESS); + return deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS); } task_process_status MACsecOrch::updateIngressSC( @@ -452,7 +583,7 @@ task_process_status MACsecOrch::deleteIngressSC( const TaskArgs & sc_attr) { SWSS_LOG_ENTER(); - return deleteMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_INGRESS); + return deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS); } task_process_status MACsecOrch::updateEgressSA( @@ -462,7 +593,7 @@ task_process_status MACsecOrch::updateEgressSA( SWSS_LOG_ENTER(); std::string port_name; sai_uint64_t sci; - sai_uint8_t an; + macsec_an_t an; if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); @@ -492,7 +623,7 @@ task_process_status MACsecOrch::deleteEgressSA( const TaskArgs & sa_attr) { SWSS_LOG_ENTER(); - return deleteMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_EGRESS);; + return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_EGRESS);; } task_process_status MACsecOrch::updateIngressSA( @@ -512,7 +643,7 @@ task_process_status MACsecOrch::updateIngressSA( } else { - return deleteMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_INGRESS); + return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); } return task_success; @@ -638,6 +769,7 @@ bool MACsecOrch::deinitMACsecObject(sai_object_id_t switch_id) SWSS_LOG_INFO("The MACsec wasn't initialized at the switch %lu", switch_id); return true; } + return deinitMACsecObject(macsec_obj); } @@ -671,12 +803,15 @@ std::shared_ptr MACsecOrch::createMACsecPort( { SWSS_LOG_ENTER(); + RecoverStack recover; + auto macsec_port = m_macsec_ports.emplace(port.m_alias, std::make_shared()); if (!macsec_port.second) { SWSS_LOG_INFO("The MACsec port has been initialized at the port %s", port.m_alias.c_str()); return macsec_port.first->second; } + recover.add_action([&]() { m_macsec_ports.erase(macsec_port.first); }); sai_attribute_t attr; std::vector attrs; @@ -694,9 +829,9 @@ std::shared_ptr MACsecOrch::createMACsecPort( attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot create MACsec egress port at the port %s", port.m_alias.c_str()); - m_macsec_ports.erase(macsec_port.first); return nullptr; } + recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); }); attrs.clear(); attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; @@ -712,10 +847,9 @@ std::shared_ptr MACsecOrch::createMACsecPort( attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot create MACsec ingress port at the port %s", port.m_alias.c_str()); - sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); - m_macsec_ports.erase(macsec_port.first); return nullptr; } + recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_ingress_port_id); }); attrs.clear(); attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; @@ -728,11 +862,9 @@ std::shared_ptr MACsecOrch::createMACsecPort( attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot create MACsec egress flow at the port %s", port.m_alias.c_str()); - sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); - sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_ingress_port_id); - m_macsec_ports.erase(macsec_port.first); return nullptr; } + recover.add_action([&]() { sai_macsec_api->remove_macsec_flow(macsec_port.first->second->m_egress_flow_id); }); attrs.clear(); attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; @@ -745,13 +877,11 @@ std::shared_ptr MACsecOrch::createMACsecPort( attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot create MACsec ingress flow at the port %s", port.m_alias.c_str()); - sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); - sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_ingress_port_id); - sai_macsec_api->remove_macsec_flow(macsec_port.first->second->m_ingress_flow_id); - m_macsec_ports.erase(macsec_port.first); return nullptr; } + recover.add_action([&]() { sai_macsec_api->remove_macsec_flow(macsec_port.first->second->m_ingress_flow_id); }); + recover.clear(); return macsec_port.first->second; } @@ -762,10 +892,21 @@ bool MACsecOrch::deleteMACsecPort(const std::string & port_name) auto macsec_port = m_macsec_ports.find(port_name); if (macsec_port == m_macsec_ports.end()) { - SWSS_LOG_INFO("The MACsec port wasn't initialized at the port %s", port_name.c_str()); + SWSS_LOG_WARN("The MACsec port wasn't initialized at the port %s", port_name.c_str()); return true; } + for (auto & sc : macsec_port->second->m_egress_scs) + { + const std::string port_sci = join(':', port_name, sc.first); + deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS); + } + for (auto & sc : macsec_port->second->m_ingress_scs) + { + const std::string port_sci = join(':', port_name, sc.first); + deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS); + } + bool result = true; if(sai_macsec_api->remove_macsec_port( @@ -821,7 +962,7 @@ task_process_status MACsecOrch::updateMACsecSC( SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); return task_need_retry; } - sai_object_id_t switch_id = 0; + sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; if (!getGearboxSwitchId(port_name, switch_id)) { SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); @@ -838,39 +979,95 @@ task_process_status MACsecOrch::updateMACsecSC( // If SC has been created if (!sc.second) { - if (direction == SAI_MACSEC_DIRECTION_EGRESS) + return setEncodingAN(sc.first->second, sc_attr, direction); + } + + sai_object_id_t flow_id= + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_flow_id + : + port->second->m_ingress_flow_id; + + auto result = crateMACsecSC( + sc.first->second, + port_name, + sc_attr, + sci, + flow_id, + switch_id, + direction); + + // If the SC is the first one + // change the ACL entry action from packet action to MACsec flow + if (result == task_success && scs.size() == 1) + { + auto entry_id = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_acl_table.m_data_packet_entry_id + : + port->second->m_ingress_acl_table.m_data_packet_entry_id; + if ( !setACLEntryMACsecFlow(entry_id, flow_id)) { - if (!get_value(sc_attr, "encoding_an", sc.first->second.m_encoding_an)) - { - return task_failed; - } + deleteMACsecSC(port_sci, direction); + SWSS_LOG_WARN("Cannot change the entry action from packet action to MACsec flow"); + result = task_failed; + } + } + + return result; +} + +task_process_status MACsecOrch::setEncodingAN( + MACsecSC &sc, + const TaskArgs & sc_attr, + sai_int32_t direction) +{ + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + if (!get_value(sc_attr, "encoding_an", sc.m_encoding_an)) + { + SWSS_LOG_WARN("Wrong parameter, the encoding AN cannot be found"); + return task_failed; } return task_success; } + else + { + SWSS_LOG_WARN("Cannot set encoding AN for the ingress SC"); + return task_failed; + } +} + +task_process_status MACsecOrch::crateMACsecSC( + MACsecSC &sc, + const std::string & port_name, + const TaskArgs & sc_attr, + sai_uint64_t sci, + sai_object_id_t flow_id, + sai_object_id_t switch_id, + sai_int32_t direction) +{ + const std::string port_sci = join(':', port_name, sci); sai_uint32_t ssci; - sc.first->second.m_xpn64_enable = false; + sc.m_xpn64_enable = false; if (get_value(sc_attr, "ssci", ssci)) { - sc.first->second.m_xpn64_enable = true; + sc.m_xpn64_enable = true; } if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - get_value(sc_attr, "encoding_an", sc.first->second.m_encoding_an); + get_value(sc_attr, "encoding_an", sc.m_encoding_an); } - sai_object_id_t flow_id= - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_flow_id - : - port->second->m_ingress_flow_id; if (!createMACsecSC( - sc.first->second.m_sc_id, + sc.m_sc_id, switch_id, direction, flow_id, sci, ssci, - sc.first->second.m_xpn64_enable)) + sc.m_xpn64_enable)) { SWSS_LOG_WARN("Create MACsec SC %s fail.", port_sci.c_str()); return task_failed; @@ -888,13 +1085,11 @@ task_process_status MACsecOrch::updateMACsecSC( { m_state_macsec_ingress_sc.set(join('|', port_name, sci), fvVector); } - return task_success; } task_process_status MACsecOrch::deleteMACsecSC( const std::string & port_sci, - const TaskArgs & sc_attr, sai_int32_t direction) { SWSS_LOG_ENTER(); @@ -926,11 +1121,42 @@ task_process_status MACsecOrch::deleteMACsecSC( SWSS_LOG_WARN("The MACsec SC %s wasn't created", port_sci.c_str()); return task_failed; } - auto ret = task_success; + + auto result = task_success; + + // If the SC is the only one SC of the direction at this port + // Change the ACL Entry action from flow action to packet action + if (scs.size() == 1) + { + auto entry_id = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_acl_table.m_data_packet_entry_id + : + port->second->m_ingress_acl_table.m_data_packet_entry_id; + sai_object_id_t flow_id= + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? + port->second->m_egress_flow_id + : + port->second->m_ingress_flow_id; + if (!setACLEntryPacketAction(entry_id, flow_id)) + { + SWSS_LOG_WARN("Cannot change the entry action from MACsec flow to packet action"); + result = task_failed; + } + } + + for (macsec_an_t an = 0; an <= MAX_SA_NUMBER; an++) + { + const std::string port_sci_an = join(':', port_sci, an); + deleteMACsecSA(port_sci_an, direction); + } + if (!deleteMACsecSC(sc->second.m_sc_id)) { SWSS_LOG_WARN("The MACsec SC %s cannot be deleted", port_sci.c_str()); - ret = task_failed; + result = task_failed; } port->second->m_egress_scs.erase(sc); SWSS_LOG_NOTICE("MACsec SC %s is deleted.", port_sci.c_str()); @@ -944,7 +1170,7 @@ task_process_status MACsecOrch::deleteMACsecSC( m_state_macsec_ingress_sc.del(join('|', port_name, sci)); } - return ret; + return result; } bool MACsecOrch::createMACsecSC( @@ -1011,7 +1237,7 @@ task_process_status MACsecOrch::createMACsecSA( std::string port_name; sai_uint64_t sci; - sai_uint8_t an; + macsec_an_t an; if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); @@ -1024,7 +1250,7 @@ task_process_status MACsecOrch::createMACsecSA( SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); return task_need_retry; } - sai_object_id_t switch_id = 0; + sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; if (!getGearboxSwitchId(port_name, switch_id)) { SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); @@ -1068,7 +1294,7 @@ task_process_status MACsecOrch::createMACsecSA( return task_failed; } } - catch(std::invalid_argument & e) + catch(const std::invalid_argument & e) { SWSS_LOG_WARN("Invalid argument : %s", e.what()); return task_failed; @@ -1113,10 +1339,12 @@ task_process_status MACsecOrch::createMACsecSA( fvVector.emplace_back("state", "ok"); if (direction == SAI_MACSEC_DIRECTION_EGRESS) { + installCounter(port_sci_an, sc->second.m_sa_ids[an], macsec_egress_sa_stats); m_state_macsec_egress_sa.set(join('|', port_name, sci, an), fvVector); } else { + installCounter(port_sci_an, sc->second.m_sa_ids[an], macsec_ingress_sa_stats); m_state_macsec_ingress_sa.set(join('|', port_name, sci, an), fvVector); } @@ -1126,14 +1354,13 @@ task_process_status MACsecOrch::createMACsecSA( task_process_status MACsecOrch::deleteMACsecSA( const std::string & port_sci_an, - const TaskArgs & sa_attr, sai_int32_t direction) { SWSS_LOG_ENTER(); std::string port_name; sai_uint64_t sci; - sai_uint8_t an; + macsec_an_t an; if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); @@ -1143,8 +1370,8 @@ task_process_status MACsecOrch::deleteMACsecSA( auto port = m_macsec_ports.find(port_name); if (port == m_macsec_ports.end()) { - SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); - return task_need_retry; + SWSS_LOG_WARN("The MACsec port hasn't been created at the port %s.", port_name.c_str()); + return task_failed; } auto & scs = @@ -1153,22 +1380,26 @@ task_process_status MACsecOrch::deleteMACsecSA( port->second->m_egress_scs : port->second->m_ingress_scs; + auto sc = scs.find(sci); if (sc == scs.end()) { - SWSS_LOG_INFO("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); - return task_need_retry; + SWSS_LOG_WARN("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); + return task_failed; } - if (sc->second.m_sa_ids[an] == 0) + if (sc->second.m_sa_ids[an] == SAI_NULL_OBJECT_ID) { SWSS_LOG_WARN("The MACsec SA %s hasn't been created.", port_sci_an.c_str()); return task_failed; } + + uninstallCounter(port_sci_an, sc->second.m_sa_ids[an]); if (!deleteMACsecSA(sc->second.m_sa_ids[an])) { SWSS_LOG_WARN("Cannot delete the MACsec SA %s.", port_sci_an.c_str()); } + sc->second.m_sa_ids[an] = SAI_NULL_OBJECT_ID; if (direction == SAI_MACSEC_DIRECTION_EGRESS) { @@ -1188,7 +1419,7 @@ bool MACsecOrch::createMACsecSA( sai_object_id_t switch_id, sai_int32_t direction, sai_object_id_t sc_id, - sai_uint8_t an, + macsec_an_t an, bool encryption_enable, bool sak_256_bit, sai_macsec_sak_t sak, @@ -1212,7 +1443,7 @@ bool MACsecOrch::createMACsecSA( attrs.push_back(attr); attr.id = SAI_MACSEC_SA_ATTR_AN; - attr.value.u8 = an; + attr.value.u8 = static_cast(an); attrs.push_back(attr); attr.id = SAI_MACSEC_SA_ATTR_ENCRYPTION_ENABLE; @@ -1272,3 +1503,315 @@ bool MACsecOrch::deleteMACsecSA(sai_object_id_t sa_id) } return true; } + +void MACsecOrch::installCounter( + const std::string & obj_name, + sai_object_id_t obj_id, + const std::vector & stats) +{ + FieldValueTuple tuple(obj_name, sai_serialize_object_id(obj_id)); + vector fields; + fields.push_back(tuple); + m_macsec_counters_map.set("", fields); + + std::unordered_set counter_stats; + for (const auto& stat : stats) + { + counter_stats.emplace(stat); + } + m_macsec_stat_manager.setCounterIdList(obj_id, CounterType::MACSEC, counter_stats); +} + +void MACsecOrch::uninstallCounter(const std::string & obj_name, sai_object_id_t obj_id) +{ + m_macsec_stat_manager.clearCounterIdList(obj_id); + + RedisClient redisClient(&m_counter_db); + redisClient.hdel(COUNTERS_PORT_NAME_MAP, obj_name); +} + +bool MACsecOrch::initACLTable( + ACLTable & acl_table, + const Port & port, + sai_object_id_t switch_id, + sai_int32_t direction) +{ + RecoverStack recover; + + if (!createACLTable(acl_table.m_table_id, switch_id, direction)) + { + SWSS_LOG_WARN("Cannot create ACL table at the port %s", port.m_alias.c_str()); + return false; + } + recover.add_action([&]() { deleteACLTable(acl_table.m_table_id); }); + + if (!createACLEAPOLEntry( + acl_table.m_eapol_packet_forward_entry_id, + acl_table.m_table_id, + switch_id)) + { + SWSS_LOG_WARN("Cannot create ACL EAPOL entry at the port %s", port.m_alias.c_str()); + return false; + } + recover.add_action([&]() { deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id); }); + + if (!createACLDataEntry( + acl_table.m_data_packet_entry_id, + acl_table.m_table_id, + switch_id)) + { + SWSS_LOG_WARN("Cannot create ACL entry at the port %s", port.m_alias.c_str()); + return false; + } + recover.add_action([&]() { deleteACLEntry(acl_table.m_data_packet_entry_id); }); + + if (!bindACLTabletoPort(acl_table.m_table_id, port.m_line_port_id)) + { + SWSS_LOG_WARN("Cannot bind ACL table to the port %s", port.m_alias.c_str()); + return false; + } + recover.add_action([&]() { unbindACLTable(port.m_line_port_id); }); + + recover.clear(); + return true; +} + +bool MACsecOrch::deinitACLTable(ACLTable & acl_table, const Port & port) +{ + bool result = true; + + if (!unbindACLTable(port.m_line_port_id)) + { + SWSS_LOG_WARN("Cannot unbind ACL table at the port %s", port.m_alias.c_str()); + result &= false; + } + if (!deleteACLEntry(acl_table.m_data_packet_entry_id)) + { + SWSS_LOG_WARN("Cannot delete ACL entry at the port %s", port.m_alias.c_str()); + result &= false; + } + if (!deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id)) + { + SWSS_LOG_WARN("Cannot delete ACL entry at the port %s", port.m_alias.c_str()); + result &= false; + } + if (!deleteACLTable(acl_table.m_table_id)) + { + SWSS_LOG_WARN("Cannot delete ACL table at the port %s", port.m_alias.c_str()); + result &= false; + } + + return result; +} + +bool MACsecOrch::createACLTable(sai_object_id_t & table_id, sai_object_id_t switch_id, sai_int32_t direction) +{ + sai_attribute_t attr; + std::vector attrs; + + // Create ingress MACsec ACL table for port_id1 + attr.id = SAI_ACL_TABLE_ATTR_ACL_STAGE; + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + attr.value.s32 = SAI_ACL_STAGE_EGRESS_MACSEC; + } + else + { + attr.value.s32 = SAI_ACL_STAGE_INGRESS_MACSEC; + } + attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST; + vector bpoint_list = { SAI_ACL_BIND_POINT_TYPE_PORT }; + attr.value.s32list.count = static_cast(bpoint_list.size()); + attr.value.s32list.list = bpoint_list.data(); + attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_DST_MAC; + attr.value.booldata = true; + attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE; + attr.value.booldata = true; + attrs.push_back(attr); + + if (sai_acl_api->create_acl_table( + &table_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} + +bool MACsecOrch::deleteACLTable(sai_object_id_t table_id) +{ + if (sai_acl_api->remove_acl_table(table_id) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} + +bool MACsecOrch::bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t port_id) +{ + sai_attribute_t attr; + + attr.id = SAI_PORT_ATTR_INGRESS_MACSEC_ACL; + attr.value.oid = table_id; + + if (sai_port_api->set_port_attribute( + port_id, + &attr) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} + +bool MACsecOrch::unbindACLTable(sai_object_id_t port_id) +{ + sai_attribute_t attr; + + attr.id = SAI_PORT_ATTR_INGRESS_MACSEC_ACL; + attr.value.oid = SAI_NULL_OBJECT_ID; + + if (sai_port_api->set_port_attribute( + port_id, + &attr) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} + +bool MACsecOrch::createACLEAPOLEntry( + sai_object_id_t & entry_id, + sai_object_id_t table_id, + sai_object_id_t switch_id) +{ + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_ACL_ENTRY_ATTR_TABLE_ID; + attr.value.oid = table_id; + attrs.push_back(attr); + attr.id = SAI_ACL_ENTRY_ATTR_PRIORITY; + attr.value.u32 = 100; + attrs.push_back(attr); + attr.id = SAI_ACL_ENTRY_ATTR_ADMIN_STATE; + attr.value.booldata = true; + attrs.push_back(attr); + attr.id = SAI_ACL_ENTRY_ATTR_FIELD_DST_MAC; + static const MacAddress nearest_non_tpmr_bridge("01:80:c2:00:00:03"); + nearest_non_tpmr_bridge.getMac(attr.value.aclfield.data.mac); + attrs.push_back(attr); + static const MacAddress mac_address_mask("ff:ff:ff:ff:ff:ff"); + mac_address_mask.getMac(attr.value.aclfield.mask.mac); + attr.value.aclfield.enable = true; + attrs.push_back(attr); + attr.id = SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE; + attr.value.aclfield.data.u16 = EAPOL_ETHER_TYPE; + attr.value.aclfield.mask.u16 = 0xFFFF; + attr.value.aclfield.enable = true; + attrs.push_back(attr); + attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; + attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_FORWARD; + attr.value.aclaction.enable = true; + attrs.push_back(attr); + if (sai_acl_api->create_acl_entry( + &entry_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} + +bool MACsecOrch::createACLDataEntry( + sai_object_id_t & entry_id, + sai_object_id_t table_id, + sai_object_id_t switch_id) +{ + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_ACL_ENTRY_ATTR_TABLE_ID; + attr.value.oid = table_id; + attrs.push_back(attr); + attr.id = SAI_ACL_ENTRY_ATTR_PRIORITY; + attr.value.u32 = 1; + attrs.push_back(attr); + attr.id = SAI_ACL_ENTRY_ATTR_ADMIN_STATE; + attr.value.booldata = true; + attrs.push_back(attr); + attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; + attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_DROP; + attr.value.aclaction.enable = true; + attrs.push_back(attr); + if (sai_acl_api->create_acl_entry( + &entry_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} + +bool MACsecOrch::setACLEntryPacketAction(sai_object_id_t entry_id, sai_object_id_t flow_id) +{ + sai_attribute_t attr; + + attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; + attr.value.aclaction.enable = true; + if (sai_acl_api->set_acl_entry_attribute( + entry_id, + &attr) != SAI_STATUS_SUCCESS) { + return false; + } + + attr.id = SAI_ACL_ENTRY_ATTR_ACTION_MACSEC_FLOW; + attr.value.aclaction.parameter.oid = flow_id; + attr.value.aclaction.enable = false; + + if (sai_acl_api->set_acl_entry_attribute( + entry_id, + &attr) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} + +bool MACsecOrch::setACLEntryMACsecFlow(sai_object_id_t entry_id, sai_object_id_t flow_id) +{ + sai_attribute_t attr; + + attr.id = SAI_ACL_ENTRY_ATTR_ACTION_MACSEC_FLOW; + attr.value.aclaction.parameter.oid = flow_id; + attr.value.aclaction.enable = true; + + if (sai_acl_api->set_acl_entry_attribute( + entry_id, + &attr) != SAI_STATUS_SUCCESS) { + return false; + } + + attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; + attr.value.aclaction.enable = false; + if (sai_acl_api->set_acl_entry_attribute( + entry_id, + &attr) != SAI_STATUS_SUCCESS) { + return false; + } + + return true; +} + +bool MACsecOrch::deleteACLEntry(sai_object_id_t entry_id) +{ + if (sai_acl_api->remove_acl_entry( + entry_id) != SAI_STATUS_SUCCESS) { + return false; + } + return true; +} diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index eeb2423852..e01495cd3f 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -30,15 +30,36 @@ #include #include + +#undef SWSS_LOG_ERROR +#undef SWSS_LOG_WARN +#undef SWSS_LOG_NOTICE +#undef SWSS_LOG_INFO +#undef SWSS_LOG_DEBUG +#undef SWSS_LOG_ENTER + +#define SWSS_LOG_ERROR(MSG, ...) printf("ERROR %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +#define SWSS_LOG_WARN(MSG, ...) printf("WARN %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +#define SWSS_LOG_NOTICE(MSG, ...) printf("NOTICE %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +#define SWSS_LOG_INFO(MSG, ...) printf("INFO %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +#define SWSS_LOG_DEBUG(MSG, ...) printf("DEBUG %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +#define SWSS_LOG_ENTER() printf("ENTER %s : - %s : %d\n", __FILE__, __FUNCTION__, __LINE__) + using namespace swss; // AN is a 2 bit number, it can only be 0, 1, 2 or 3 #define MAX_SA_NUMBER (3) +using macsec_an_t = std::uint32_t; + class MACsecOrch : public Orch { public: - MACsecOrch(DBConnector *app_db, DBConnector *state_db, const std::vector &tables, PortsOrch * port_orch); + MACsecOrch( + DBConnector *app_db, + DBConnector *state_db, + const std::vector &tables, + PortsOrch * port_orch); ~MACsecOrch(); private: @@ -68,10 +89,20 @@ class MACsecOrch : public Orch Table m_state_macsec_egress_sa; Table m_state_macsec_ingress_sa; + DBConnector m_counter_db; + Table m_macsec_counters_map; + FlexCounterManager m_macsec_stat_manager; + Table m_gearbox_table; bool m_gearbox_enabled; map m_gearbox_phy_map; map m_gearbox_interface_map; + struct ACLTable + { + sai_object_id_t m_table_id; + sai_object_id_t m_eapol_packet_forward_entry_id; + sai_object_id_t m_data_packet_entry_id; + }; struct MACsecSC { sai_uint8_t m_encoding_an; @@ -88,6 +119,8 @@ class MACsecOrch : public Orch std::map m_egress_scs; std::map m_ingress_scs; bool m_enable_encrypt; + ACLTable m_egress_acl_table; + ACLTable m_ingress_acl_table; }; struct MACsecObject { @@ -109,16 +142,24 @@ class MACsecOrch : public Orch std::shared_ptr createMACsecPort(const Port & port, sai_object_id_t switch_id); bool deleteMACsecPort(const std::string & port_name); - // bool createACL; - // bool deleteACL; - task_process_status updateMACsecSC( const std::string & port_sci, const TaskArgs & sc_attr, sai_int32_t direction); + task_process_status setEncodingAN( + MACsecSC &sc, + const TaskArgs & sc_attr, + sai_int32_t direction); + task_process_status crateMACsecSC( + MACsecSC &sc, + const std::string & port_name, + const TaskArgs & sc_attr, + sai_uint64_t sci, + sai_object_id_t flow_id, + sai_object_id_t switch_id, + sai_int32_t direction); task_process_status deleteMACsecSC( const std::string & port_sci, - const TaskArgs & sc_attr, sai_int32_t direction); bool createMACsecSC( sai_object_id_t & sc_id, @@ -136,14 +177,13 @@ class MACsecOrch : public Orch sai_int32_t direction); task_process_status deleteMACsecSA( const std::string & port_sci_an, - const TaskArgs & sa_attr, sai_int32_t direction); bool createMACsecSA( sai_object_id_t & sa_id, sai_object_id_t switch_id, sai_int32_t direction, sai_object_id_t sc_id, - sai_uint8_t an, + macsec_an_t an, bool encryption_enable, bool sak_256_bit, sai_macsec_sak_t sak, @@ -153,6 +193,41 @@ class MACsecOrch : public Orch sai_uint64_t pn ); bool deleteMACsecSA(sai_object_id_t sa_id); + + void installCounter( + const std::string & obj_name, + sai_object_id_t obj_id, + const std::vector & stats); + void uninstallCounter(const std::string & obj_name, sai_object_id_t obj_id); + + bool initACLTable( + ACLTable & acl_table, + const Port & port, + sai_object_id_t switch_id, + sai_int32_t direction); + bool deinitACLTable(ACLTable & acl_table, const Port & port); + bool createACLTable( + sai_object_id_t & table_id, + sai_object_id_t switch_id, + sai_int32_t direction); + bool deleteACLTable(sai_object_id_t table_id); + bool bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t port_id); + bool unbindACLTable(sai_object_id_t port_id); + bool createACLEAPOLEntry( + sai_object_id_t & entry_id, + sai_object_id_t table_id, + sai_object_id_t switch_id); + bool createACLDataEntry( + sai_object_id_t & entry_id, + sai_object_id_t table_id, + sai_object_id_t switch_id); + bool setACLEntryPacketAction( + sai_object_id_t entry_id, + sai_object_id_t flow_id); + bool setACLEntryMACsecFlow( + sai_object_id_t entry_id, + sai_object_id_t flow_id); + bool deleteACLEntry(sai_object_id_t entry_id); }; #endif From 23335e0a22f616160f4ba7e804b4fd35b11f0f24 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 4 Sep 2020 02:03:06 +0800 Subject: [PATCH 03/31] Add Debugging information Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 1216 ++++++++++++++++++++++++-------------- orchagent/macsecorch.h | 145 +++-- 2 files changed, 880 insertions(+), 481 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index a8b25a877c..854edef74b 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -1,10 +1,10 @@ #include "macsecorch.h" #include "gearboxutils.h" -#include "sai_serialize.h" #include #include #include +#include #include #include @@ -12,29 +12,101 @@ #include #include +/* Only for Debug */ + +#define MockSAIFunc(FUNC_NAME) \ +sai_status_t FUNC_NAME(...) \ +{ \ + return SAI_STATUS_SUCCESS; \ +} + +struct MockSAIAPI +{ + sai_status_t get_switch_attribute( + sai_object_id_t switch_id, + uint32_t attr_count, + sai_attribute_t *attr_list) + { + if (attr_count != 1) + { + return SAI_STATUS_FAILURE; + } + if (attr_list[0].id == SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY) + { + attr_list[0].value.u32 = 100; + } + else if (attr_list[0].id == SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY) + { + attr_list[0].value.u32 = 0; + } + return SAI_STATUS_SUCCESS; + } + MockSAIFunc(set_port_attribute); + MockSAIFunc(create_macsec); + MockSAIFunc(remove_macsec); + MockSAIFunc(create_macsec_port); + MockSAIFunc(remove_macsec_port); + sai_status_t get_macsec_attribute( + sai_object_id_t switch_id, + uint32_t attr_count, + sai_attribute_t *attr_list) + { + if (attr_count != 1) + { + return SAI_STATUS_FAILURE; + } + if (attr_list[0].id == SAI_MACSEC_ATTR_SCI_IN_INGRESS_MACSEC_ACL) + { + attr_list[0].value.booldata = true; + } + return SAI_STATUS_SUCCESS; + } + MockSAIFunc(create_macsec_flow); + MockSAIFunc(remove_macsec_flow); + MockSAIFunc(create_macsec_sc); + MockSAIFunc(remove_macsec_sc); + MockSAIFunc(create_macsec_sa); + MockSAIFunc(remove_macsec_sa); + MockSAIFunc(create_acl_table); + MockSAIFunc(remove_acl_table); + MockSAIFunc(create_acl_entry); + MockSAIFunc(remove_acl_entry); + MockSAIFunc(set_acl_entry_attribute); +}; + +static MockSAIAPI mock_api; + +static MockSAIAPI * sai_macsec_api = &mock_api; +static MockSAIAPI * sai_acl_api = &mock_api; +static MockSAIAPI * sai_port_api = &mock_api; +static MockSAIAPI * sai_switch_api = &mock_api; + +#define MOCK_RETURN_BOOL return true; + /* Global Variables*/ #define EAPOL_ETHER_TYPE 0x888e #define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000 -extern sai_macsec_api_t* sai_macsec_api; -extern sai_acl_api_t* sai_acl_api; -extern sai_port_api_t* sai_port_api; +// extern sai_macsec_api_t *sai_macsec_api; +// extern sai_acl_api_t *sai_acl_api; +// extern sai_port_api_t *sai_port_api; +// extern sai_switch_api_t *sai_switch_api; -static const std::vector macsec_egress_sa_stats = -{ - "SAI_MACSEC_SA_ATTR_XPN", +static const std::vector macsec_egress_sa_stats = + { + "SAI_MACSEC_SA_ATTR_XPN", }; -static const std::vector macsec_ingress_sa_stats = -{ - "SAI_MACSEC_SA_ATTR_MINIMUM_XPN", +static const std::vector macsec_ingress_sa_stats = + { + "SAI_MACSEC_SA_ATTR_MINIMUM_XPN", }; /* Helpers */ -template -static bool split(const std::string & input, char delimiter, T & output) +template +static bool split(const std::string &input, char delimiter, T &output) { if (input.find(delimiter) != std::string::npos) { @@ -45,8 +117,8 @@ static bool split(const std::string & input, char delimiter, T & output) return true; } -template -static bool split(const std::string & input, char delimiter, T & output, Args & ... args) +template +static bool split(const std::string &input, char delimiter, T &output, Args &... args) { auto pos = input.find(delimiter); if (pos == std::string::npos) @@ -58,33 +130,33 @@ static bool split(const std::string & input, char delimiter, T & output, Args & return split(input.substr(pos + 1, input.length() - pos - 1), delimiter, args...); } -template -static std::string join(const T & input) +template +static std::string join(const T &input) { std::ostringstream ostream; ostream << input; return ostream.str(); } -template -static std::string join(char delimiter, const T & input) +template +static std::string join(char delimiter, const T &input) { return join(input); } -template -static std::string join(char delimiter, const T & input, const Args & ... args) +template +static std::string join(char delimiter, const T &input, const Args &... args) { std::ostringstream ostream; ostream << input << delimiter << join(delimiter, args...); return ostream.str(); } -template +template static bool get_value( - const MACsecOrch::TaskArgs & ta, - const std::string & field, - T & value) + const MACsecOrch::TaskArgs &ta, + const std::string &field, + T &value) { SWSS_LOG_ENTER(); @@ -97,8 +169,7 @@ static bool get_value( auto itr = std::find_if( ta.begin(), ta.end(), - [&](const MACsecOrch::TaskArgs::value_type & entry) - { + [&](const MACsecOrch::TaskArgs::value_type &entry) { std::string field = fvField(entry); std::transform( field.begin(), @@ -121,9 +192,9 @@ static bool get_value( return false; } -static std::istringstream& operator>>( +static std::istringstream &operator>>( std::istringstream &istream, - bool & b) + bool &b) { std::string buffer = istream.str(); std::transform( @@ -143,13 +214,13 @@ static std::istringstream& operator>>( { throw std::invalid_argument("Invalid bool string : " + buffer); } - + return istream; } static bool hex_to_binary( - const std::string & hex_str, - std::uint8_t * buffer, + const std::string &hex_str, + std::uint8_t *buffer, size_t buffer_length) { size_t buffer_cur = 0; @@ -163,7 +234,7 @@ static bool hex_to_binary( std::stringstream stream; stream << std::hex; stream << hex_str[hex_cur++]; - stream << hex_str[hex_cur++]; + stream << hex_str[hex_cur++]; stream >> buffer[buffer_cur++]; } return hex_cur == hex_str.length(); @@ -172,15 +243,15 @@ static bool hex_to_binary( struct MACsecSAK { sai_macsec_sak_t m_sak; - bool m_sak_256_enable; + bool m_sak_256_enable; }; -static std::istringstream& operator>>( +static std::istringstream &operator>>( std::istringstream &istream, - MACsecSAK & sak) + MACsecSAK &sak) { SWSS_LOG_ENTER(); - const std::string & buffer = istream.str(); + const std::string &buffer = istream.str(); bool convert_done = false; if (buffer.length() == sizeof(sak.m_sak)) { @@ -210,16 +281,15 @@ struct MACsecSalt sai_macsec_salt_t m_salt; }; -static std::istringstream& operator>>( +static std::istringstream &operator>>( std::istringstream &istream, - MACsecSalt & salt) + MACsecSalt &salt) { SWSS_LOG_ENTER(); - const std::string & buffer = istream.str(); + const std::string &buffer = istream.str(); if ( - (buffer.length() != sizeof(salt.m_salt) * 2) - || (!hex_to_binary(buffer, salt.m_salt, sizeof(salt.m_salt)))) + (buffer.length() != sizeof(salt.m_salt) * 2) || (!hex_to_binary(buffer, salt.m_salt, sizeof(salt.m_salt)))) { throw std::invalid_argument("Invalid SALT : " + buffer); } @@ -231,25 +301,25 @@ struct MACsecAuthKey sai_macsec_auth_key_t m_auth_key; }; -static std::istringstream& operator>>( +static std::istringstream &operator>>( std::istringstream &istream, - MACsecAuthKey & auth_key) + MACsecAuthKey &auth_key) { SWSS_LOG_ENTER(); - const std::string & buffer = istream.str(); + const std::string &buffer = istream.str(); if ( - (buffer.length() != sizeof(auth_key.m_auth_key) * 2) - || (!hex_to_binary( - buffer, - auth_key.m_auth_key, - sizeof(auth_key.m_auth_key)))) + (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!hex_to_binary( + buffer, + auth_key.m_auth_key, + sizeof(auth_key.m_auth_key)))) { throw std::invalid_argument("Invalid Auth Key : " + buffer); } return istream; } +/* Recover from a fail action by a serial of pre-defined recover actions */ class RecoverStack { public: @@ -265,6 +335,7 @@ class RecoverStack { m_recover_actions.push(action); } + private: void pop_all(bool do_recover = false) { @@ -277,7 +348,7 @@ class RecoverStack m_recover_actions.pop(); } } - std::stack > m_recover_actions; + std::stack> m_recover_actions; }; /* MACsec Orchagent */ @@ -286,22 +357,21 @@ MACsecOrch::MACsecOrch( DBConnector *app_db, DBConnector *state_db, const std::vector &tables, - PortsOrch * port_orch) : - Orch(app_db, tables), - m_port_orch(port_orch), - m_state_macsec_port(state_db, STATE_MACSEC_PORT_TABLE_NAME), - m_state_macsec_egress_sc(state_db, STATE_MACSEC_EGRESS_SC_TABLE_NAME), - m_state_macsec_ingress_sc(state_db, STATE_MACSEC_INGRESS_SC_TABLE_NAME), - m_state_macsec_egress_sa(state_db, STATE_MACSEC_EGRESS_SA_TABLE_NAME), - m_state_macsec_ingress_sa(state_db, STATE_MACSEC_INGRESS_SA_TABLE_NAME), - m_counter_db("COUNTERS_DB", 0), - m_macsec_counters_map(&m_counter_db, COUNTERS_MACSEC_NAME_MAP), - m_macsec_stat_manager( - COUNTERS_MACSEC_TABLE, - StatsMode::READ, - MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true), - m_gearbox_table(app_db, "_GEARBOX_TABLE"), - m_gearbox_enabled(false) + PortsOrch *port_orch) : Orch(app_db, tables), + m_port_orch(port_orch), + m_state_macsec_port(state_db, STATE_MACSEC_PORT_TABLE_NAME), + m_state_macsec_egress_sc(state_db, STATE_MACSEC_EGRESS_SC_TABLE_NAME), + m_state_macsec_ingress_sc(state_db, STATE_MACSEC_INGRESS_SC_TABLE_NAME), + m_state_macsec_egress_sa(state_db, STATE_MACSEC_EGRESS_SA_TABLE_NAME), + m_state_macsec_ingress_sa(state_db, STATE_MACSEC_INGRESS_SA_TABLE_NAME), + m_counter_db("COUNTERS_DB", 0), + m_macsec_counters_map(&m_counter_db, COUNTERS_MACSEC_NAME_MAP), + m_macsec_stat_manager( + COUNTERS_MACSEC_TABLE, + StatsMode::READ, + MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true), + m_gearbox_table(app_db, "_GEARBOX_TABLE"), + m_gearbox_enabled(false) { SWSS_LOG_ENTER(); } @@ -329,40 +399,40 @@ void MACsecOrch::doTask(Consumer &consumer) } } - using TaskType = std::tuple; + using TaskType = std::tuple; using TaskFunc = task_process_status (MACsecOrch::*)( const std::string &, const TaskArgs &); - const static std::map TaskMap = { - { { APP_MACSEC_PORT_TABLE_NAME, SET_COMMAND }, - &MACsecOrch::enableMACsecPort }, - { { APP_MACSEC_PORT_TABLE_NAME, DEL_COMMAND }, - &MACsecOrch::disableMACsecPort }, - { { APP_MACSEC_EGRESS_SC_TABLE_NAME, SET_COMMAND }, - &MACsecOrch::updateEgressSC }, - { { APP_MACSEC_EGRESS_SC_TABLE_NAME, DEL_COMMAND }, - &MACsecOrch::deleteEgressSC }, - { { APP_MACSEC_INGRESS_SC_TABLE_NAME, SET_COMMAND }, - &MACsecOrch::updateIngressSC }, - { { APP_MACSEC_INGRESS_SC_TABLE_NAME, DEL_COMMAND }, - &MACsecOrch::deleteIngressSC }, - { { APP_MACSEC_EGRESS_SA_TABLE_NAME, SET_COMMAND }, - &MACsecOrch::updateEgressSA }, - { { APP_MACSEC_EGRESS_SA_TABLE_NAME, DEL_COMMAND }, - &MACsecOrch::deleteEgressSA }, - { { APP_MACSEC_INGRESS_SA_TABLE_NAME, SET_COMMAND }, - &MACsecOrch::updateIngressSA }, - { { APP_MACSEC_INGRESS_SA_TABLE_NAME, DEL_COMMAND }, - &MACsecOrch::deleteIngressSA }, + const static std::map TaskMap = { + {{APP_MACSEC_PORT_TABLE_NAME, SET_COMMAND}, + &MACsecOrch::updateMACsecPort}, + {{APP_MACSEC_PORT_TABLE_NAME, DEL_COMMAND}, + &MACsecOrch::disableMACsecPort}, + {{APP_MACSEC_EGRESS_SC_TABLE_NAME, SET_COMMAND}, + &MACsecOrch::updateEgressSC}, + {{APP_MACSEC_EGRESS_SC_TABLE_NAME, DEL_COMMAND}, + &MACsecOrch::deleteEgressSC}, + {{APP_MACSEC_INGRESS_SC_TABLE_NAME, SET_COMMAND}, + &MACsecOrch::updateIngressSC}, + {{APP_MACSEC_INGRESS_SC_TABLE_NAME, DEL_COMMAND}, + &MACsecOrch::deleteIngressSC}, + {{APP_MACSEC_EGRESS_SA_TABLE_NAME, SET_COMMAND}, + &MACsecOrch::updateEgressSA}, + {{APP_MACSEC_EGRESS_SA_TABLE_NAME, DEL_COMMAND}, + &MACsecOrch::deleteEgressSA}, + {{APP_MACSEC_INGRESS_SA_TABLE_NAME, SET_COMMAND}, + &MACsecOrch::updateIngressSA}, + {{APP_MACSEC_INGRESS_SA_TABLE_NAME, DEL_COMMAND}, + &MACsecOrch::deleteIngressSA}, }; - const std::string & table_name = consumer.getTableName(); + 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 &message = itr->second; + const std::string &op = kfvOp(message); auto task = TaskMap.find(std::make_tuple(table_name, op)); if (task != TaskMap.end()) @@ -392,8 +462,8 @@ void MACsecOrch::doTask(Consumer &consumer) if (task_done != task_success) { SWSS_LOG_WARN("Task %s - %s fail", - table_name.c_str(), - op.c_str()); + table_name.c_str(), + op.c_str()); } else { @@ -408,9 +478,9 @@ void MACsecOrch::doTask(Consumer &consumer) } } -task_process_status MACsecOrch::enableMACsecPort( - const std::string & port_name, - const TaskArgs & port_attr) +task_process_status MACsecOrch::updateMACsecPort( + const std::string &port_name, + const TaskArgs &port_attr) { SWSS_LOG_ENTER(); @@ -435,48 +505,112 @@ task_process_status MACsecOrch::enableMACsecPort( SWSS_LOG_WARN("Cannot init MACsec at the port %s.", port_name.c_str()); return task_failed; } - recover.add_action([&]() - { + recover.add_action([&]() { if (macsec_obj->second.m_ports.empty()) { deinitMACsecObject(macsec_obj); } }); - auto macsec_port = createMACsecPort(port, switch_id); - if (macsec_port == nullptr) + std::shared_ptr macsec_port; + auto macsec_port_itr = m_macsec_ports.find(port_name); + if (macsec_port_itr == m_macsec_ports.end()) { - SWSS_LOG_WARN("Cannot init MACsec port at the port %s.", port_name.c_str()); - return task_failed; + macsec_port = createMACsecPort( + port_name, + port.m_line_port_id, + switch_id); + if (macsec_port == nullptr) + { + SWSS_LOG_WARN("Cannot init MACsec port at the port %s.", port_name.c_str()); + return task_failed; + } + recover.add_action([&]() { deleteMACsecPort(port_name); }); + macsec_obj->second.m_ports[port_name] = macsec_port; + recover.add_action([&]() { macsec_obj->second.m_ports.erase(port_name); }); + } + else + { + macsec_port = macsec_port_itr->second; + } + + get_value(port_attr, "enable_encrypt", macsec_port->m_enable_encrypt); + get_value(port_attr, "send_sci", macsec_port->m_sci_in_sectag); + if (get_value(port_attr, "enable", macsec_port->m_enable)) + { + std::vector scs; + for (auto &sc : macsec_port->m_egress_scs) + { + scs.push_back(&(sc.second)); + } + for (auto &sc : macsec_port->m_ingress_scs) + { + scs.push_back(&(sc.second)); + } + for (auto &sc : scs) + { + // Change the ACL entry action from packet action to MACsec flow + if (macsec_port->m_enable) + { + if (!setACLEntryMACsecFlow(sc->m_entry_id, sc->m_flow_id)) + { + SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); + return task_failed; + } + recover.add_action([&]() { setACLEntryPacketAction(sc->m_encoding_an, sc->m_flow_id); }); + } + else + { + setACLEntryPacketAction(sc->m_encoding_an, sc->m_flow_id); + } + } + } + + // If hardware matches SCI in ACL, the macsec_flow maps to an IEEE 802.1ae SecY object. + // Multiple SCs can be associated with such a macsec_flow. + // Then a specific value of SCI from the SecTAG in the packet is used to identify a specific SC + // for that macsec_flow. + // False means one flow can be associated with multiple ACL entries and multiple SC + if (!macsec_obj->second.m_sci_in_ingress_macsec_acl) + { + if (!createMACsecFlow(macsec_port->m_egress_flow_id, switch_id, SAI_MACSEC_DIRECTION_EGRESS)) + { + SWSS_LOG_WARN("Cannot create MACsec egress flow at the port %s.", port_name.c_str()); + return task_failed; + } + recover.add_action([&]() { deleteMACsecFlow(macsec_port->m_egress_flow_id); }); + + if (!createMACsecFlow(macsec_port->m_ingress_flow_id, switch_id, SAI_MACSEC_DIRECTION_EGRESS)) + { + SWSS_LOG_WARN("Cannot create MACsec ingress flow at the port %s.", port_name.c_str()); + return task_failed; + } + recover.add_action([&]() { deleteMACsecFlow(macsec_port->m_ingress_flow_id); }); } - recover.add_action([&]() { deleteMACsecPort(port_name); }); if (!initACLTable( - macsec_port->m_egress_acl_table, - port, - switch_id, - SAI_MACSEC_DIRECTION_EGRESS)) + macsec_port->m_egress_acl_table, + port.m_line_port_id, + switch_id, + SAI_MACSEC_DIRECTION_EGRESS, + macsec_port->m_sci_in_sectag)) { SWSS_LOG_WARN("Cannot init the ACL Table at the port %s.", port_name.c_str()); return task_failed; } - recover.add_action([&]() { deinitACLTable(macsec_port->m_egress_acl_table, port); }); + recover.add_action([&]() { deinitACLTable(macsec_port->m_egress_acl_table, port.m_line_port_id); }); if (!initACLTable( - macsec_port->m_ingress_acl_table, - port, - switch_id, - SAI_MACSEC_DIRECTION_INGRESS)) + macsec_port->m_ingress_acl_table, + port.m_line_port_id, + switch_id, + SAI_MACSEC_DIRECTION_INGRESS, + macsec_port->m_sci_in_sectag)) { SWSS_LOG_WARN("Cannot init the ACL Table at the port %s.", port_name.c_str()); return task_failed; } - recover.add_action([&]() { deinitACLTable(macsec_port->m_ingress_acl_table, port); }); - - macsec_port->m_enable_encrypt = true; - get_value(port_attr, "enable_encrypt", macsec_port->m_enable_encrypt); - - macsec_obj->second.m_ports[port_name] = macsec_port; + recover.add_action([&]() { deinitACLTable(macsec_port->m_ingress_acl_table, port.m_line_port_id); }); std::vector fvVector; fvVector.emplace_back("state", "ok"); @@ -488,8 +622,8 @@ task_process_status MACsecOrch::enableMACsecPort( } task_process_status MACsecOrch::disableMACsecPort( - const std::string & port_name, - const TaskArgs & port_attr) + const std::string &port_name, + const TaskArgs &port_attr) { SWSS_LOG_ENTER(); @@ -510,19 +644,19 @@ task_process_status MACsecOrch::disableMACsecPort( Port port; if (!m_port_orch->getPort(port_name, port)) { - SWSS_LOG_WARN("Port %s cannot be found.", port_name.c_str()); - return task_failed; + SWSS_LOG_INFO("Port %s cannot be found.", port_name.c_str()); + return task_success; } task_process_status result = task_success; - if (!deinitACLTable(macsec_port->second->m_ingress_acl_table, port)) + if (!deinitACLTable(macsec_port->second->m_ingress_acl_table, port.m_line_port_id)) { SWSS_LOG_WARN("Cannot deinit ingress ACL table at the port %s.", port_name.c_str()); result = task_failed; } - if (!deinitACLTable(macsec_port->second->m_egress_acl_table, port)) + if (!deinitACLTable(macsec_port->second->m_egress_acl_table, port.m_line_port_id)) { SWSS_LOG_WARN("Cannot deinit egress ACL table at the port %s.", port_name.c_str()); result = task_failed; @@ -555,40 +689,40 @@ task_process_status MACsecOrch::disableMACsecPort( } task_process_status MACsecOrch::updateEgressSC( - const std::string & port_sci, - const TaskArgs & sc_attr) + const std::string &port_sci, + const TaskArgs &sc_attr) { SWSS_LOG_ENTER(); return updateMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_EGRESS); } task_process_status MACsecOrch::deleteEgressSC( - const std::string & port_sci, - const TaskArgs & sc_attr) + const std::string &port_sci, + const TaskArgs &sc_attr) { SWSS_LOG_ENTER(); return deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS); } task_process_status MACsecOrch::updateIngressSC( - const std::string & port_sci, - const TaskArgs & sc_attr) + const std::string &port_sci, + const TaskArgs &sc_attr) { SWSS_LOG_ENTER(); return updateMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_INGRESS); } task_process_status MACsecOrch::deleteIngressSC( - const std::string & port_sci, - const TaskArgs & sc_attr) + const std::string &port_sci, + const TaskArgs &sc_attr) { SWSS_LOG_ENTER(); return deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS); } task_process_status MACsecOrch::updateEgressSA( - const std::string & port_sci_an, - const TaskArgs & sa_attr) + const std::string &port_sci_an, + const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); std::string port_name; @@ -603,7 +737,8 @@ task_process_status MACsecOrch::updateEgressSA( if (port == m_macsec_ports.end()) { SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); - return task_need_retry; + // return task_need_retry; + return task_failed; } auto sc = port->second->m_egress_scs.find(sci); if (sc == port->second->m_egress_scs.end()) @@ -619,16 +754,17 @@ task_process_status MACsecOrch::updateEgressSA( } task_process_status MACsecOrch::deleteEgressSA( - const std::string & port_sci_an, - const TaskArgs & sa_attr) + const std::string &port_sci_an, + const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); - return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_EGRESS);; + return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_EGRESS); + ; } task_process_status MACsecOrch::updateIngressSA( - const std::string & port_sci_an, - const TaskArgs & sa_attr) + const std::string &port_sci_an, + const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); bool active = false; @@ -645,13 +781,13 @@ task_process_status MACsecOrch::updateIngressSA( { return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); } - + return task_success; } task_process_status MACsecOrch::deleteIngressSA( - const std::string & port_sci_an, - const TaskArgs & sa_attr) + const std::string &port_sci_an, + const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); return task_success; @@ -674,7 +810,7 @@ bool MACsecOrch::initGearbox() return m_gearbox_enabled; } -bool MACsecOrch::getGearboxSwitchId(const std::string & port_name, sai_object_id_t & switch_id) const +bool MACsecOrch::getGearboxSwitchId(const std::string &port_name, sai_object_id_t &switch_id) const { SWSS_LOG_ENTER(); @@ -687,8 +823,9 @@ bool MACsecOrch::getGearboxSwitchId(const std::string & port_name, sai_object_id return getGearboxSwitchId(port, switch_id); } -bool MACsecOrch::getGearboxSwitchId(const Port & port, sai_object_id_t & switch_id) const +bool MACsecOrch::getGearboxSwitchId(const Port &port, sai_object_id_t &switch_id) const { + MOCK_RETURN_BOOL; SWSS_LOG_ENTER(); auto phy_id = m_gearbox_interface_map.find(port.m_index); @@ -716,46 +853,64 @@ map::iterator MACsecOrch::initMACsecO { SWSS_LOG_ENTER(); + RecoverStack recover; + auto macsec_obj = m_macsec_objs.emplace(switch_id, MACsecObject()); if (!macsec_obj.second) { SWSS_LOG_INFO("The MACsec has been initialized at the switch %lu", switch_id); return macsec_obj.first; } + recover.add_action([&]() { m_macsec_objs.erase(macsec_obj.first); }); sai_attribute_t attr; std::vector attrs; - attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.id = SAI_MACSEC_ATTR_DIRECTION; attr.value.s32 = SAI_MACSEC_DIRECTION_EGRESS; attrs.push_back(attr); - if(sai_macsec_api->create_macsec( - &macsec_obj.first->second.m_egress_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) + if (sai_macsec_api->create_macsec( + &macsec_obj.first->second.m_egress_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot initialize MACsec egress object at the switch %lu", switch_id); - m_macsec_objs.erase(macsec_obj.first); return m_macsec_objs.end(); } + recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_egress_id); }); attrs.clear(); - attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.id = SAI_MACSEC_ATTR_DIRECTION; attr.value.s32 = SAI_MACSEC_DIRECTION_INGRESS; attrs.push_back(attr); - if(sai_macsec_api->create_macsec( - &macsec_obj.first->second.m_ingress_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) + if (sai_macsec_api->create_macsec( + &macsec_obj.first->second.m_ingress_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot initialize MACsec ingress object at the switch %lu", switch_id); - sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_egress_id); - m_macsec_objs.erase(macsec_obj.first); return m_macsec_objs.end(); } + recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_ingress_id); }); + + attrs.clear(); + attr.id = SAI_MACSEC_ATTR_SCI_IN_INGRESS_MACSEC_ACL; + attrs.push_back(attr); + if (sai_macsec_api->get_macsec_attribute( + macsec_obj.first->second.m_ingress_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN( + "Cannot get MACsec attribution SAI_MACSEC_ATTR_SCI_IN_INGRESS_MACSEC_ACL at the switch %lu", + switch_id); + return m_macsec_objs.end(); + } + macsec_obj.first->second.m_sci_in_ingress_macsec_acl = attrs.front().value.booldata; + recover.clear(); return macsec_obj.first; } @@ -779,15 +934,15 @@ bool MACsecOrch::deinitMACsecObject(map::iterator bool result = true; - if(sai_macsec_api->remove_macsec( - macsec_obj->second.m_egress_id) != SAI_STATUS_SUCCESS) + if (sai_macsec_api->remove_macsec( + macsec_obj->second.m_egress_id) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot deinitialize MACsec egress object at the switch %lu", macsec_obj->first); result &= false; } - if(sai_macsec_api->remove_macsec( - macsec_obj->second.m_ingress_id) != SAI_STATUS_SUCCESS) + if (sai_macsec_api->remove_macsec( + macsec_obj->second.m_ingress_id) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot deinitialize MACsec ingress object at the switch %lu", macsec_obj->first); result &= false; @@ -798,17 +953,18 @@ bool MACsecOrch::deinitMACsecObject(map::iterator } std::shared_ptr MACsecOrch::createMACsecPort( - const Port & port, + const std::string &port_name, + sai_object_id_t port_id, sai_object_id_t switch_id) { SWSS_LOG_ENTER(); RecoverStack recover; - auto macsec_port = m_macsec_ports.emplace(port.m_alias, std::make_shared()); + auto macsec_port = m_macsec_ports.emplace(port_name, std::make_shared()); if (!macsec_port.second) { - SWSS_LOG_INFO("The MACsec port has been initialized at the port %s", port.m_alias.c_str()); + SWSS_LOG_INFO("The MACsec port has been initialized at the port %s.", port_name.c_str()); return macsec_port.first->second; } recover.add_action([&]() { m_macsec_ports.erase(macsec_port.first); }); @@ -820,15 +976,15 @@ std::shared_ptr MACsecOrch::createMACsecPort( attr.value.s32 = SAI_MACSEC_DIRECTION_EGRESS; attrs.push_back(attr); attr.id = SAI_MACSEC_PORT_ATTR_PORT_ID; - attr.value.oid = port.m_line_port_id; + attr.value.oid = port_id; attrs.push_back(attr); if (sai_macsec_api->create_macsec_port( - &macsec_port.first->second->m_egress_port_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) + &macsec_port.first->second->m_egress_port_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot create MACsec egress port at the port %s", port.m_alias.c_str()); + SWSS_LOG_WARN("Cannot create MACsec egress port at the port %s", port_name.c_str()); return nullptr; } recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); }); @@ -838,54 +994,28 @@ std::shared_ptr MACsecOrch::createMACsecPort( attr.value.s32 = SAI_MACSEC_DIRECTION_INGRESS; attrs.push_back(attr); attr.id = SAI_MACSEC_PORT_ATTR_PORT_ID; - attr.value.oid = port.m_line_port_id; + attr.value.oid = port_id; attrs.push_back(attr); if (sai_macsec_api->create_macsec_port( - &macsec_port.first->second->m_ingress_port_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) + &macsec_port.first->second->m_ingress_port_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot create MACsec ingress port at the port %s", port.m_alias.c_str()); + SWSS_LOG_WARN("Cannot create MACsec ingress port at the port %s", port_name.c_str()); return nullptr; } recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_ingress_port_id); }); - attrs.clear(); - attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; - attr.value.s32 = SAI_MACSEC_DIRECTION_EGRESS; - attrs.push_back(attr); - if (sai_macsec_api->create_macsec_flow( - &macsec_port.first->second->m_egress_flow_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) - { - SWSS_LOG_WARN("Cannot create MACsec egress flow at the port %s", port.m_alias.c_str()); - return nullptr; - } - recover.add_action([&]() { sai_macsec_api->remove_macsec_flow(macsec_port.first->second->m_egress_flow_id); }); - - attrs.clear(); - attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; - attr.value.s32 = SAI_MACSEC_DIRECTION_INGRESS; - attrs.push_back(attr); - if (sai_macsec_api->create_macsec_flow( - &macsec_port.first->second->m_ingress_flow_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) - { - SWSS_LOG_WARN("Cannot create MACsec ingress flow at the port %s", port.m_alias.c_str()); - return nullptr; - } - recover.add_action([&]() { sai_macsec_api->remove_macsec_flow(macsec_port.first->second->m_ingress_flow_id); }); + macsec_port.first->second->m_enable_encrypt = true; + macsec_port.first->second->m_sci_in_sectag = true; + macsec_port.first->second->m_enable = false; recover.clear(); return macsec_port.first->second; } -bool MACsecOrch::deleteMACsecPort(const std::string & port_name) +bool MACsecOrch::deleteMACsecPort(const std::string &port_name) { SWSS_LOG_ENTER(); @@ -896,12 +1026,12 @@ bool MACsecOrch::deleteMACsecPort(const std::string & port_name) return true; } - for (auto & sc : macsec_port->second->m_egress_scs) + for (auto &sc : macsec_port->second->m_egress_scs) { const std::string port_sci = join(':', port_name, sc.first); deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS); } - for (auto & sc : macsec_port->second->m_ingress_scs) + for (auto &sc : macsec_port->second->m_ingress_scs) { const std::string port_sci = join(':', port_name, sc.first); deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS); @@ -909,29 +1039,29 @@ bool MACsecOrch::deleteMACsecPort(const std::string & port_name) bool result = true; - if(sai_macsec_api->remove_macsec_port( - macsec_port->second->m_egress_port_id) != SAI_STATUS_SUCCESS) + if (sai_macsec_api->remove_macsec_port( + macsec_port->second->m_egress_port_id) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot delete MACsec egress port at the port %s", port_name.c_str()); result &= false; } - if(sai_macsec_api->remove_macsec_port( - macsec_port->second->m_ingress_port_id) != SAI_STATUS_SUCCESS) + if (sai_macsec_api->remove_macsec_port( + macsec_port->second->m_ingress_port_id) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot delete MACsec ingress port at the port %s", port_name.c_str()); result &= false; } - if(sai_macsec_api->remove_macsec_flow( - macsec_port->second->m_egress_flow_id) != SAI_STATUS_SUCCESS) + if (sai_macsec_api->remove_macsec_flow( + macsec_port->second->m_egress_flow_id) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot delete MACsec egress flow at the port %s", port_name.c_str()); result &= false; } - if(sai_macsec_api->remove_macsec_flow( - macsec_port->second->m_ingress_flow_id) != SAI_STATUS_SUCCESS) + if (sai_macsec_api->remove_macsec_flow( + macsec_port->second->m_ingress_flow_id) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot delete MACsec ingress flow at the port %s", port_name.c_str()); result &= false; @@ -941,9 +1071,48 @@ bool MACsecOrch::deleteMACsecPort(const std::string & port_name) return true; } +bool MACsecOrch::createMACsecFlow( + sai_object_id_t &flow_id, + sai_object_id_t switch_id, + sai_int32_t direction) +{ + SWSS_LOG_ENTER(); + + if (flow_id != SAI_NULL_OBJECT_ID) + { + return true; + } + + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.value.s32 = direction; + attrs.push_back(attr); + if (sai_macsec_api->create_macsec_flow( + &flow_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + return false; + } + return true; +} + +bool MACsecOrch::deleteMACsecFlow(sai_object_id_t flow_id) +{ + if (sai_macsec_api->remove_macsec_flow( + flow_id) != SAI_STATUS_SUCCESS) + { + return false; + } + return true; +} + task_process_status MACsecOrch::updateMACsecSC( - const std::string & port_sci, - const TaskArgs & sc_attr, + const std::string &port_sci, + const TaskArgs &sc_attr, sai_int32_t direction) { SWSS_LOG_ENTER(); @@ -956,8 +1125,8 @@ task_process_status MACsecOrch::updateMACsecSC( return task_failed; } - auto port = m_macsec_ports.find(port_name); - if (port == m_macsec_ports.end()) + auto m_macsec_port = m_macsec_ports.find(port_name); + if (m_macsec_port == m_macsec_ports.end()) { SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); return task_need_retry; @@ -969,59 +1138,37 @@ task_process_status MACsecOrch::updateMACsecSC( return task_failed; } - auto & scs = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_scs - : - port->second->m_ingress_scs; - auto sc = scs.emplace(sci, MACsecSC()); - // If SC has been created - if (!sc.second) + auto macsec_obj = m_macsec_objs.find(switch_id); + if (macsec_obj == m_macsec_objs.end()) { - return setEncodingAN(sc.first->second, sc_attr, direction); + SWSS_LOG_INFO("The MACsec wasn't initialized at the switch %lu", switch_id); + return task_failed; } - sai_object_id_t flow_id= - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_flow_id - : - port->second->m_ingress_flow_id; + auto &scs = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? m_macsec_port->second->m_egress_scs + : m_macsec_port->second->m_ingress_scs; + auto sc = scs.find(sci); + // If SC has been created + if (sc != scs.end()) + { + return setEncodingAN(sc->second, sc_attr, direction); + } - auto result = crateMACsecSC( - sc.first->second, + return createMACsecSC( + *(m_macsec_port->second), port_name, sc_attr, + macsec_obj->second, sci, - flow_id, switch_id, direction); - - // If the SC is the first one - // change the ACL entry action from packet action to MACsec flow - if (result == task_success && scs.size() == 1) - { - auto entry_id = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_acl_table.m_data_packet_entry_id - : - port->second->m_ingress_acl_table.m_data_packet_entry_id; - if ( !setACLEntryMACsecFlow(entry_id, flow_id)) - { - deleteMACsecSC(port_sci, direction); - SWSS_LOG_WARN("Cannot change the entry action from packet action to MACsec flow"); - result = task_failed; - } - } - - return result; } task_process_status MACsecOrch::setEncodingAN( MACsecSC &sc, - const TaskArgs & sc_attr, + const TaskArgs &sc_attr, sai_int32_t direction) { if (direction == SAI_MACSEC_DIRECTION_EGRESS) @@ -1040,19 +1187,37 @@ task_process_status MACsecOrch::setEncodingAN( } } -task_process_status MACsecOrch::crateMACsecSC( - MACsecSC &sc, - const std::string & port_name, - const TaskArgs & sc_attr, +task_process_status MACsecOrch::createMACsecSC( + MACsecPort &macsec_port, + const std::string &port_name, + const TaskArgs &sc_attr, + const MACsecObject &macsec_obj, sai_uint64_t sci, - sai_object_id_t flow_id, sai_object_id_t switch_id, sai_int32_t direction) { + SWSS_LOG_ENTER(); + + RecoverStack recover; + const std::string port_sci = join(':', port_name, sci); + + auto &scs = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? macsec_port.m_egress_scs + : macsec_port.m_ingress_scs; + auto sc_itr = scs.emplace(sci, MACsecSC()); + if (!sc_itr.second) + { + SWSS_LOG_ERROR("The SC %s has been created.", port_sci.c_str()); + return task_failed; + } + recover.add_action([&]() { scs.erase(sc_itr.first->first); }); + auto &sc = sc_itr.first->second; + sai_uint32_t ssci; sc.m_xpn64_enable = false; - if (get_value(sc_attr, "ssci", ssci)) + if (get_value(sc_attr, "ssci", ssci) && ssci) { sc.m_xpn64_enable = true; } @@ -1060,18 +1225,69 @@ task_process_status MACsecOrch::crateMACsecSC( { get_value(sc_attr, "encoding_an", sc.m_encoding_an); } + + sc.m_flow_id = SAI_NULL_OBJECT_ID; + + // If SCI can only be used as ACL field + // Which means one ingress flow can be associated with only one ACL entry and one SC. + if (macsec_obj.m_sci_in_ingress_macsec_acl) + { + if (!createMACsecFlow(sc.m_flow_id, switch_id, direction)) + { + SWSS_LOG_WARN("Cannot create MACsec Flow"); + return task_failed; + } + recover.add_action([&]() { deleteMACsecFlow(sc.m_flow_id); }); + } + else + { + sc.m_flow_id = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? macsec_port.m_egress_flow_id + : macsec_port.m_ingress_flow_id; + } + if (!createMACsecSC( - sc.m_sc_id, + sc.m_sc_id, + switch_id, + direction, + sc.m_flow_id, + sci, + ssci, + sc.m_xpn64_enable)) + { + SWSS_LOG_WARN("Create MACsec SC %s fail.", port_sci.c_str()); + return task_failed; + } + recover.add_action([&]() { deleteMACsecSC(sc.m_sc_id); }); + + auto &table = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? macsec_port.m_egress_acl_table + : macsec_port.m_ingress_acl_table; + if (table.m_available_acl_priorities.empty()) + { + SWSS_LOG_WARN("Available ACL priorities have been exhausted."); + return task_failed; + } + sc.m_acl_priority = *(table.m_available_acl_priorities.begin()); + table.m_available_acl_priorities.erase(table.m_available_acl_priorities.begin()); + if (!createACLDataEntry( + sc.m_entry_id, + table.m_table_id, switch_id, - direction, - flow_id, + macsec_port.m_sci_in_sectag, sci, - ssci, - sc.m_xpn64_enable)) + sc.m_acl_priority)) { - SWSS_LOG_WARN("Create MACsec SC %s fail.", port_sci.c_str()); + SWSS_LOG_WARN("Cannot create ACL Data entry"); return task_failed; } + recover.add_action([&]() + { + deleteACLEntry(sc.m_entry_id); + table.m_available_acl_priorities.insert(sc.m_acl_priority); + }); SWSS_LOG_NOTICE("MACsec SC %s is created.", port_sci.c_str()); @@ -1089,7 +1305,7 @@ task_process_status MACsecOrch::crateMACsecSC( } task_process_status MACsecOrch::deleteMACsecSC( - const std::string & port_sci, + const std::string &port_sci, sai_int32_t direction) { SWSS_LOG_ENTER(); @@ -1102,19 +1318,31 @@ task_process_status MACsecOrch::deleteMACsecSC( return task_failed; } - auto port = m_macsec_ports.find(port_name); - if (port == m_macsec_ports.end()) + auto macsec_port = m_macsec_ports.find(port_name); + if (macsec_port == m_macsec_ports.end()) { SWSS_LOG_WARN("The MACsec port hasn't been created at the port %s.", port_name.c_str()); return task_failed; } - auto & scs = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_scs - : - port->second->m_ingress_scs; + sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; + if (!getGearboxSwitchId(port_name, switch_id)) + { + SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); + return task_failed; + } + + auto macsec_obj = m_macsec_objs.find(switch_id); + if (macsec_obj == m_macsec_objs.end()) + { + SWSS_LOG_INFO("The MACsec wasn't initialized at the switch %lu", switch_id); + return task_failed; + } + + auto &scs = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? macsec_port->second->m_egress_scs + : macsec_port->second->m_ingress_scs; auto sc = scs.find(sci); if (sc == scs.end()) { @@ -1124,41 +1352,29 @@ task_process_status MACsecOrch::deleteMACsecSC( auto result = task_success; - // If the SC is the only one SC of the direction at this port - // Change the ACL Entry action from flow action to packet action - if (scs.size() == 1) + for (macsec_an_t an = 0; an < sizeof(sc->second.m_sa_ids) / sizeof(sc->second.m_sa_ids[0]); an++) { - auto entry_id = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_acl_table.m_data_packet_entry_id - : - port->second->m_ingress_acl_table.m_data_packet_entry_id; - sai_object_id_t flow_id= - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_flow_id - : - port->second->m_ingress_flow_id; - if (!setACLEntryPacketAction(entry_id, flow_id)) + if (sc->second.m_sa_ids[an] != SAI_NULL_OBJECT_ID) { - SWSS_LOG_WARN("Cannot change the entry action from MACsec flow to packet action"); - result = task_failed; + const std::string port_sci_an = join(':', port_sci, an); + deleteMACsecSA(port_sci_an, direction); } } - for (macsec_an_t an = 0; an <= MAX_SA_NUMBER; an++) - { - const std::string port_sci_an = join(':', port_sci, an); - deleteMACsecSA(port_sci_an, direction); - } + deleteACLEntry(sc->second.m_entry_id); + auto &table = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? macsec_port->second->m_egress_acl_table + : macsec_port->second->m_ingress_acl_table; + table.m_available_acl_priorities.insert(sc->second.m_acl_priority); if (!deleteMACsecSC(sc->second.m_sc_id)) { SWSS_LOG_WARN("The MACsec SC %s cannot be deleted", port_sci.c_str()); result = task_failed; } - port->second->m_egress_scs.erase(sc); + macsec_port->second->m_egress_scs.erase(sc); + SWSS_LOG_NOTICE("MACsec SC %s is deleted.", port_sci.c_str()); if (direction == SAI_MACSEC_DIRECTION_EGRESS) @@ -1174,7 +1390,7 @@ task_process_status MACsecOrch::deleteMACsecSC( } bool MACsecOrch::createMACsecSC( - sai_object_id_t & sc_id, + sai_object_id_t &sc_id, sai_object_id_t switch_id, sai_int32_t direction, sai_object_id_t flow_id, @@ -1207,10 +1423,11 @@ bool MACsecOrch::createMACsecSC( attrs.push_back(attr); if (sai_macsec_api->create_macsec_sc( - &sc_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) { + &sc_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { SWSS_LOG_WARN("Cannot create MACsec egress SC %lu", sci); return false; } @@ -1222,15 +1439,16 @@ bool MACsecOrch::deleteMACsecSC(sai_object_id_t sc_id) SWSS_LOG_ENTER(); if (sai_macsec_api->remove_macsec_sc( - sc_id) != SAI_STATUS_SUCCESS) { + sc_id) != SAI_STATUS_SUCCESS) + { return false; } return true; } task_process_status MACsecOrch::createMACsecSA( - const std::string & port_sci_an, - const TaskArgs & sa_attr, + const std::string &port_sci_an, + const TaskArgs &sa_attr, sai_int32_t direction) { SWSS_LOG_ENTER(); @@ -1244,8 +1462,8 @@ task_process_status MACsecOrch::createMACsecSA( return task_failed; } - auto port = m_macsec_ports.find(port_name); - if (port == m_macsec_ports.end()) + auto macsec_port = m_macsec_ports.find(port_name); + if (macsec_port == m_macsec_ports.end()) { SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); return task_need_retry; @@ -1257,12 +1475,10 @@ task_process_status MACsecOrch::createMACsecSA( return task_failed; } - auto & scs = + auto &scs = (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_scs - : - port->second->m_ingress_scs; + ? macsec_port->second->m_egress_scs + : macsec_port->second->m_ingress_scs; auto sc = scs.find(sci); if (sc == scs.end()) { @@ -1294,7 +1510,7 @@ task_process_status MACsecOrch::createMACsecSA( return task_failed; } } - catch(const std::invalid_argument & e) + catch (const std::invalid_argument &e) { SWSS_LOG_WARN("Invalid argument : %s", e.what()); return task_failed; @@ -1317,23 +1533,42 @@ task_process_status MACsecOrch::createMACsecSA( } } + RecoverStack recover; + if (!createMACsecSA( - sc->second.m_sa_ids[an], - switch_id, - direction, - sc->second.m_sc_id, - an, - port->second->m_enable_encrypt, - sak.m_sak_256_enable, - sak.m_sak, - sc->second.m_xpn64_enable, - salt.m_salt, - auth_key.m_auth_key, - pn)) + sc->second.m_sa_ids[an], + switch_id, + direction, + sc->second.m_sc_id, + an, + macsec_port->second->m_enable_encrypt, + sak.m_sak_256_enable, + sak.m_sak, + sc->second.m_xpn64_enable, + salt.m_salt, + auth_key.m_auth_key, + pn)) { SWSS_LOG_WARN("Cannot create the SA %s", port_sci_an.c_str()); return task_failed; } + recover.add_action([&]() + { + deleteMACsecSA(sc->second.m_sa_ids[an]); + sc->second.m_sa_ids[an] = SAI_NULL_OBJECT_ID; + }); + + // If this SA is the first SA + // change the ACL entry action from packet action to MACsec flow + if (macsec_port->second->m_enable && get_active_sa_count(sc->second) == 1) + { + if (!setACLEntryMACsecFlow(sc->second.m_entry_id, sc->second.m_flow_id)) + { + SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); + return task_failed; + } + recover.add_action([&]() { setACLEntryPacketAction(sc->second.m_encoding_an, sc->second.m_flow_id); }); + } std::vector fvVector; fvVector.emplace_back("state", "ok"); @@ -1353,7 +1588,7 @@ task_process_status MACsecOrch::createMACsecSA( } task_process_status MACsecOrch::deleteMACsecSA( - const std::string & port_sci_an, + const std::string &port_sci_an, sai_int32_t direction) { SWSS_LOG_ENTER(); @@ -1367,25 +1602,23 @@ task_process_status MACsecOrch::deleteMACsecSA( return task_failed; } - auto port = m_macsec_ports.find(port_name); - if (port == m_macsec_ports.end()) + auto macsec_port = m_macsec_ports.find(port_name); + if (macsec_port == m_macsec_ports.end()) { SWSS_LOG_WARN("The MACsec port hasn't been created at the port %s.", port_name.c_str()); return task_failed; } - auto & scs = + auto &scs = (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? - port->second->m_egress_scs - : - port->second->m_ingress_scs; + ? macsec_port->second->m_egress_scs + : macsec_port->second->m_ingress_scs; auto sc = scs.find(sci); if (sc == scs.end()) { SWSS_LOG_WARN("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); - return task_failed; + return task_need_retry; } if (sc->second.m_sa_ids[an] == SAI_NULL_OBJECT_ID) @@ -1394,6 +1627,16 @@ task_process_status MACsecOrch::deleteMACsecSA( return task_failed; } + // If this SA is the last SA + // change the ACL entry action from MACsec flow to packet action + if (get_active_sa_count(sc->second) == 1) + { + if (!setACLEntryPacketAction(sc->second.m_entry_id, sc->second.m_flow_id)) + { + SWSS_LOG_WARN("Cannot change the ACL entry action from MACsec flow to packet action"); + } + } + uninstallCounter(port_sci_an, sc->second.m_sa_ids[an]); if (!deleteMACsecSA(sc->second.m_sa_ids[an])) { @@ -1415,19 +1658,18 @@ task_process_status MACsecOrch::deleteMACsecSA( } bool MACsecOrch::createMACsecSA( - sai_object_id_t & sa_id, - sai_object_id_t switch_id, - sai_int32_t direction, - sai_object_id_t sc_id, - macsec_an_t an, - bool encryption_enable, - bool sak_256_bit, - sai_macsec_sak_t sak, - bool xpn64_enable, - sai_macsec_salt_t salt, - sai_macsec_auth_key_t auth_key, - sai_uint64_t pn - ) + sai_object_id_t &sa_id, + sai_object_id_t switch_id, + sai_int32_t direction, + sai_object_id_t sc_id, + macsec_an_t an, + bool encryption_enable, + bool sak_256_bit, + sai_macsec_sak_t sak, + bool xpn64_enable, + sai_macsec_salt_t salt, + sai_macsec_auth_key_t auth_key, + sai_uint64_t pn) { SWSS_LOG_ENTER(); @@ -1483,10 +1725,10 @@ bool MACsecOrch::createMACsecSA( } if (sai_macsec_api->create_macsec_sa( - &sa_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) + &sa_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { return false; } @@ -1497,17 +1739,30 @@ bool MACsecOrch::deleteMACsecSA(sai_object_id_t sa_id) { SWSS_LOG_ENTER(); if (sai_macsec_api->remove_macsec_sa( - sa_id) != SAI_STATUS_SUCCESS) + sa_id) != SAI_STATUS_SUCCESS) { return false; } return true; } +std::uint8_t MACsecOrch::get_active_sa_count(const MACsecSC &sc) const +{ + std::uint8_t count = 0; + for (macsec_an_t an = 0; an < sizeof(sc.m_sa_ids) / sizeof(sc.m_sa_ids[0]); an++) + { + if (sc.m_sa_ids[an] != SAI_NULL_OBJECT_ID) + { + count++; + } + } + return count; +} + void MACsecOrch::installCounter( - const std::string & obj_name, + const std::string &obj_name, sai_object_id_t obj_id, - const std::vector & stats) + const std::vector &stats) { FieldValueTuple tuple(obj_name, sai_serialize_object_id(obj_id)); vector fields; @@ -1515,14 +1770,14 @@ void MACsecOrch::installCounter( m_macsec_counters_map.set("", fields); std::unordered_set counter_stats; - for (const auto& stat : stats) + for (const auto &stat : stats) { counter_stats.emplace(stat); } m_macsec_stat_manager.setCounterIdList(obj_id, CounterType::MACSEC, counter_stats); } -void MACsecOrch::uninstallCounter(const std::string & obj_name, sai_object_id_t obj_id) +void MACsecOrch::uninstallCounter(const std::string &obj_name, sai_object_id_t obj_id) { m_macsec_stat_manager.clearCounterIdList(obj_id); @@ -1531,80 +1786,100 @@ void MACsecOrch::uninstallCounter(const std::string & obj_name, sai_object_id_t } bool MACsecOrch::initACLTable( - ACLTable & acl_table, - const Port & port, + ACLTable &acl_table, + sai_object_id_t port_id, sai_object_id_t switch_id, - sai_int32_t direction) + sai_int32_t direction, + bool sci_in_sectag) { + SWSS_LOG_ENTER(); + RecoverStack recover; - if (!createACLTable(acl_table.m_table_id, switch_id, direction)) + if (acl_table.m_table_id != SAI_NULL_OBJECT_ID) + { + SWSS_LOG_INFO("The ACL table has been created"); + return true; + } + + if (!createACLTable(acl_table.m_table_id, switch_id, direction, sci_in_sectag)) { - SWSS_LOG_WARN("Cannot create ACL table at the port %s", port.m_alias.c_str()); + SWSS_LOG_WARN("Cannot create ACL table"); return false; } recover.add_action([&]() { deleteACLTable(acl_table.m_table_id); }); if (!createACLEAPOLEntry( - acl_table.m_eapol_packet_forward_entry_id, - acl_table.m_table_id, - switch_id)) + acl_table.m_eapol_packet_forward_entry_id, + acl_table.m_table_id, + switch_id)) { - SWSS_LOG_WARN("Cannot create ACL EAPOL entry at the port %s", port.m_alias.c_str()); + SWSS_LOG_WARN("Cannot create ACL EAPOL entry"); return false; } recover.add_action([&]() { deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id); }); - if (!createACLDataEntry( - acl_table.m_data_packet_entry_id, - acl_table.m_table_id, - switch_id)) + if (!bindACLTabletoPort(acl_table.m_table_id, port_id)) { - SWSS_LOG_WARN("Cannot create ACL entry at the port %s", port.m_alias.c_str()); + SWSS_LOG_WARN("Cannot bind ACL table"); return false; } - recover.add_action([&]() { deleteACLEntry(acl_table.m_data_packet_entry_id); }); + recover.add_action([&]() { unbindACLTable(port_id); }); - if (!bindACLTabletoPort(acl_table.m_table_id, port.m_line_port_id)) + sai_uint32_t minimum_priority; + if (!get_acl_minimum_priority(switch_id, minimum_priority)) { - SWSS_LOG_WARN("Cannot bind ACL table to the port %s", port.m_alias.c_str()); return false; } - recover.add_action([&]() { unbindACLTable(port.m_line_port_id); }); + sai_uint32_t maximum_priority; + if (!get_acl_maximum_priority(switch_id, maximum_priority)) + { + return false; + } + sai_uint32_t priority = minimum_priority + 1; + while (priority < maximum_priority) + { + acl_table.m_available_acl_priorities.insert(priority); + priority += 1; + } recover.clear(); return true; } -bool MACsecOrch::deinitACLTable(ACLTable & acl_table, const Port & port) +bool MACsecOrch::deinitACLTable(ACLTable &acl_table, sai_object_id_t port_id) { bool result = true; - if (!unbindACLTable(port.m_line_port_id)) + if (!unbindACLTable(port_id)) { - SWSS_LOG_WARN("Cannot unbind ACL table at the port %s", port.m_alias.c_str()); - result &= false; - } - if (!deleteACLEntry(acl_table.m_data_packet_entry_id)) - { - SWSS_LOG_WARN("Cannot delete ACL entry at the port %s", port.m_alias.c_str()); + SWSS_LOG_WARN("Cannot unbind ACL table"); result &= false; } + // if (!deleteACLEntry(acl_table.m_data_packet_entry_id)) + // { + // SWSS_LOG_WARN("Cannot delete ACL entry at the port %s", port.m_alias.c_str()); + // result &= false; + // } if (!deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id)) { - SWSS_LOG_WARN("Cannot delete ACL entry at the port %s", port.m_alias.c_str()); + SWSS_LOG_WARN("Cannot delete ACL entry"); result &= false; } if (!deleteACLTable(acl_table.m_table_id)) { - SWSS_LOG_WARN("Cannot delete ACL table at the port %s", port.m_alias.c_str()); + SWSS_LOG_WARN("Cannot delete ACL table"); result &= false; } return result; } -bool MACsecOrch::createACLTable(sai_object_id_t & table_id, sai_object_id_t switch_id, sai_int32_t direction) +bool MACsecOrch::createACLTable( + sai_object_id_t &table_id, + sai_object_id_t switch_id, + sai_int32_t direction, + bool sci_in_sectag) { sai_attribute_t attr; std::vector attrs; @@ -1622,7 +1897,7 @@ bool MACsecOrch::createACLTable(sai_object_id_t & table_id, sai_object_id_t swit attrs.push_back(attr); attr.id = SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST; - vector bpoint_list = { SAI_ACL_BIND_POINT_TYPE_PORT }; + vector bpoint_list = {SAI_ACL_BIND_POINT_TYPE_PORT}; attr.value.s32list.count = static_cast(bpoint_list.size()); attr.value.s32list.list = bpoint_list.data(); attrs.push_back(attr); @@ -1635,11 +1910,16 @@ bool MACsecOrch::createACLTable(sai_object_id_t & table_id, sai_object_id_t swit attr.value.booldata = true; attrs.push_back(attr); + attr.id = SAI_ACL_TABLE_ATTR_FIELD_MACSEC_SCI; + attr.value.booldata = sci_in_sectag; + attrs.push_back(attr); + if (sai_acl_api->create_acl_table( - &table_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) { + &table_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { return false; } return true; @@ -1647,7 +1927,8 @@ bool MACsecOrch::createACLTable(sai_object_id_t & table_id, sai_object_id_t swit bool MACsecOrch::deleteACLTable(sai_object_id_t table_id) { - if (sai_acl_api->remove_acl_table(table_id) != SAI_STATUS_SUCCESS) { + if (sai_acl_api->remove_acl_table(table_id) != SAI_STATUS_SUCCESS) + { return false; } return true; @@ -1661,8 +1942,9 @@ bool MACsecOrch::bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t po attr.value.oid = table_id; if (sai_port_api->set_port_attribute( - port_id, - &attr) != SAI_STATUS_SUCCESS) { + port_id, + &attr) != SAI_STATUS_SUCCESS) + { return false; } return true; @@ -1676,15 +1958,16 @@ bool MACsecOrch::unbindACLTable(sai_object_id_t port_id) attr.value.oid = SAI_NULL_OBJECT_ID; if (sai_port_api->set_port_attribute( - port_id, - &attr) != SAI_STATUS_SUCCESS) { + port_id, + &attr) != SAI_STATUS_SUCCESS) + { return false; } return true; } bool MACsecOrch::createACLEAPOLEntry( - sai_object_id_t & entry_id, + sai_object_id_t &entry_id, sai_object_id_t table_id, sai_object_id_t switch_id) { @@ -1695,7 +1978,10 @@ bool MACsecOrch::createACLEAPOLEntry( attr.value.oid = table_id; attrs.push_back(attr); attr.id = SAI_ACL_ENTRY_ATTR_PRIORITY; - attr.value.u32 = 100; + if (!get_acl_maximum_priority(switch_id, attr.value.u32)) + { + return false; + } attrs.push_back(attr); attr.id = SAI_ACL_ENTRY_ATTR_ADMIN_STATE; attr.value.booldata = true; @@ -1718,19 +2004,23 @@ bool MACsecOrch::createACLEAPOLEntry( attr.value.aclaction.enable = true; attrs.push_back(attr); if (sai_acl_api->create_acl_entry( - &entry_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) { + &entry_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { return false; } return true; } bool MACsecOrch::createACLDataEntry( - sai_object_id_t & entry_id, + sai_object_id_t &entry_id, sai_object_id_t table_id, - sai_object_id_t switch_id) + sai_object_id_t switch_id, + bool sci_in_sectag, + sai_uint64_t sci, + sai_uint32_t priority) { sai_attribute_t attr; std::vector attrs; @@ -1739,7 +2029,7 @@ bool MACsecOrch::createACLDataEntry( attr.value.oid = table_id; attrs.push_back(attr); attr.id = SAI_ACL_ENTRY_ATTR_PRIORITY; - attr.value.u32 = 1; + attr.value.u32 = priority; attrs.push_back(attr); attr.id = SAI_ACL_ENTRY_ATTR_ADMIN_STATE; attr.value.booldata = true; @@ -1748,11 +2038,21 @@ bool MACsecOrch::createACLDataEntry( attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_DROP; attr.value.aclaction.enable = true; attrs.push_back(attr); + attr.id = SAI_ACL_TABLE_ATTR_FIELD_MACSEC_SCI; + attr.value.booldata = sci_in_sectag; + attrs.push_back(attr); + if (sci_in_sectag) + { + attr.id = SAI_ACL_ENTRY_ATTR_FIELD_MACSEC_SCI; + attr.value.u64 = sci; + attrs.push_back(attr); + } if (sai_acl_api->create_acl_entry( - &entry_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) { + &entry_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { return false; } return true; @@ -1765,8 +2065,9 @@ bool MACsecOrch::setACLEntryPacketAction(sai_object_id_t entry_id, sai_object_id attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; attr.value.aclaction.enable = true; if (sai_acl_api->set_acl_entry_attribute( - entry_id, - &attr) != SAI_STATUS_SUCCESS) { + entry_id, + &attr) != SAI_STATUS_SUCCESS) + { return false; } @@ -1775,8 +2076,9 @@ bool MACsecOrch::setACLEntryPacketAction(sai_object_id_t entry_id, sai_object_id attr.value.aclaction.enable = false; if (sai_acl_api->set_acl_entry_attribute( - entry_id, - &attr) != SAI_STATUS_SUCCESS) { + entry_id, + &attr) != SAI_STATUS_SUCCESS) + { return false; } return true; @@ -1791,16 +2093,18 @@ bool MACsecOrch::setACLEntryMACsecFlow(sai_object_id_t entry_id, sai_object_id_t attr.value.aclaction.enable = true; if (sai_acl_api->set_acl_entry_attribute( - entry_id, - &attr) != SAI_STATUS_SUCCESS) { + entry_id, + &attr) != SAI_STATUS_SUCCESS) + { return false; } attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; attr.value.aclaction.enable = false; if (sai_acl_api->set_acl_entry_attribute( - entry_id, - &attr) != SAI_STATUS_SUCCESS) { + entry_id, + &attr) != SAI_STATUS_SUCCESS) + { return false; } @@ -1810,8 +2114,64 @@ bool MACsecOrch::setACLEntryMACsecFlow(sai_object_id_t entry_id, sai_object_id_t bool MACsecOrch::deleteACLEntry(sai_object_id_t entry_id) { if (sai_acl_api->remove_acl_entry( - entry_id) != SAI_STATUS_SUCCESS) { + entry_id) != SAI_STATUS_SUCCESS) + { return false; } return true; } + +bool MACsecOrch::get_acl_maximum_priority(sai_object_id_t switch_id, sai_uint32_t &priority) const +{ + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY; + attrs.push_back(attr); + if (sai_switch_api->get_switch_attribute( + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Cannot fetch ACL maximum Priority from switch"); + return false; + } + priority = attrs.front().value.u32; + + return true; +} + +bool MACsecOrch::get_acl_minimum_priority(sai_object_id_t switch_id, sai_uint32_t &priority) const +{ + sai_attribute_t attr; + std::vector attrs; + + attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY; + attrs.push_back(attr); + if (sai_switch_api->get_switch_attribute( + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Cannot fetch ACL maximum Priority from switch"); + return false; + } + priority = attrs.front().value.u32; + + return true; +} + +static void wait_break() +{ + std::this_thread::sleep_for(std::chrono::milliseconds(10)); +} + +void break_point() +{ + int state = 1; + while (state != 0) + { + wait_break(); + } +} + diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index e01495cd3f..e2b6409806 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -26,25 +26,11 @@ #include +#include #include #include #include - -#undef SWSS_LOG_ERROR -#undef SWSS_LOG_WARN -#undef SWSS_LOG_NOTICE -#undef SWSS_LOG_INFO -#undef SWSS_LOG_DEBUG -#undef SWSS_LOG_ENTER - -#define SWSS_LOG_ERROR(MSG, ...) printf("ERROR %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -#define SWSS_LOG_WARN(MSG, ...) printf("WARN %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -#define SWSS_LOG_NOTICE(MSG, ...) printf("NOTICE %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -#define SWSS_LOG_INFO(MSG, ...) printf("INFO %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -#define SWSS_LOG_DEBUG(MSG, ...) printf("DEBUG %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -#define SWSS_LOG_ENTER() printf("ENTER %s : - %s : %d\n", __FILE__, __FUNCTION__, __LINE__) - using namespace swss; // AN is a 2 bit number, it can only be 0, 1, 2 or 3 @@ -70,7 +56,7 @@ class MACsecOrch : public Orch private: - task_process_status enableMACsecPort(const std::string & port_name, const TaskArgs & port_attr); + task_process_status updateMACsecPort(const std::string & port_name, const TaskArgs & port_attr); task_process_status disableMACsecPort(const std::string & port_name, const TaskArgs & port_attr); task_process_status updateEgressSC(const std::string & port_sci, const TaskArgs & sc_attr); task_process_status deleteEgressSC(const std::string & port_sci, const TaskArgs & sc_attr); @@ -99,9 +85,9 @@ class MACsecOrch : public Orch map m_gearbox_interface_map; struct ACLTable { - sai_object_id_t m_table_id; - sai_object_id_t m_eapol_packet_forward_entry_id; - sai_object_id_t m_data_packet_entry_id; + sai_object_id_t m_table_id; + sai_object_id_t m_eapol_packet_forward_entry_id; + std::set m_available_acl_priorities; }; struct MACsecSC { @@ -109,6 +95,9 @@ class MACsecOrch : public Orch bool m_xpn64_enable; sai_object_id_t m_sc_id; sai_object_id_t m_sa_ids[MAX_SA_NUMBER + 1]; + sai_object_id_t m_flow_id; + sai_object_id_t m_entry_id; + sai_uint32_t m_acl_priority; }; struct MACsecPort { @@ -118,51 +107,67 @@ class MACsecOrch : public Orch sai_object_id_t m_ingress_flow_id; std::map m_egress_scs; std::map m_ingress_scs; - bool m_enable_encrypt; ACLTable m_egress_acl_table; ACLTable m_ingress_acl_table; + bool m_enable_encrypt; + bool m_sci_in_sectag; + bool m_enable; }; struct MACsecObject { sai_object_id_t m_egress_id; sai_object_id_t m_ingress_id; map > m_ports; + bool m_sci_in_ingress_macsec_acl; }; map m_macsec_objs; map > m_macsec_ports; bool initGearbox(); - bool getGearboxSwitchId(const Port & port, sai_object_id_t & switch_id) const; - bool getGearboxSwitchId(const std::string & port_name, sai_object_id_t & switch_id) const; + bool getGearboxSwitchId(const Port &port, sai_object_id_t &switch_id) const; + bool getGearboxSwitchId(const std::string &port_name, sai_object_id_t &switch_id) const; + /* MACsec Object */ map::iterator initMACsecObject(sai_object_id_t switch_id); bool deinitMACsecObject(map::iterator switch_id); bool deinitMACsecObject(sai_object_id_t switch_id); - std::shared_ptr createMACsecPort(const Port & port, sai_object_id_t switch_id); - bool deleteMACsecPort(const std::string & port_name); + /* MACsec Port */ + std::shared_ptr createMACsecPort( + const std::string &port_name, + sai_object_id_t port_id, + sai_object_id_t switch_id); + bool deleteMACsecPort(const std::string &port_name); + + /* MACsec Flow */ + bool createMACsecFlow( + sai_object_id_t &flow_id, + sai_object_id_t switch_id, + sai_int32_t direction); + bool deleteMACsecFlow(sai_object_id_t flow_id); + /* MACsec SC */ task_process_status updateMACsecSC( - const std::string & port_sci, - const TaskArgs & sc_attr, + const std::string &port_sci, + const TaskArgs &sc_attr, sai_int32_t direction); task_process_status setEncodingAN( MACsecSC &sc, - const TaskArgs & sc_attr, + const TaskArgs &sc_attr, sai_int32_t direction); - task_process_status crateMACsecSC( - MACsecSC &sc, - const std::string & port_name, - const TaskArgs & sc_attr, + task_process_status createMACsecSC( + MACsecPort &macsec_port, + const std::string &port_name, + const TaskArgs &sc_attr, + const MACsecObject &macsec_obj, sai_uint64_t sci, - sai_object_id_t flow_id, sai_object_id_t switch_id, sai_int32_t direction); task_process_status deleteMACsecSC( - const std::string & port_sci, + const std::string &port_sci, sai_int32_t direction); bool createMACsecSC( - sai_object_id_t & sc_id, + sai_object_id_t &sc_id, sai_object_id_t switch_id, sai_int32_t direction, sai_object_id_t flow_id, @@ -171,15 +176,16 @@ class MACsecOrch : public Orch bool xpn64_enable); bool deleteMACsecSC(sai_object_id_t sc_id); + /* MACsec SA */ task_process_status createMACsecSA( - const std::string & port_sci_an, - const TaskArgs & sa_attr, + const std::string &port_sci_an, + const TaskArgs &sa_attr, sai_int32_t direction); task_process_status deleteMACsecSA( - const std::string & port_sci_an, + const std::string &port_sci_an, sai_int32_t direction); bool createMACsecSA( - sai_object_id_t & sa_id, + sai_object_id_t &sa_id, sai_object_id_t switch_id, sai_int32_t direction, sai_object_id_t sc_id, @@ -190,37 +196,46 @@ class MACsecOrch : public Orch bool xpn64_enable, sai_macsec_salt_t salt, sai_macsec_auth_key_t auth_key, - sai_uint64_t pn - ); + sai_uint64_t pn); bool deleteMACsecSA(sai_object_id_t sa_id); + std::uint8_t get_active_sa_count(const MACsecSC &sc) const; + /* Counter */ void installCounter( - const std::string & obj_name, + const std::string &obj_name, sai_object_id_t obj_id, - const std::vector & stats); - void uninstallCounter(const std::string & obj_name, sai_object_id_t obj_id); + const std::vector &stats); + void uninstallCounter(const std::string &obj_name, sai_object_id_t obj_id); + /* ACL */ bool initACLTable( - ACLTable & acl_table, - const Port & port, + ACLTable &acl_table, + sai_object_id_t port_id, sai_object_id_t switch_id, - sai_int32_t direction); - bool deinitACLTable(ACLTable & acl_table, const Port & port); + sai_int32_t direction, + bool sci_in_sectag); + bool deinitACLTable( + ACLTable &acl_table, + sai_object_id_t port_id); bool createACLTable( - sai_object_id_t & table_id, + sai_object_id_t &table_id, sai_object_id_t switch_id, - sai_int32_t direction); + sai_int32_t direction, + bool sci_in_sectag); bool deleteACLTable(sai_object_id_t table_id); bool bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t port_id); bool unbindACLTable(sai_object_id_t port_id); bool createACLEAPOLEntry( - sai_object_id_t & entry_id, + sai_object_id_t &entry_id, sai_object_id_t table_id, sai_object_id_t switch_id); bool createACLDataEntry( - sai_object_id_t & entry_id, + sai_object_id_t &entry_id, sai_object_id_t table_id, - sai_object_id_t switch_id); + sai_object_id_t switch_id, + bool sci_in_sectag, + sai_uint64_t sci, + sai_uint32_t priority); bool setACLEntryPacketAction( sai_object_id_t entry_id, sai_object_id_t flow_id); @@ -228,6 +243,30 @@ class MACsecOrch : public Orch sai_object_id_t entry_id, sai_object_id_t flow_id); bool deleteACLEntry(sai_object_id_t entry_id); + bool get_acl_maximum_priority( + sai_object_id_t switch_id, + sai_uint32_t &priority) const; + bool get_acl_minimum_priority( + sai_object_id_t switch_id, + sai_uint32_t &priority) const; }; -#endif +// The following code is only for debugging + +// #undef SWSS_LOG_ERROR +// #undef SWSS_LOG_WARN +// #undef SWSS_LOG_NOTICE +// #undef SWSS_LOG_INFO +// #undef SWSS_LOG_DEBUG +// #undef SWSS_LOG_ENTER + +// #define SWSS_LOG_ERROR(MSG, ...) printf("ERROR %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +// #define SWSS_LOG_WARN(MSG, ...) printf("WARN %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +// #define SWSS_LOG_NOTICE(MSG, ...) printf("NOTICE %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +// #define SWSS_LOG_INFO(MSG, ...) printf("INFO %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +// #define SWSS_LOG_DEBUG(MSG, ...) printf("DEBUG %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) +// #define SWSS_LOG_ENTER() printf("ENTER %s : - %s : %d\n", __FILE__, __FUNCTION__, __LINE__) + +void break_point(); + +#endif // ORCHAGENT_MACSECORCH_H_ From 17d40af83ac464215a3ee449bb255065d2b609c5 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 4 Sep 2020 23:45:21 +0800 Subject: [PATCH 04/31] Fix bug Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 218 +++++++++++++++++++++++---------------- orchagent/macsecorch.h | 15 ++- 2 files changed, 134 insertions(+), 99 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 854edef74b..8a84e9a7cc 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -33,7 +33,7 @@ struct MockSAIAPI } if (attr_list[0].id == SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY) { - attr_list[0].value.u32 = 100; + attr_list[0].value.u32 = 5; } else if (attr_list[0].id == SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY) { @@ -83,8 +83,11 @@ static MockSAIAPI * sai_switch_api = &mock_api; #define MOCK_RETURN_BOOL return true; +/* Finish Debug */ + /* Global Variables*/ +#define PRIORITY_LIMITATION 32 #define EAPOL_ETHER_TYPE 0x888e #define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000 @@ -301,23 +304,23 @@ struct MACsecAuthKey sai_macsec_auth_key_t m_auth_key; }; -static std::istringstream &operator>>( - std::istringstream &istream, - MACsecAuthKey &auth_key) -{ - SWSS_LOG_ENTER(); - const std::string &buffer = istream.str(); - - if ( - (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!hex_to_binary( - buffer, - auth_key.m_auth_key, - sizeof(auth_key.m_auth_key)))) - { - throw std::invalid_argument("Invalid Auth Key : " + buffer); - } - return istream; -} +// static std::istringstream &operator>>( +// std::istringstream &istream, +// MACsecAuthKey &auth_key) +// { +// SWSS_LOG_ENTER(); +// const std::string &buffer = istream.str(); + +// if ( +// (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!hex_to_binary( +// buffer, +// auth_key.m_auth_key, +// sizeof(auth_key.m_auth_key)))) +// { +// throw std::invalid_argument("Invalid Auth Key : " + buffer); +// } +// return istream; +// } /* Recover from a fail action by a serial of pre-defined recover actions */ class RecoverStack @@ -641,14 +644,21 @@ task_process_status MACsecOrch::disableMACsecPort( return task_success; } + task_process_status result = task_success; + Port port; if (!m_port_orch->getPort(port_name, port)) { - SWSS_LOG_INFO("Port %s cannot be found.", port_name.c_str()); - return task_success; + SWSS_LOG_ERROR("Port %s cannot be found.", port_name.c_str()); + return task_failed; } - task_process_status result = task_success; + auto macsec_obj = m_macsec_objs.find(switch_id); + if (macsec_obj == m_macsec_objs.end()) + { + SWSS_LOG_ERROR("The MACsec wasn't initialized at the switch %lu", switch_id); + result = task_failed; + } if (!deinitACLTable(macsec_port->second->m_ingress_acl_table, port.m_line_port_id)) { @@ -662,13 +672,26 @@ task_process_status MACsecOrch::disableMACsecPort( result = task_failed; } + if (!macsec_obj->second.m_sci_in_ingress_macsec_acl) + { + if (!deleteMACsecFlow(macsec_port->second->m_egress_flow_id)) + { + SWSS_LOG_WARN("Cannot delete the MACsec egress flow at the port %s.", port_name.c_str()); + result = task_failed; + } + if (!deleteMACsecFlow(macsec_port->second->m_ingress_flow_id)) + { + SWSS_LOG_WARN("Cannot delete the MACsec ingress flow at the port %s.", port_name.c_str()); + result = task_failed; + } + } + if (!deleteMACsecPort(port_name)) { SWSS_LOG_WARN("Cannot delete macsec port at the port %s.", port_name.c_str()); result = task_failed; } - auto macsec_obj = m_macsec_objs.find(switch_id); if (macsec_obj != m_macsec_objs.end()) { macsec_obj->second.m_ports.erase(port_name); @@ -726,8 +749,8 @@ task_process_status MACsecOrch::updateEgressSA( { SWSS_LOG_ENTER(); std::string port_name; - sai_uint64_t sci; - macsec_an_t an; + sai_uint64_t sci = 0; + macsec_an_t an = 0; if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); @@ -737,8 +760,7 @@ task_process_status MACsecOrch::updateEgressSA( if (port == m_macsec_ports.end()) { SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); - // return task_need_retry; - return task_failed; + return task_need_retry; } auto sc = port->second->m_egress_scs.find(sci); if (sc == port->second->m_egress_scs.end()) @@ -758,8 +780,15 @@ task_process_status MACsecOrch::deleteEgressSA( const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); - return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_EGRESS); - ; + auto result = deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_EGRESS); + if (result == task_success) + { + return task_success; + } + else + { + return task_failed; + } } task_process_status MACsecOrch::updateIngressSA( @@ -781,8 +810,6 @@ task_process_status MACsecOrch::updateIngressSA( { return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); } - - return task_success; } task_process_status MACsecOrch::deleteIngressSA( @@ -790,7 +817,15 @@ task_process_status MACsecOrch::deleteIngressSA( const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); - return task_success; + auto result = deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); + if (result == task_success) + { + return task_success; + } + else + { + return task_failed; + } } bool MACsecOrch::initGearbox() @@ -1052,7 +1087,9 @@ bool MACsecOrch::deleteMACsecPort(const std::string &port_name) SWSS_LOG_WARN("Cannot delete MACsec ingress port at the port %s", port_name.c_str()); result &= false; } - + // TODO + // If m_sci_in_ingress_macsec_acl + // { if (sai_macsec_api->remove_macsec_flow( macsec_port->second->m_egress_flow_id) != SAI_STATUS_SUCCESS) { @@ -1066,6 +1103,7 @@ bool MACsecOrch::deleteMACsecPort(const std::string &port_name) SWSS_LOG_WARN("Cannot delete MACsec ingress flow at the port %s", port_name.c_str()); result &= false; } + // } m_macsec_ports.erase(macsec_port); return true; @@ -1118,15 +1156,15 @@ task_process_status MACsecOrch::updateMACsecSC( SWSS_LOG_ENTER(); std::string port_name; - sai_uint64_t sci; + sai_uint64_t sci = {0}; if (!split(port_sci, ':', port_name, sci)) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci.c_str()); return task_failed; } - auto m_macsec_port = m_macsec_ports.find(port_name); - if (m_macsec_port == m_macsec_ports.end()) + auto macsec_port = m_macsec_ports.find(port_name); + if (macsec_port == m_macsec_ports.end()) { SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); return task_need_retry; @@ -1134,21 +1172,21 @@ task_process_status MACsecOrch::updateMACsecSC( sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; if (!getGearboxSwitchId(port_name, switch_id)) { - SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); + SWSS_LOG_ERROR("Cannot find gearbox at the port %s.", port_name.c_str()); return task_failed; } auto macsec_obj = m_macsec_objs.find(switch_id); if (macsec_obj == m_macsec_objs.end()) { - SWSS_LOG_INFO("The MACsec wasn't initialized at the switch %lu", switch_id); + SWSS_LOG_ERROR("The MACsec wasn't initialized at the switch %lu", switch_id); return task_failed; } auto &scs = (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? m_macsec_port->second->m_egress_scs - : m_macsec_port->second->m_ingress_scs; + ? macsec_port->second->m_egress_scs + : macsec_port->second->m_ingress_scs; auto sc = scs.find(sci); // If SC has been created if (sc != scs.end()) @@ -1157,7 +1195,7 @@ task_process_status MACsecOrch::updateMACsecSC( } return createMACsecSC( - *(m_macsec_port->second), + *(macsec_port->second), port_name, sc_attr, macsec_obj->second, @@ -1215,7 +1253,7 @@ task_process_status MACsecOrch::createMACsecSC( recover.add_action([&]() { scs.erase(sc_itr.first->first); }); auto &sc = sc_itr.first->second; - sai_uint32_t ssci; + sai_uint32_t ssci = 0; sc.m_xpn64_enable = false; if (get_value(sc_attr, "ssci", ssci) && ssci) { @@ -1301,6 +1339,8 @@ task_process_status MACsecOrch::createMACsecSC( { m_state_macsec_ingress_sc.set(join('|', port_name, sci), fvVector); } + + recover.clear(); return task_success; } @@ -1311,7 +1351,7 @@ task_process_status MACsecOrch::deleteMACsecSC( SWSS_LOG_ENTER(); std::string port_name; - sai_uint64_t sci; + sai_uint64_t sci = {0}; if (!split(port_sci, ':', port_name, sci)) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci.c_str()); @@ -1335,7 +1375,7 @@ task_process_status MACsecOrch::deleteMACsecSC( auto macsec_obj = m_macsec_objs.find(switch_id); if (macsec_obj == m_macsec_objs.end()) { - SWSS_LOG_INFO("The MACsec wasn't initialized at the switch %lu", switch_id); + SWSS_LOG_WARN("The MACsec wasn't initialized at the switch %lu", switch_id); return task_failed; } @@ -1352,13 +1392,10 @@ task_process_status MACsecOrch::deleteMACsecSC( auto result = task_success; - for (macsec_an_t an = 0; an < sizeof(sc->second.m_sa_ids) / sizeof(sc->second.m_sa_ids[0]); an++) + for (auto &sa : sc->second.m_sa_ids) { - if (sc->second.m_sa_ids[an] != SAI_NULL_OBJECT_ID) - { - const std::string port_sci_an = join(':', port_sci, an); - deleteMACsecSA(port_sci_an, direction); - } + const std::string port_sci_an = join(':', port_sci, sa.first); + deleteMACsecSA(port_sci_an, direction); } deleteACLEntry(sc->second.m_entry_id); @@ -1368,12 +1405,21 @@ task_process_status MACsecOrch::deleteMACsecSC( : macsec_port->second->m_ingress_acl_table; table.m_available_acl_priorities.insert(sc->second.m_acl_priority); + if (!macsec_obj->second.m_sci_in_ingress_macsec_acl) + { + if (deleteMACsecFlow(sc->second.m_flow_id)) + { + SWSS_LOG_WARN("Cannot delete MACsec flow"); + result = task_failed; + } + } + if (!deleteMACsecSC(sc->second.m_sc_id)) { SWSS_LOG_WARN("The MACsec SC %s cannot be deleted", port_sci.c_str()); result = task_failed; } - macsec_port->second->m_egress_scs.erase(sc); + scs.erase(sc); SWSS_LOG_NOTICE("MACsec SC %s is deleted.", port_sci.c_str()); @@ -1454,8 +1500,8 @@ task_process_status MACsecOrch::createMACsecSA( SWSS_LOG_ENTER(); std::string port_name; - sai_uint64_t sci; - macsec_an_t an; + sai_uint64_t sci = 0; + macsec_an_t an = 0; if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); @@ -1486,9 +1532,9 @@ task_process_status MACsecOrch::createMACsecSA( return task_need_retry; } - MACsecSAK sak; - MACsecSalt salt; - MACsecAuthKey auth_key; + MACsecSAK sak = {{0}, false}; + MACsecSalt salt = {0}; + MACsecAuthKey auth_key = {0}; try { if (!get_value(sa_attr, "sak", sak)) @@ -1504,18 +1550,19 @@ task_process_status MACsecOrch::createMACsecSA( return task_failed; } } - if (!get_value(sa_attr, "auth_key", auth_key)) - { - SWSS_LOG_WARN("The auth key isn't existed at SA %s", port_sci_an.c_str()); - return task_failed; - } + // TODO Auth Key + // if (!get_value(sa_attr, "auth_key", auth_key)) + // { + // SWSS_LOG_WARN("The auth key isn't existed at SA %s", port_sci_an.c_str()); + // return task_failed; + // } } catch (const std::invalid_argument &e) { SWSS_LOG_WARN("Invalid argument : %s", e.what()); return task_failed; } - sai_uint64_t pn; + sai_uint64_t pn = 1; if (direction == SAI_MACSEC_DIRECTION_EGRESS) { if (!get_value(sa_attr, "init_pn", pn)) @@ -1555,12 +1602,12 @@ task_process_status MACsecOrch::createMACsecSA( recover.add_action([&]() { deleteMACsecSA(sc->second.m_sa_ids[an]); - sc->second.m_sa_ids[an] = SAI_NULL_OBJECT_ID; + sc->second.m_sa_ids.erase(an); }); // If this SA is the first SA // change the ACL entry action from packet action to MACsec flow - if (macsec_port->second->m_enable && get_active_sa_count(sc->second) == 1) + if (macsec_port->second->m_enable && sc->second.m_sa_ids.size() == 1) { if (!setACLEntryMACsecFlow(sc->second.m_entry_id, sc->second.m_flow_id)) { @@ -1584,6 +1631,8 @@ task_process_status MACsecOrch::createMACsecSA( } SWSS_LOG_NOTICE("MACsec SA %s is created.", port_sci_an.c_str()); + + recover.clear(); return task_success; } @@ -1593,9 +1642,9 @@ task_process_status MACsecOrch::deleteMACsecSA( { SWSS_LOG_ENTER(); - std::string port_name; - sai_uint64_t sci; - macsec_an_t an; + std::string port_name = ""; + sai_uint64_t sci = 0; + macsec_an_t an = 0; if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); @@ -1606,7 +1655,7 @@ task_process_status MACsecOrch::deleteMACsecSA( if (macsec_port == m_macsec_ports.end()) { SWSS_LOG_WARN("The MACsec port hasn't been created at the port %s.", port_name.c_str()); - return task_failed; + return task_need_retry; } auto &scs = @@ -1621,15 +1670,15 @@ task_process_status MACsecOrch::deleteMACsecSA( return task_need_retry; } - if (sc->second.m_sa_ids[an] == SAI_NULL_OBJECT_ID) + if (sc->second.m_sa_ids.find(an) == sc->second.m_sa_ids.end()) { SWSS_LOG_WARN("The MACsec SA %s hasn't been created.", port_sci_an.c_str()); - return task_failed; + return task_need_retry; } // If this SA is the last SA // change the ACL entry action from MACsec flow to packet action - if (get_active_sa_count(sc->second) == 1) + if (sc->second.m_sa_ids.size() == 1) { if (!setACLEntryPacketAction(sc->second.m_entry_id, sc->second.m_flow_id)) { @@ -1642,7 +1691,7 @@ task_process_status MACsecOrch::deleteMACsecSA( { SWSS_LOG_WARN("Cannot delete the MACsec SA %s.", port_sci_an.c_str()); } - sc->second.m_sa_ids[an] = SAI_NULL_OBJECT_ID; + sc->second.m_sa_ids.erase(an); if (direction == SAI_MACSEC_DIRECTION_EGRESS) { @@ -1746,19 +1795,6 @@ bool MACsecOrch::deleteMACsecSA(sai_object_id_t sa_id) return true; } -std::uint8_t MACsecOrch::get_active_sa_count(const MACsecSC &sc) const -{ - std::uint8_t count = 0; - for (macsec_an_t an = 0; an < sizeof(sc.m_sa_ids) / sizeof(sc.m_sa_ids[0]); an++) - { - if (sc.m_sa_ids[an] != SAI_NULL_OBJECT_ID) - { - count++; - } - } - return count; -} - void MACsecOrch::installCounter( const std::string &obj_name, sai_object_id_t obj_id, @@ -1826,19 +1862,24 @@ bool MACsecOrch::initACLTable( } recover.add_action([&]() { unbindACLTable(port_id); }); - sai_uint32_t minimum_priority; + sai_uint32_t minimum_priority = 0; if (!get_acl_minimum_priority(switch_id, minimum_priority)) { return false; } - sai_uint32_t maximum_priority; + sai_uint32_t maximum_priority = 0; if (!get_acl_maximum_priority(switch_id, maximum_priority)) { return false; } + sai_uint32_t priority = minimum_priority + 1; while (priority < maximum_priority) { + if (acl_table.m_available_acl_priorities.size() >= PRIORITY_LIMITATION) + { + break; + } acl_table.m_available_acl_priorities.insert(priority); priority += 1; } @@ -1856,11 +1897,6 @@ bool MACsecOrch::deinitACLTable(ACLTable &acl_table, sai_object_id_t port_id) SWSS_LOG_WARN("Cannot unbind ACL table"); result &= false; } - // if (!deleteACLEntry(acl_table.m_data_packet_entry_id)) - // { - // SWSS_LOG_WARN("Cannot delete ACL entry at the port %s", port.m_alias.c_str()); - // result &= false; - // } if (!deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id)) { SWSS_LOG_WARN("Cannot delete ACL entry"); diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index e2b6409806..ca7169d8d2 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -91,13 +91,13 @@ class MACsecOrch : public Orch }; struct MACsecSC { - sai_uint8_t m_encoding_an; - bool m_xpn64_enable; - sai_object_id_t m_sc_id; - sai_object_id_t m_sa_ids[MAX_SA_NUMBER + 1]; - sai_object_id_t m_flow_id; - sai_object_id_t m_entry_id; - sai_uint32_t m_acl_priority; + macsec_an_t m_encoding_an; + bool m_xpn64_enable; + sai_object_id_t m_sc_id; + std::map m_sa_ids; + sai_object_id_t m_flow_id; + sai_object_id_t m_entry_id; + sai_uint32_t m_acl_priority; }; struct MACsecPort { @@ -198,7 +198,6 @@ class MACsecOrch : public Orch sai_macsec_auth_key_t auth_key, sai_uint64_t pn); bool deleteMACsecSA(sai_object_id_t sa_id); - std::uint8_t get_active_sa_count(const MACsecSC &sc) const; /* Counter */ void installCounter( From 0c2e766a9feced39e07c3cdde4c3ab6585cc7834 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Mon, 7 Sep 2020 22:51:34 +0800 Subject: [PATCH 05/31] Refactor context fetch Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 1365 ++++++++++++++++++++++---------------- orchagent/macsecorch.h | 85 ++- 2 files changed, 829 insertions(+), 621 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 8a84e9a7cc..2c74ef9c91 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -11,14 +11,15 @@ #include #include #include +#include /* Only for Debug */ -#define MockSAIFunc(FUNC_NAME) \ -sai_status_t FUNC_NAME(...) \ -{ \ - return SAI_STATUS_SUCCESS; \ -} +#define MockSAIFunc(FUNC_NAME) \ + sai_status_t FUNC_NAME(...) \ + { \ + return SAI_STATUS_SUCCESS; \ + } struct MockSAIAPI { @@ -76,10 +77,10 @@ struct MockSAIAPI static MockSAIAPI mock_api; -static MockSAIAPI * sai_macsec_api = &mock_api; -static MockSAIAPI * sai_acl_api = &mock_api; -static MockSAIAPI * sai_port_api = &mock_api; -static MockSAIAPI * sai_switch_api = &mock_api; +static MockSAIAPI *sai_macsec_api = &mock_api; +static MockSAIAPI *sai_acl_api = &mock_api; +static MockSAIAPI *sai_port_api = &mock_api; +static MockSAIAPI *sai_switch_api = &mock_api; #define MOCK_RETURN_BOOL return true; @@ -245,8 +246,8 @@ static bool hex_to_binary( struct MACsecSAK { - sai_macsec_sak_t m_sak; - bool m_sak_256_enable; + sai_macsec_sak_t m_sak; + bool m_sak_256_enable; }; static std::istringstream &operator>>( @@ -304,23 +305,23 @@ struct MACsecAuthKey sai_macsec_auth_key_t m_auth_key; }; -// static std::istringstream &operator>>( -// std::istringstream &istream, -// MACsecAuthKey &auth_key) -// { -// SWSS_LOG_ENTER(); -// const std::string &buffer = istream.str(); - -// if ( -// (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!hex_to_binary( -// buffer, -// auth_key.m_auth_key, -// sizeof(auth_key.m_auth_key)))) -// { -// throw std::invalid_argument("Invalid Auth Key : " + buffer); -// } -// return istream; -// } +static std::istringstream &operator>>( + std::istringstream &istream, + MACsecAuthKey &auth_key) +{ + SWSS_LOG_ENTER(); + const std::string &buffer = istream.str(); + // TODO : Implement auth_key + // if ( + // (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!hex_to_binary( + // buffer, + // auth_key.m_auth_key, + // sizeof(auth_key.m_auth_key)))) + // { + // throw std::invalid_argument("Invalid Auth Key : " + buffer); + // } + return istream; +} /* Recover from a fail action by a serial of pre-defined recover actions */ class RecoverStack @@ -354,6 +355,233 @@ class RecoverStack std::stack> m_recover_actions; }; +/* Get MACsecOrch Context from port_name, sci or an */ + +class MACsecOrchContext +{ +public: + MACsecOrchContext( + MACsecOrch *orch, + const std::string &port_name) : MACsecOrchContext(orch) + { + m_port_name.reset(new std::string(port_name)); + } + MACsecOrchContext( + MACsecOrch *orch, + const std::string &port_name, + sai_macsec_direction_t direction, + sai_uint64_t sci) : MACsecOrchContext(orch, port_name) + { + m_direction = direction; + m_sci.reset(new sai_uint64_t(sci)); + } + MACsecOrchContext( + MACsecOrch *orch, + const std::string &port_name, + sai_macsec_direction_t direction, + sai_uint64_t sci, + macsec_an_t an) : MACsecOrchContext(orch, port_name, direction, sci) + { + m_an.reset(new macsec_an_t(an)); + } + + Port *get_port() + { + if (m_port == nullptr) + { + if (m_orch == nullptr) + { + SWSS_LOG_ERROR("MACsec orch wasn't provided"); + return nullptr; + } + if (m_port_name == nullptr || m_port_name->empty()) + { + SWSS_LOG_ERROR("Port name wasn't provided."); + return nullptr; + } + auto port = std::make_unique(); + if (!m_orch->m_port_orch->getPort(*m_port_name, *port)) + { + SWSS_LOG_INFO("Cannot find the port %s.", m_port_name->c_str()); + return nullptr; + } + m_port = std::move(port); + } + return m_port.get(); + } + + sai_object_id_t *get_switch_id() + { + if (m_switch_id == nullptr) + { + auto port = get_port(); + if (port == nullptr) + { + return nullptr; + } + auto switch_id = std::make_unique(); + if (!m_orch->getGearboxSwitchId(*port, *switch_id)) + { + SWSS_LOG_INFO("Cannot find MACsec switch at the port %s.", m_port_name->c_str()); + return nullptr; + } + m_switch_id = std::move(switch_id); + } + return m_switch_id.get(); + } + + MACsecOrch::MACsecObject *get_macsec_obj() + { + if (m_macsec_obj == nullptr) + { + auto switch_id = get_switch_id(); + if (switch_id == nullptr) + { + return nullptr; + } + auto macsec_port = m_orch->m_macsec_objs.find(*switch_id); + if (macsec_port == m_orch->m_macsec_objs.end()) + { + SWSS_LOG_INFO("Cannot find the MACsec Object at the port %s.", m_port_name->c_str()); + return nullptr; + } + m_macsec_obj = &macsec_port->second; + } + return m_macsec_obj; + } + + MACsecOrch::MACsecPort *get_macsec_port() + { + if (m_macsec_port == nullptr) + { + if (m_orch == nullptr) + { + SWSS_LOG_ERROR("MACsec orch wasn't provided"); + return nullptr; + } + if (m_port_name == nullptr || m_port_name->empty()) + { + SWSS_LOG_ERROR("Port name wasn't provided."); + return nullptr; + } + auto macsec_port = m_orch->m_macsec_ports.find(*m_port_name); + if (macsec_port == m_orch->m_macsec_ports.end()) + { + SWSS_LOG_INFO("Cannot find the MACsec Object at the port %s.", m_port_name->c_str()); + return nullptr; + } + m_macsec_port = macsec_port->second.get(); + } + return m_macsec_port; + } + + MACsecOrch::ACLTable *get_acl_table() + { + if (m_acl_table == nullptr) + { + auto port = get_macsec_port(); + if (port == nullptr) + { + return nullptr; + } + m_acl_table = + (m_direction == SAI_MACSEC_DIRECTION_EGRESS) + ? &port->m_egress_acl_table + : &port->m_ingress_acl_table; + } + return m_acl_table; + } + + MACsecOrch::MACsecSC *get_macsec_sc() + { + if (m_macsec_sc == nullptr) + { + if (m_sci == nullptr) + { + SWSS_LOG_ERROR("SCI wasn't provided"); + return nullptr; + } + auto port = get_macsec_port(); + if (port == nullptr) + { + return nullptr; + } + auto &scs = + (m_direction == SAI_MACSEC_DIRECTION_EGRESS) + ? port->m_egress_scs + : port->m_ingress_scs; + auto sc = scs.find(*m_sci); + if (sc == scs.end()) + { + SWSS_LOG_INFO("Cannot find the MACsec SC %lu at the port %s.", *m_sci, m_port_name->c_str()); + return nullptr; + } + m_macsec_sc = &sc->second; + } + return m_macsec_sc; + } + + sai_object_id_t *get_macsec_sa() + { + if (m_macsec_sa == nullptr) + { + if (m_an == nullptr) + { + SWSS_LOG_ERROR("AN wasn't provided"); + return nullptr; + } + auto sc = get_macsec_sc(); + if (sc == nullptr) + { + return nullptr; + } + auto an = sc->m_sa_ids.find(*m_an); + if (an == sc->m_sa_ids.end()) + { + SWSS_LOG_INFO( + "Cannot find the MACsec SA %u of SC %lu at the port %s.", + *m_an, + *m_sci, + m_port_name->c_str()); + return nullptr; + } + m_macsec_sa = &an->second; + } + return m_macsec_sa; + } + +private: + MACsecOrchContext(MACsecOrch *orch) : m_orch(orch), + m_port_name(nullptr), + m_direction(SAI_MACSEC_DIRECTION_EGRESS), + m_sci(nullptr), + m_an(nullptr), + m_port(nullptr), + m_macsec_obj(nullptr), + m_switch_id(nullptr), + m_macsec_port(nullptr), + m_acl_table(nullptr), + m_macsec_sc(nullptr), + m_macsec_sa(nullptr) + { + } + MACsecOrch *m_orch; + std::shared_ptr m_port_name; + sai_macsec_direction_t m_direction; + std::unique_ptr m_sci; + std::unique_ptr m_an; + + std::unique_ptr m_port; + MACsecOrch::MACsecObject *m_macsec_obj; + std::unique_ptr m_switch_id; + + MACsecOrch::MACsecPort *m_macsec_port; + MACsecOrch::ACLTable *m_acl_table; + + MACsecOrch::MACsecSC *m_macsec_sc; + sai_object_id_t *m_macsec_sa; +}; + /* MACsec Orchagent */ MACsecOrch::MACsecOrch( @@ -487,140 +715,53 @@ task_process_status MACsecOrch::updateMACsecPort( { SWSS_LOG_ENTER(); + MACsecOrchContext ctx(this, port_name); RecoverStack recover; - Port port; - if (!m_port_orch->getPort(port_name, port)) + if (ctx.get_port() == nullptr || ctx.get_switch_id() == nullptr) { - SWSS_LOG_WARN("Port %s cannot be found.", port_name.c_str()); return task_need_retry; } - sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; - if (!getGearboxSwitchId(port, switch_id)) - { - SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); - return task_failed; - } - - auto macsec_obj = initMACsecObject(switch_id); - if (macsec_obj == m_macsec_objs.end()) + if (ctx.get_macsec_obj() == nullptr) { - SWSS_LOG_WARN("Cannot init MACsec at the port %s.", port_name.c_str()); - return task_failed; - } - recover.add_action([&]() { - if (macsec_obj->second.m_ports.empty()) + if (!initMACsecObject(*ctx.get_switch_id())) { - deinitMACsecObject(macsec_obj); - } - }); - - std::shared_ptr macsec_port; - auto macsec_port_itr = m_macsec_ports.find(port_name); - if (macsec_port_itr == m_macsec_ports.end()) - { - macsec_port = createMACsecPort( - port_name, - port.m_line_port_id, - switch_id); - if (macsec_port == nullptr) - { - SWSS_LOG_WARN("Cannot init MACsec port at the port %s.", port_name.c_str()); + SWSS_LOG_WARN("Cannot init MACsec Object at the port %s.", port_name.c_str()); return task_failed; } - recover.add_action([&]() { deleteMACsecPort(port_name); }); - macsec_obj->second.m_ports[port_name] = macsec_port; - recover.add_action([&]() { macsec_obj->second.m_ports.erase(port_name); }); - } - else - { - macsec_port = macsec_port_itr->second; - } - - get_value(port_attr, "enable_encrypt", macsec_port->m_enable_encrypt); - get_value(port_attr, "send_sci", macsec_port->m_sci_in_sectag); - if (get_value(port_attr, "enable", macsec_port->m_enable)) - { - std::vector scs; - for (auto &sc : macsec_port->m_egress_scs) - { - scs.push_back(&(sc.second)); - } - for (auto &sc : macsec_port->m_ingress_scs) - { - scs.push_back(&(sc.second)); - } - for (auto &sc : scs) - { - // Change the ACL entry action from packet action to MACsec flow - if (macsec_port->m_enable) - { - if (!setACLEntryMACsecFlow(sc->m_entry_id, sc->m_flow_id)) - { - SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); - return task_failed; - } - recover.add_action([&]() { setACLEntryPacketAction(sc->m_encoding_an, sc->m_flow_id); }); - } - else - { - setACLEntryPacketAction(sc->m_encoding_an, sc->m_flow_id); - } - } + auto switch_id = *ctx.get_switch_id(); + recover.add_action([this, switch_id]() { this->deinitMACsecObject(switch_id); }); } - - // If hardware matches SCI in ACL, the macsec_flow maps to an IEEE 802.1ae SecY object. - // Multiple SCs can be associated with such a macsec_flow. - // Then a specific value of SCI from the SecTAG in the packet is used to identify a specific SC - // for that macsec_flow. - // False means one flow can be associated with multiple ACL entries and multiple SC - if (!macsec_obj->second.m_sci_in_ingress_macsec_acl) + if (ctx.get_macsec_port() == nullptr) { - if (!createMACsecFlow(macsec_port->m_egress_flow_id, switch_id, SAI_MACSEC_DIRECTION_EGRESS)) - { - SWSS_LOG_WARN("Cannot create MACsec egress flow at the port %s.", port_name.c_str()); - return task_failed; - } - recover.add_action([&]() { deleteMACsecFlow(macsec_port->m_egress_flow_id); }); + auto macsec_port_itr = m_macsec_ports.emplace(port_name, std::make_shared()).first; + recover.add_action([this, macsec_port_itr]() { this->m_macsec_ports.erase(macsec_port_itr); }); - if (!createMACsecFlow(macsec_port->m_ingress_flow_id, switch_id, SAI_MACSEC_DIRECTION_EGRESS)) + if (!createMACsecPort( + *macsec_port_itr->second, + port_name, + port_attr, + *ctx.get_macsec_obj(), + ctx.get_port()->m_line_port_id, + *ctx.get_switch_id())) { - SWSS_LOG_WARN("Cannot create MACsec ingress flow at the port %s.", port_name.c_str()); return task_failed; } - recover.add_action([&]() { deleteMACsecFlow(macsec_port->m_ingress_flow_id); }); + ctx.get_macsec_obj()->m_macsec_ports[port_name] = macsec_port_itr->second; + recover.add_action([this, &port_name, &ctx, macsec_port_itr]() { + this->deleteMACsecPort( + *macsec_port_itr->second, + port_name, + *ctx.get_macsec_obj(), + ctx.get_port()->m_line_port_id); + }); } - - if (!initACLTable( - macsec_port->m_egress_acl_table, - port.m_line_port_id, - switch_id, - SAI_MACSEC_DIRECTION_EGRESS, - macsec_port->m_sci_in_sectag)) + if (!updateMACsecPort(*ctx.get_macsec_port(), port_attr)) { - SWSS_LOG_WARN("Cannot init the ACL Table at the port %s.", port_name.c_str()); return task_failed; } - recover.add_action([&]() { deinitACLTable(macsec_port->m_egress_acl_table, port.m_line_port_id); }); - - if (!initACLTable( - macsec_port->m_ingress_acl_table, - port.m_line_port_id, - switch_id, - SAI_MACSEC_DIRECTION_INGRESS, - macsec_port->m_sci_in_sectag)) - { - SWSS_LOG_WARN("Cannot init the ACL Table at the port %s.", port_name.c_str()); - return task_failed; - } - recover.add_action([&]() { deinitACLTable(macsec_port->m_ingress_acl_table, port.m_line_port_id); }); - - std::vector fvVector; - fvVector.emplace_back("state", "ok"); - m_state_macsec_port.set(port_name, fvVector); recover.clear(); - return task_success; } @@ -630,84 +771,46 @@ task_process_status MACsecOrch::disableMACsecPort( { SWSS_LOG_ENTER(); - sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; - if (!getGearboxSwitchId(port_name, switch_id)) - { - SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); - return task_failed; - } - - auto macsec_port = m_macsec_ports.find(port_name); - if (macsec_port == m_macsec_ports.end()) - { - SWSS_LOG_INFO("The MACsec wasn't enabled at the port %s", port_name.c_str()); - return task_success; - } - - task_process_status result = task_success; + MACsecOrchContext ctx(this, port_name); - Port port; - if (!m_port_orch->getPort(port_name, port)) + if (ctx.get_switch_id() == nullptr || ctx.get_macsec_port() == nullptr) { - SWSS_LOG_ERROR("Port %s cannot be found.", port_name.c_str()); + SWSS_LOG_WARN("Cannot find MACsec switch at the port %s.", port_name.c_str()); return task_failed; } - - auto macsec_obj = m_macsec_objs.find(switch_id); - if (macsec_obj == m_macsec_objs.end()) + if (ctx.get_port() == nullptr) { - SWSS_LOG_ERROR("The MACsec wasn't initialized at the switch %lu", switch_id); - result = task_failed; + SWSS_LOG_WARN("Cannot find the port %s.", port_name.c_str()); + return task_failed; } - if (!deinitACLTable(macsec_port->second->m_ingress_acl_table, port.m_line_port_id)) + if (ctx.get_macsec_port() == nullptr) { - SWSS_LOG_WARN("Cannot deinit ingress ACL table at the port %s.", port_name.c_str()); - result = task_failed; + SWSS_LOG_INFO("The MACsec wasn't enabled at the port %s", port_name.c_str()); + return task_success; } - if (!deinitACLTable(macsec_port->second->m_egress_acl_table, port.m_line_port_id)) + auto result = task_success; + if (!deleteMACsecPort( + *ctx.get_macsec_port(), + port_name, + *ctx.get_macsec_obj(), + ctx.get_port()->m_line_port_id)) { - SWSS_LOG_WARN("Cannot deinit egress ACL table at the port %s.", port_name.c_str()); result = task_failed; } - - if (!macsec_obj->second.m_sci_in_ingress_macsec_acl) + m_macsec_ports.erase(port_name); + ctx.get_macsec_obj()->m_macsec_ports.erase(port_name); + // All ports on this macsec object have been deleted. + if (ctx.get_macsec_obj()->m_macsec_ports.empty()) { - if (!deleteMACsecFlow(macsec_port->second->m_egress_flow_id)) - { - SWSS_LOG_WARN("Cannot delete the MACsec egress flow at the port %s.", port_name.c_str()); - result = task_failed; - } - if (!deleteMACsecFlow(macsec_port->second->m_ingress_flow_id)) + if (!deinitMACsecObject(*ctx.get_switch_id())) { - SWSS_LOG_WARN("Cannot delete the MACsec ingress flow at the port %s.", port_name.c_str()); + SWSS_LOG_WARN("Cannot deinit macsec at the port %s.", port_name.c_str()); result = task_failed; } } - if (!deleteMACsecPort(port_name)) - { - SWSS_LOG_WARN("Cannot delete macsec port at the port %s.", port_name.c_str()); - result = task_failed; - } - - if (macsec_obj != m_macsec_objs.end()) - { - macsec_obj->second.m_ports.erase(port_name); - // All ports on this macsec object have been deleted. - if (macsec_obj->second.m_ports.empty()) - { - if (!deinitMACsecObject(macsec_obj)) - { - SWSS_LOG_WARN("Cannot deinit macsec at the port %s.", port_name.c_str()); - result = task_failed; - } - } - } - - m_state_macsec_port.del(port_name); - return result; } @@ -756,19 +859,14 @@ task_process_status MACsecOrch::updateEgressSA( SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); return task_failed; } - auto port = m_macsec_ports.find(port_name); - if (port == m_macsec_ports.end()) - { - SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); - return task_need_retry; - } - auto sc = port->second->m_egress_scs.find(sci); - if (sc == port->second->m_egress_scs.end()) + + MACsecOrchContext ctx(this, port_name, SAI_MACSEC_DIRECTION_EGRESS, sci, an); + if (ctx.get_macsec_sc() == nullptr) { SWSS_LOG_INFO("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); return task_need_retry; } - if (sc->second.m_encoding_an == an) + if (ctx.get_macsec_sc()->m_encoding_an == an) { return createMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_EGRESS); } @@ -780,15 +878,7 @@ task_process_status MACsecOrch::deleteEgressSA( const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); - auto result = deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_EGRESS); - if (result == task_success) - { - return task_success; - } - else - { - return task_failed; - } + return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_EGRESS); } task_process_status MACsecOrch::updateIngressSA( @@ -796,19 +886,39 @@ task_process_status MACsecOrch::updateIngressSA( const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); + bool active = false; - if (!get_value(sa_attr, "active", active)) - { - SWSS_LOG_WARN("Active filed isn't existed at the SA %s.", port_sci_an.c_str()); - return task_failed; - } + get_value(sa_attr, "active", active); if (active) { return createMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_INGRESS); } else { - return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); + + std::string port_name; + sai_uint64_t sci = 0; + macsec_an_t an = 0; + if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) + { + SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); + return task_failed; + } + + MACsecOrchContext ctx(this, port_name, SAI_MACSEC_DIRECTION_INGRESS, sci, an); + + if (ctx.get_macsec_sa() != nullptr) + { + return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); + } + else + { + // The MACsec SA hasn't been created. + // Don't need do anything until the active field to be enabled. + // To use "retry" because this message maybe include other initialized fields + // To use other return values will make us lose these initialized fields. + return task_need_retry; + } } } @@ -817,15 +927,7 @@ task_process_status MACsecOrch::deleteIngressSA( const TaskArgs &sa_attr) { SWSS_LOG_ENTER(); - auto result = deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); - if (result == task_success) - { - return task_success; - } - else - { - return task_failed; - } + return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); } bool MACsecOrch::initGearbox() @@ -884,7 +986,7 @@ bool MACsecOrch::getGearboxSwitchId(const Port &port, sai_object_id_t &switch_id return true; } -map::iterator MACsecOrch::initMACsecObject(sai_object_id_t switch_id) +bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id) { SWSS_LOG_ENTER(); @@ -894,7 +996,7 @@ map::iterator MACsecOrch::initMACsecO if (!macsec_obj.second) { SWSS_LOG_INFO("The MACsec has been initialized at the switch %lu", switch_id); - return macsec_obj.first; + return true; } recover.add_action([&]() { m_macsec_objs.erase(macsec_obj.first); }); @@ -911,7 +1013,7 @@ map::iterator MACsecOrch::initMACsecO attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot initialize MACsec egress object at the switch %lu", switch_id); - return m_macsec_objs.end(); + return false; } recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_egress_id); }); @@ -926,7 +1028,7 @@ map::iterator MACsecOrch::initMACsecO attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("Cannot initialize MACsec ingress object at the switch %lu", switch_id); - return m_macsec_objs.end(); + return false; } recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_ingress_id); }); @@ -941,12 +1043,12 @@ map::iterator MACsecOrch::initMACsecO SWSS_LOG_WARN( "Cannot get MACsec attribution SAI_MACSEC_ATTR_SCI_IN_INGRESS_MACSEC_ACL at the switch %lu", switch_id); - return m_macsec_objs.end(); + return false; } macsec_obj.first->second.m_sci_in_ingress_macsec_acl = attrs.front().value.booldata; recover.clear(); - return macsec_obj.first; + return true; } bool MACsecOrch::deinitMACsecObject(sai_object_id_t switch_id) @@ -960,13 +1062,6 @@ bool MACsecOrch::deinitMACsecObject(sai_object_id_t switch_id) return true; } - return deinitMACsecObject(macsec_obj); -} - -bool MACsecOrch::deinitMACsecObject(map::iterator macsec_obj) -{ - SWSS_LOG_ENTER(); - bool result = true; if (sai_macsec_api->remove_macsec( @@ -987,132 +1082,284 @@ bool MACsecOrch::deinitMACsecObject(map::iterator return result; } -std::shared_ptr MACsecOrch::createMACsecPort( +bool MACsecOrch::createMACsecPort( + MACsecPort &macsec_port, const std::string &port_name, - sai_object_id_t port_id, + const TaskArgs &port_attr, + const MACsecObject &macsec_obj, + sai_object_id_t line_port_id, sai_object_id_t switch_id) { SWSS_LOG_ENTER(); RecoverStack recover; - auto macsec_port = m_macsec_ports.emplace(port_name, std::make_shared()); - if (!macsec_port.second) + if (!createMACsecPort( + macsec_port.m_egress_port_id, + line_port_id, + switch_id, + SAI_MACSEC_DIRECTION_EGRESS)) { - SWSS_LOG_INFO("The MACsec port has been initialized at the port %s.", port_name.c_str()); - return macsec_port.first->second; + SWSS_LOG_WARN("Cannot create MACsec egress port at the port %s", port_name.c_str()); + return false; } - recover.add_action([&]() { m_macsec_ports.erase(macsec_port.first); }); + recover.add_action([this, &macsec_port]() { + this->deleteMACsecPort(macsec_port.m_egress_port_id); + macsec_port.m_egress_port_id = SAI_NULL_OBJECT_ID; + }); + + if (!createMACsecPort( + macsec_port.m_ingress_port_id, + line_port_id, + switch_id, + SAI_MACSEC_DIRECTION_INGRESS)) + { + SWSS_LOG_WARN("Cannot create MACsec ingress port at the port %s", port_name.c_str()); + return false; + } + recover.add_action([this, &macsec_port]() { + this->deleteMACsecPort(macsec_port.m_ingress_port_id); + macsec_port.m_ingress_port_id = SAI_NULL_OBJECT_ID; + }); + + macsec_port.m_enable_encrypt = true; + macsec_port.m_sci_in_sectag = true; + macsec_port.m_enable = false; + + // If hardware matches SCI in ACL, the macsec_flow maps to an IEEE 802.1ae SecY object. + // Multiple SCs can be associated with such a macsec_flow. + // Then a specific value of SCI from the SecTAG in the packet is used to identify a specific SC + // for that macsec_flow. + // False means one flow can be associated with multiple ACL entries and multiple SC + if (!macsec_obj.m_sci_in_ingress_macsec_acl) + { + if (!createMACsecFlow( + macsec_port.m_egress_flow_id, + switch_id, + SAI_MACSEC_DIRECTION_EGRESS)) + { + SWSS_LOG_WARN("Cannot create MACsec egress flow at the port %s.", port_name.c_str()); + return false; + } + recover.add_action([this, &macsec_port]() { + this->deleteMACsecFlow(macsec_port.m_egress_flow_id); + macsec_port.m_egress_flow_id = SAI_NULL_OBJECT_ID; + }); + + if (!createMACsecFlow( + macsec_port.m_ingress_flow_id, + switch_id, + SAI_MACSEC_DIRECTION_INGRESS)) + { + SWSS_LOG_WARN("Cannot create MACsec ingress flow at the port %s.", port_name.c_str()); + return false; + } + recover.add_action([this, &macsec_port]() { + this->deleteMACsecFlow(macsec_port.m_ingress_flow_id); + macsec_port.m_ingress_flow_id = SAI_NULL_OBJECT_ID; + }); + } + + if (!initACLTable( + macsec_port.m_egress_acl_table, + line_port_id, + switch_id, + SAI_MACSEC_DIRECTION_EGRESS, + macsec_port.m_sci_in_sectag)) + { + SWSS_LOG_WARN("Cannot init the ACL Table at the port %s.", port_name.c_str()); + return false; + } + recover.add_action([this, &macsec_port, line_port_id]() { + this->deinitACLTable( + macsec_port.m_egress_acl_table, + line_port_id, + SAI_MACSEC_DIRECTION_EGRESS); + }); + + if (!initACLTable( + macsec_port.m_ingress_acl_table, + line_port_id, + switch_id, + SAI_MACSEC_DIRECTION_INGRESS, + macsec_port.m_sci_in_sectag)) + { + SWSS_LOG_WARN("Cannot init the ACL Table at the port %s.", port_name.c_str()); + return false; + } + recover.add_action([this, &macsec_port, line_port_id]() { + this->deinitACLTable( + macsec_port.m_ingress_acl_table, + line_port_id, + SAI_MACSEC_DIRECTION_INGRESS); + }); + + std::vector fvVector; + fvVector.emplace_back("state", "ok"); + m_state_macsec_port.set(port_name, fvVector); + + recover.clear(); + return true; +} + +bool MACsecOrch::createMACsecPort( + sai_object_id_t &macsec_port_id, + sai_object_id_t line_port_id, + sai_object_id_t switch_id, + sai_macsec_direction_t direction) +{ + SWSS_LOG_ENTER(); sai_attribute_t attr; std::vector attrs; attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; - attr.value.s32 = SAI_MACSEC_DIRECTION_EGRESS; + attr.value.s32 = direction; attrs.push_back(attr); attr.id = SAI_MACSEC_PORT_ATTR_PORT_ID; - attr.value.oid = port_id; + attr.value.oid = line_port_id; attrs.push_back(attr); if (sai_macsec_api->create_macsec_port( - &macsec_port.first->second->m_egress_port_id, + &macsec_port_id, switch_id, static_cast(attrs.size()), attrs.data()) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot create MACsec egress port at the port %s", port_name.c_str()); - return nullptr; + return false; } - recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_egress_port_id); }); - attrs.clear(); - attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; - attr.value.s32 = SAI_MACSEC_DIRECTION_INGRESS; - attrs.push_back(attr); - attr.id = SAI_MACSEC_PORT_ATTR_PORT_ID; - attr.value.oid = port_id; - attrs.push_back(attr); - if (sai_macsec_api->create_macsec_port( - &macsec_port.first->second->m_ingress_port_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) + return true; +} + +bool MACsecOrch::updateMACsecPort(MACsecPort &macsec_port, const TaskArgs &port_attr) +{ + SWSS_LOG_ENTER(); + + RecoverStack recover; + + get_value(port_attr, "enable_encrypt", macsec_port.m_enable_encrypt); + get_value(port_attr, "send_sci", macsec_port.m_sci_in_sectag); + if (get_value(port_attr, "enable", macsec_port.m_enable)) { - SWSS_LOG_WARN("Cannot create MACsec ingress port at the port %s", port_name.c_str()); - return nullptr; + std::vector macsec_scs; + for (auto sc : macsec_port.m_egress_scs) + { + macsec_scs.push_back(&sc.second); + } + for (auto sc : macsec_port.m_ingress_scs) + { + macsec_scs.push_back(&sc.second); + } + for (auto &macsec_sc : macsec_scs) + { + // Change the ACL entry action from packet action to MACsec flow + if (macsec_port.m_enable) + { + if (!setACLEntryMACsecFlow(macsec_sc->m_entry_id, macsec_sc->m_flow_id)) + { + SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); + return false; + } + auto an = macsec_sc->m_encoding_an; + auto flow_id = macsec_sc->m_flow_id; + recover.add_action([this, an, flow_id]() { this->setACLEntryPacketAction(an, flow_id); }); + } + else + { + setACLEntryPacketAction(macsec_sc->m_encoding_an, macsec_sc->m_flow_id); + } + } } - recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_port.first->second->m_ingress_port_id); }); - - macsec_port.first->second->m_enable_encrypt = true; - macsec_port.first->second->m_sci_in_sectag = true; - macsec_port.first->second->m_enable = false; recover.clear(); - return macsec_port.first->second; + return true; } -bool MACsecOrch::deleteMACsecPort(const std::string &port_name) +bool MACsecOrch::deleteMACsecPort( + const MACsecPort &macsec_port, + const std::string &port_name, + const MACsecObject &macsec_obj, + sai_object_id_t line_port_id) { SWSS_LOG_ENTER(); - auto macsec_port = m_macsec_ports.find(port_name); - if (macsec_port == m_macsec_ports.end()) - { - SWSS_LOG_WARN("The MACsec port wasn't initialized at the port %s", port_name.c_str()); - return true; - } + bool result = true; - for (auto &sc : macsec_port->second->m_egress_scs) + for (auto sc : macsec_port.m_egress_scs) { const std::string port_sci = join(':', port_name, sc.first); - deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS); + if (deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS) != task_success) + { + result &= false; + } } - for (auto &sc : macsec_port->second->m_ingress_scs) + for (auto sc : macsec_port.m_ingress_scs) { const std::string port_sci = join(':', port_name, sc.first); - deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS); + if (deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS) != task_success) + { + result &= false; + } } - bool result = true; + if (!macsec_obj.m_sci_in_ingress_macsec_acl) + { + if (!this->deleteMACsecFlow(macsec_port.m_egress_flow_id)) + { + SWSS_LOG_WARN("Cannot delete MACsec egress flow at the port %s", port_name.c_str()); + result &= false; + } - if (sai_macsec_api->remove_macsec_port( - macsec_port->second->m_egress_port_id) != SAI_STATUS_SUCCESS) + if (!this->deleteMACsecFlow(macsec_port.m_ingress_flow_id)) + { + SWSS_LOG_WARN("Cannot delete MACsec ingress flow at the port %s", port_name.c_str()); + result &= false; + } + } + + if (!deinitACLTable(macsec_port.m_ingress_acl_table, line_port_id, SAI_MACSEC_DIRECTION_INGRESS)) { - SWSS_LOG_WARN("Cannot delete MACsec egress port at the port %s", port_name.c_str()); + SWSS_LOG_WARN("Cannot deinit ingress ACL table at the port %s.", port_name.c_str()); result &= false; } - if (sai_macsec_api->remove_macsec_port( - macsec_port->second->m_ingress_port_id) != SAI_STATUS_SUCCESS) + if (!deinitACLTable(macsec_port.m_egress_acl_table, line_port_id, SAI_MACSEC_DIRECTION_EGRESS)) { - SWSS_LOG_WARN("Cannot delete MACsec ingress port at the port %s", port_name.c_str()); + SWSS_LOG_WARN("Cannot deinit egress ACL table at the port %s.", port_name.c_str()); result &= false; } - // TODO - // If m_sci_in_ingress_macsec_acl - // { - if (sai_macsec_api->remove_macsec_flow( - macsec_port->second->m_egress_flow_id) != SAI_STATUS_SUCCESS) + + if (!deleteMACsecPort(macsec_port.m_egress_port_id)) { - SWSS_LOG_WARN("Cannot delete MACsec egress flow at the port %s", port_name.c_str()); + SWSS_LOG_WARN("Cannot delete MACsec egress port at the port %s", port_name.c_str()); result &= false; } - if (sai_macsec_api->remove_macsec_flow( - macsec_port->second->m_ingress_flow_id) != SAI_STATUS_SUCCESS) + if (!deleteMACsecPort(macsec_port.m_ingress_port_id)) { - SWSS_LOG_WARN("Cannot delete MACsec ingress flow at the port %s", port_name.c_str()); + SWSS_LOG_WARN("Cannot delete MACsec ingress port at the port %s", port_name.c_str()); result &= false; } - // } - m_macsec_ports.erase(macsec_port); + m_state_macsec_port.del(port_name); + + return true; +} + +bool MACsecOrch::deleteMACsecPort(sai_object_id_t macsec_port_id) +{ + if (sai_macsec_api->remove_macsec_port( + macsec_port_id) != SAI_STATUS_SUCCESS) + { + return false; + } return true; } bool MACsecOrch::createMACsecFlow( sai_object_id_t &flow_id, sai_object_id_t switch_id, - sai_int32_t direction) + sai_macsec_direction_t direction) { SWSS_LOG_ENTER(); @@ -1151,7 +1398,7 @@ bool MACsecOrch::deleteMACsecFlow(sai_object_id_t flow_id) task_process_status MACsecOrch::updateMACsecSC( const std::string &port_sci, const TaskArgs &sc_attr, - sai_int32_t direction) + sai_macsec_direction_t direction) { SWSS_LOG_ENTER(); @@ -1163,76 +1410,73 @@ task_process_status MACsecOrch::updateMACsecSC( return task_failed; } - auto macsec_port = m_macsec_ports.find(port_name); - if (macsec_port == m_macsec_ports.end()) + MACsecOrchContext ctx(this, port_name, direction, sci); + + if (ctx.get_macsec_port() == nullptr) { - SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); return task_need_retry; } - sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; - if (!getGearboxSwitchId(port_name, switch_id)) + + if (ctx.get_switch_id() == nullptr || ctx.get_macsec_obj() == nullptr) { SWSS_LOG_ERROR("Cannot find gearbox at the port %s.", port_name.c_str()); return task_failed; } - auto macsec_obj = m_macsec_objs.find(switch_id); - if (macsec_obj == m_macsec_objs.end()) + if (ctx.get_macsec_sc() == nullptr) { - SWSS_LOG_ERROR("The MACsec wasn't initialized at the switch %lu", switch_id); - return task_failed; + if (!createMACsecSC( + *ctx.get_macsec_port(), + port_name, + sc_attr, + *ctx.get_macsec_obj(), + sci, + *ctx.get_switch_id(), + direction)) + { + return task_failed; + } + } + else + { + if (!setEncodingAN(*ctx.get_macsec_sc(), sc_attr, direction)) + { + return task_failed; + } } - auto &scs = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? macsec_port->second->m_egress_scs - : macsec_port->second->m_ingress_scs; - auto sc = scs.find(sci); - // If SC has been created - if (sc != scs.end()) - { - return setEncodingAN(sc->second, sc_attr, direction); - } - - return createMACsecSC( - *(macsec_port->second), - port_name, - sc_attr, - macsec_obj->second, - sci, - switch_id, - direction); + return task_success; } -task_process_status MACsecOrch::setEncodingAN( +bool MACsecOrch::setEncodingAN( MACsecSC &sc, const TaskArgs &sc_attr, - sai_int32_t direction) + sai_macsec_direction_t direction) { if (direction == SAI_MACSEC_DIRECTION_EGRESS) { if (!get_value(sc_attr, "encoding_an", sc.m_encoding_an)) { SWSS_LOG_WARN("Wrong parameter, the encoding AN cannot be found"); - return task_failed; + return false; } - return task_success; } else { SWSS_LOG_WARN("Cannot set encoding AN for the ingress SC"); - return task_failed; + return false; } + return true; } -task_process_status MACsecOrch::createMACsecSC( +bool MACsecOrch::createMACsecSC( MACsecPort &macsec_port, const std::string &port_name, const TaskArgs &sc_attr, const MACsecObject &macsec_obj, sai_uint64_t sci, sai_object_id_t switch_id, - sai_int32_t direction) + sai_macsec_direction_t direction) { SWSS_LOG_ENTER(); @@ -1240,91 +1484,94 @@ task_process_status MACsecOrch::createMACsecSC( const std::string port_sci = join(':', port_name, sci); - auto &scs = + auto scs = (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? macsec_port.m_egress_scs - : macsec_port.m_ingress_scs; - auto sc_itr = scs.emplace(sci, MACsecSC()); + ? &macsec_port.m_egress_scs + : &macsec_port.m_ingress_scs; + auto sc_itr = scs->emplace( + std::piecewise_construct, + std::forward_as_tuple(sci), + std::forward_as_tuple()); if (!sc_itr.second) { SWSS_LOG_ERROR("The SC %s has been created.", port_sci.c_str()); - return task_failed; + return false; } - recover.add_action([&]() { scs.erase(sc_itr.first->first); }); - auto &sc = sc_itr.first->second; + recover.add_action([scs, sc_itr]() { + scs->erase(sc_itr.first->first); + }); + auto sc = &sc_itr.first->second; sai_uint32_t ssci = 0; - sc.m_xpn64_enable = false; + sc->m_xpn64_enable = false; if (get_value(sc_attr, "ssci", ssci) && ssci) { - sc.m_xpn64_enable = true; + sc->m_xpn64_enable = true; } if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - get_value(sc_attr, "encoding_an", sc.m_encoding_an); + get_value(sc_attr, "encoding_an", sc->m_encoding_an); } - sc.m_flow_id = SAI_NULL_OBJECT_ID; - + sc->m_flow_id = SAI_NULL_OBJECT_ID; // If SCI can only be used as ACL field - // Which means one ingress flow can be associated with only one ACL entry and one SC. + // Which means one flow can be associated with only one ACL entry and one SC. if (macsec_obj.m_sci_in_ingress_macsec_acl) { - if (!createMACsecFlow(sc.m_flow_id, switch_id, direction)) + if (!createMACsecFlow(sc->m_flow_id, switch_id, direction)) { SWSS_LOG_WARN("Cannot create MACsec Flow"); - return task_failed; + return false; } - recover.add_action([&]() { deleteMACsecFlow(sc.m_flow_id); }); + recover.add_action([this, sc]() { this->deleteMACsecFlow(sc->m_flow_id); }); } else { - sc.m_flow_id = + sc->m_flow_id = (direction == SAI_MACSEC_DIRECTION_EGRESS) ? macsec_port.m_egress_flow_id : macsec_port.m_ingress_flow_id; } if (!createMACsecSC( - sc.m_sc_id, + sc->m_sc_id, switch_id, direction, - sc.m_flow_id, + sc->m_flow_id, sci, ssci, - sc.m_xpn64_enable)) + sc->m_xpn64_enable)) { SWSS_LOG_WARN("Create MACsec SC %s fail.", port_sci.c_str()); - return task_failed; + return false; } - recover.add_action([&]() { deleteMACsecSC(sc.m_sc_id); }); + recover.add_action([this, sc]() { this->deleteMACsecSC(sc->m_sc_id); }); - auto &table = + auto table = (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? macsec_port.m_egress_acl_table - : macsec_port.m_ingress_acl_table; - if (table.m_available_acl_priorities.empty()) + ? &macsec_port.m_egress_acl_table + : &macsec_port.m_ingress_acl_table; + if (table->m_available_acl_priorities.empty()) { SWSS_LOG_WARN("Available ACL priorities have been exhausted."); - return task_failed; + return false; } - sc.m_acl_priority = *(table.m_available_acl_priorities.begin()); - table.m_available_acl_priorities.erase(table.m_available_acl_priorities.begin()); + sc->m_acl_priority = *(table->m_available_acl_priorities.begin()); + table->m_available_acl_priorities.erase(table->m_available_acl_priorities.begin()); if (!createACLDataEntry( - sc.m_entry_id, - table.m_table_id, - switch_id, - macsec_port.m_sci_in_sectag, - sci, - sc.m_acl_priority)) + sc->m_entry_id, + table->m_table_id, + switch_id, + macsec_port.m_sci_in_sectag, + sci, + sc->m_acl_priority)) { SWSS_LOG_WARN("Cannot create ACL Data entry"); - return task_failed; + return false; } - recover.add_action([&]() - { - deleteACLEntry(sc.m_entry_id); - table.m_available_acl_priorities.insert(sc.m_acl_priority); + recover.add_action([this, sc, table]() { + deleteACLEntry(sc->m_entry_id); + table->m_available_acl_priorities.insert(sc->m_acl_priority); }); SWSS_LOG_NOTICE("MACsec SC %s is created.", port_sci.c_str()); @@ -1341,85 +1588,106 @@ task_process_status MACsecOrch::createMACsecSC( } recover.clear(); - return task_success; + return true; } -task_process_status MACsecOrch::deleteMACsecSC( - const std::string &port_sci, - sai_int32_t direction) +bool MACsecOrch::createMACsecSC( + sai_object_id_t &sc_id, + sai_object_id_t switch_id, + sai_macsec_direction_t direction, + sai_object_id_t flow_id, + sai_uint64_t sci, + sai_uint32_t ssci, + bool xpn64_enable) { SWSS_LOG_ENTER(); - std::string port_name; - sai_uint64_t sci = {0}; - if (!split(port_sci, ':', port_name, sci)) - { - SWSS_LOG_WARN("The key %s isn't correct.", port_sci.c_str()); - return task_failed; - } + sai_attribute_t attr; + std::vector attrs; - auto macsec_port = m_macsec_ports.find(port_name); - if (macsec_port == m_macsec_ports.end()) + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_DIRECTION; + attr.value.s32 = direction; + attrs.push_back(attr); + attr.id = SAI_MACSEC_SC_ATTR_FLOW_ID; + attr.value.oid = flow_id; + attrs.push_back(attr); + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_SCI; + attr.value.u64 = sci; + attrs.push_back(attr); + if (xpn64_enable) { - SWSS_LOG_WARN("The MACsec port hasn't been created at the port %s.", port_name.c_str()); - return task_failed; + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_SSCI; + attr.value.u32 = ssci; + attrs.push_back(attr); } + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_XPN64_ENABLE; + attr.value.booldata = xpn64_enable; + attrs.push_back(attr); - sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; - if (!getGearboxSwitchId(port_name, switch_id)) + if (sai_macsec_api->create_macsec_sc( + &sc_id, + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); - return task_failed; + SWSS_LOG_WARN("Cannot create MACsec egress SC %lu", sci); + return false; } + return true; +} - auto macsec_obj = m_macsec_objs.find(switch_id); - if (macsec_obj == m_macsec_objs.end()) +task_process_status MACsecOrch::deleteMACsecSC( + const std::string &port_sci, + sai_macsec_direction_t direction) +{ + SWSS_LOG_ENTER(); + + std::string port_name; + sai_uint64_t sci = 0; + if (!split(port_sci, ':', port_name, sci)) { - SWSS_LOG_WARN("The MACsec wasn't initialized at the switch %lu", switch_id); + SWSS_LOG_WARN("The key %s isn't correct.", port_sci.c_str()); return task_failed; } - auto &scs = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? macsec_port->second->m_egress_scs - : macsec_port->second->m_ingress_scs; - auto sc = scs.find(sci); - if (sc == scs.end()) + MACsecOrchContext ctx(this, port_name, direction, sci); + + if (ctx.get_macsec_sc() == nullptr) { - SWSS_LOG_WARN("The MACsec SC %s wasn't created", port_sci.c_str()); - return task_failed; + SWSS_LOG_INFO("The MACsec SC %s wasn't created", port_sci.c_str()); + return task_success; } auto result = task_success; - for (auto &sa : sc->second.m_sa_ids) + for (auto sa : ctx.get_macsec_sc()->m_sa_ids) { const std::string port_sci_an = join(':', port_sci, sa.first); deleteMACsecSA(port_sci_an, direction); } - deleteACLEntry(sc->second.m_entry_id); - auto &table = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? macsec_port->second->m_egress_acl_table - : macsec_port->second->m_ingress_acl_table; - table.m_available_acl_priorities.insert(sc->second.m_acl_priority); + deleteACLEntry(ctx.get_macsec_sc()->m_entry_id); + ctx.get_acl_table()->m_available_acl_priorities.insert(ctx.get_macsec_sc()->m_acl_priority); - if (!macsec_obj->second.m_sci_in_ingress_macsec_acl) + if (ctx.get_macsec_obj()->m_sci_in_ingress_macsec_acl) { - if (deleteMACsecFlow(sc->second.m_flow_id)) + if (deleteMACsecFlow(ctx.get_macsec_sc()->m_flow_id)) { SWSS_LOG_WARN("Cannot delete MACsec flow"); result = task_failed; } } - if (!deleteMACsecSC(sc->second.m_sc_id)) + if (!deleteMACsecSC(ctx.get_macsec_sc()->m_sc_id)) { SWSS_LOG_WARN("The MACsec SC %s cannot be deleted", port_sci.c_str()); result = task_failed; } - scs.erase(sc); + auto scs = + (direction == SAI_MACSEC_DIRECTION_EGRESS) + ? &ctx.get_macsec_port()->m_egress_scs + : &ctx.get_macsec_port()->m_ingress_scs; + scs->erase(sci); SWSS_LOG_NOTICE("MACsec SC %s is deleted.", port_sci.c_str()); @@ -1435,51 +1703,6 @@ task_process_status MACsecOrch::deleteMACsecSC( return result; } -bool MACsecOrch::createMACsecSC( - sai_object_id_t &sc_id, - sai_object_id_t switch_id, - sai_int32_t direction, - sai_object_id_t flow_id, - sai_uint64_t sci, - sai_uint32_t ssci, - bool xpn64_enable) -{ - SWSS_LOG_ENTER(); - - sai_attribute_t attr; - std::vector attrs; - - attr.id = SAI_MACSEC_SC_ATTR_MACSEC_DIRECTION; - attr.value.s32 = direction; - attrs.push_back(attr); - attr.id = SAI_MACSEC_SC_ATTR_FLOW_ID; - attr.value.oid = flow_id; - attrs.push_back(attr); - attr.id = SAI_MACSEC_SC_ATTR_MACSEC_SCI; - attr.value.u64 = sci; - attrs.push_back(attr); - if (xpn64_enable) - { - attr.id = SAI_MACSEC_SC_ATTR_MACSEC_SSCI; - attr.value.u32 = ssci; - attrs.push_back(attr); - } - attr.id = SAI_MACSEC_SC_ATTR_MACSEC_XPN64_ENABLE; - attr.value.booldata = xpn64_enable; - attrs.push_back(attr); - - if (sai_macsec_api->create_macsec_sc( - &sc_id, - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) - { - SWSS_LOG_WARN("Cannot create MACsec egress SC %lu", sci); - return false; - } - return true; -} - bool MACsecOrch::deleteMACsecSC(sai_object_id_t sc_id) { SWSS_LOG_ENTER(); @@ -1495,7 +1718,7 @@ bool MACsecOrch::deleteMACsecSC(sai_object_id_t sc_id) task_process_status MACsecOrch::createMACsecSA( const std::string &port_sci_an, const TaskArgs &sa_attr, - sai_int32_t direction) + sai_macsec_direction_t direction) { SWSS_LOG_ENTER(); @@ -1508,29 +1731,20 @@ task_process_status MACsecOrch::createMACsecSA( return task_failed; } - auto macsec_port = m_macsec_ports.find(port_name); - if (macsec_port == m_macsec_ports.end()) - { - SWSS_LOG_INFO("The MACsec port hasn't been created at the port %s.", port_name.c_str()); - return task_need_retry; - } - sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; - if (!getGearboxSwitchId(port_name, switch_id)) + MACsecOrchContext ctx(this, port_name, direction, sci, an); + + if (ctx.get_macsec_sa() != nullptr) { - SWSS_LOG_WARN("Cannot find gearbox at the port %s.", port_name.c_str()); - return task_failed; + SWSS_LOG_NOTICE("The MACsec SA %s has been created.", port_sci_an.c_str()); + return task_success; } - auto &scs = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? macsec_port->second->m_egress_scs - : macsec_port->second->m_ingress_scs; - auto sc = scs.find(sci); - if (sc == scs.end()) + if (ctx.get_macsec_sc() == nullptr) { SWSS_LOG_INFO("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); return task_need_retry; } + auto sc = ctx.get_macsec_sc(); MACsecSAK sak = {{0}, false}; MACsecSalt salt = {0}; @@ -1542,7 +1756,7 @@ task_process_status MACsecOrch::createMACsecSA( SWSS_LOG_WARN("The SAK isn't existed at SA %s", port_sci_an.c_str()); return task_failed; } - if (sc->second.m_xpn64_enable) + if (sc->m_xpn64_enable) { if (!get_value(sa_attr, "salt", salt)) { @@ -1550,12 +1764,11 @@ task_process_status MACsecOrch::createMACsecSA( return task_failed; } } - // TODO Auth Key - // if (!get_value(sa_attr, "auth_key", auth_key)) - // { - // SWSS_LOG_WARN("The auth key isn't existed at SA %s", port_sci_an.c_str()); - // return task_failed; - // } + if (!get_value(sa_attr, "auth_key", auth_key)) + { + SWSS_LOG_WARN("The auth key isn't existed at SA %s", port_sci_an.c_str()); + return task_failed; + } } catch (const std::invalid_argument &e) { @@ -1583,15 +1796,15 @@ task_process_status MACsecOrch::createMACsecSA( RecoverStack recover; if (!createMACsecSA( - sc->second.m_sa_ids[an], - switch_id, + sc->m_sa_ids[an], + *ctx.get_switch_id(), direction, - sc->second.m_sc_id, + sc->m_sc_id, an, - macsec_port->second->m_enable_encrypt, + ctx.get_macsec_port()->m_enable_encrypt, sak.m_sak_256_enable, sak.m_sak, - sc->second.m_xpn64_enable, + sc->m_xpn64_enable, salt.m_salt, auth_key.m_auth_key, pn)) @@ -1599,34 +1812,37 @@ task_process_status MACsecOrch::createMACsecSA( SWSS_LOG_WARN("Cannot create the SA %s", port_sci_an.c_str()); return task_failed; } - recover.add_action([&]() - { - deleteMACsecSA(sc->second.m_sa_ids[an]); - sc->second.m_sa_ids.erase(an); + recover.add_action([this, sc, an]() { + this->deleteMACsecSA(sc->m_sa_ids[an]); + sc->m_sa_ids.erase(an); }); // If this SA is the first SA // change the ACL entry action from packet action to MACsec flow - if (macsec_port->second->m_enable && sc->second.m_sa_ids.size() == 1) + if (ctx.get_macsec_port()->m_enable && sc->m_sa_ids.size() == 1) { - if (!setACLEntryMACsecFlow(sc->second.m_entry_id, sc->second.m_flow_id)) + if (!setACLEntryMACsecFlow(sc->m_entry_id, sc->m_flow_id)) { SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); return task_failed; } - recover.add_action([&]() { setACLEntryPacketAction(sc->second.m_encoding_an, sc->second.m_flow_id); }); + recover.add_action([this, sc]() { + this->setACLEntryPacketAction( + sc->m_encoding_an, + sc->m_flow_id); + }); } std::vector fvVector; fvVector.emplace_back("state", "ok"); if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - installCounter(port_sci_an, sc->second.m_sa_ids[an], macsec_egress_sa_stats); + installCounter(port_sci_an, sc->m_sa_ids[an], macsec_egress_sa_stats); m_state_macsec_egress_sa.set(join('|', port_name, sci, an), fvVector); } else { - installCounter(port_sci_an, sc->second.m_sa_ids[an], macsec_ingress_sa_stats); + installCounter(port_sci_an, sc->m_sa_ids[an], macsec_ingress_sa_stats); m_state_macsec_ingress_sa.set(join('|', port_name, sci, an), fvVector); } @@ -1638,7 +1854,7 @@ task_process_status MACsecOrch::createMACsecSA( task_process_status MACsecOrch::deleteMACsecSA( const std::string &port_sci_an, - sai_int32_t direction) + sai_macsec_direction_t direction) { SWSS_LOG_ENTER(); @@ -1651,47 +1867,33 @@ task_process_status MACsecOrch::deleteMACsecSA( return task_failed; } - auto macsec_port = m_macsec_ports.find(port_name); - if (macsec_port == m_macsec_ports.end()) - { - SWSS_LOG_WARN("The MACsec port hasn't been created at the port %s.", port_name.c_str()); - return task_need_retry; - } - - auto &scs = - (direction == SAI_MACSEC_DIRECTION_EGRESS) - ? macsec_port->second->m_egress_scs - : macsec_port->second->m_ingress_scs; - - auto sc = scs.find(sci); - if (sc == scs.end()) - { - SWSS_LOG_WARN("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); - return task_need_retry; - } + MACsecOrchContext ctx(this, port_name, direction, sci, an); - if (sc->second.m_sa_ids.find(an) == sc->second.m_sa_ids.end()) + if (ctx.get_macsec_sa() == nullptr) { - SWSS_LOG_WARN("The MACsec SA %s hasn't been created.", port_sci_an.c_str()); - return task_need_retry; + SWSS_LOG_INFO("MACsec SA %s has been deleted.", port_sci_an.c_str()); + return task_success; } // If this SA is the last SA // change the ACL entry action from MACsec flow to packet action - if (sc->second.m_sa_ids.size() == 1) + if (ctx.get_macsec_sc()->m_sa_ids.size() == 1) { - if (!setACLEntryPacketAction(sc->second.m_entry_id, sc->second.m_flow_id)) + if (!setACLEntryPacketAction(ctx.get_macsec_sc()->m_entry_id, ctx.get_macsec_sc()->m_flow_id)) { SWSS_LOG_WARN("Cannot change the ACL entry action from MACsec flow to packet action"); } } - uninstallCounter(port_sci_an, sc->second.m_sa_ids[an]); - if (!deleteMACsecSA(sc->second.m_sa_ids[an])) + auto result = task_success; + + uninstallCounter(port_sci_an, ctx.get_macsec_sc()->m_sa_ids[an]); + if (!deleteMACsecSA(ctx.get_macsec_sc()->m_sa_ids[an])) { SWSS_LOG_WARN("Cannot delete the MACsec SA %s.", port_sci_an.c_str()); + result = task_failed; } - sc->second.m_sa_ids.erase(an); + ctx.get_macsec_sc()->m_sa_ids.erase(an); if (direction == SAI_MACSEC_DIRECTION_EGRESS) { @@ -1703,13 +1905,13 @@ task_process_status MACsecOrch::deleteMACsecSA( } SWSS_LOG_NOTICE("MACsec SA %s is deleted.", port_sci_an.c_str()); - return task_success; + return result; } bool MACsecOrch::createMACsecSA( sai_object_id_t &sa_id, sai_object_id_t switch_id, - sai_int32_t direction, + sai_macsec_direction_t direction, sai_object_id_t sc_id, macsec_an_t an, bool encryption_enable, @@ -1825,25 +2027,22 @@ bool MACsecOrch::initACLTable( ACLTable &acl_table, sai_object_id_t port_id, sai_object_id_t switch_id, - sai_int32_t direction, + sai_macsec_direction_t direction, bool sci_in_sectag) { SWSS_LOG_ENTER(); RecoverStack recover; - if (acl_table.m_table_id != SAI_NULL_OBJECT_ID) - { - SWSS_LOG_INFO("The ACL table has been created"); - return true; - } - if (!createACLTable(acl_table.m_table_id, switch_id, direction, sci_in_sectag)) { SWSS_LOG_WARN("Cannot create ACL table"); return false; } - recover.add_action([&]() { deleteACLTable(acl_table.m_table_id); }); + recover.add_action([this, &acl_table]() { + this->deleteACLTable(acl_table.m_table_id); + acl_table.m_table_id = SAI_NULL_OBJECT_ID; + }); if (!createACLEAPOLEntry( acl_table.m_eapol_packet_forward_entry_id, @@ -1853,14 +2052,17 @@ bool MACsecOrch::initACLTable( SWSS_LOG_WARN("Cannot create ACL EAPOL entry"); return false; } - recover.add_action([&]() { deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id); }); + recover.add_action([this, &acl_table]() { + this->deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id); + acl_table.m_eapol_packet_forward_entry_id = SAI_NULL_OBJECT_ID; + }); - if (!bindACLTabletoPort(acl_table.m_table_id, port_id)) + if (!bindACLTabletoPort(acl_table.m_table_id, port_id, direction)) { SWSS_LOG_WARN("Cannot bind ACL table"); return false; } - recover.add_action([&]() { unbindACLTable(port_id); }); + recover.add_action([this, port_id, direction]() { this->unbindACLTable(port_id, direction); }); sai_uint32_t minimum_priority = 0; if (!get_acl_minimum_priority(switch_id, minimum_priority)) @@ -1872,7 +2074,6 @@ bool MACsecOrch::initACLTable( { return false; } - sai_uint32_t priority = minimum_priority + 1; while (priority < maximum_priority) { @@ -1883,16 +2084,20 @@ bool MACsecOrch::initACLTable( acl_table.m_available_acl_priorities.insert(priority); priority += 1; } + recover.add_action([&acl_table]() { acl_table.m_available_acl_priorities.clear(); }); recover.clear(); return true; } -bool MACsecOrch::deinitACLTable(ACLTable &acl_table, sai_object_id_t port_id) +bool MACsecOrch::deinitACLTable( + const ACLTable &acl_table, + sai_object_id_t port_id, + sai_macsec_direction_t direction) { bool result = true; - if (!unbindACLTable(port_id)) + if (!unbindACLTable(port_id, direction)) { SWSS_LOG_WARN("Cannot unbind ACL table"); result &= false; @@ -1914,7 +2119,7 @@ bool MACsecOrch::deinitACLTable(ACLTable &acl_table, sai_object_id_t port_id) bool MACsecOrch::createACLTable( sai_object_id_t &table_id, sai_object_id_t switch_id, - sai_int32_t direction, + sai_macsec_direction_t direction, bool sci_in_sectag) { sai_attribute_t attr; @@ -1970,11 +2175,21 @@ bool MACsecOrch::deleteACLTable(sai_object_id_t table_id) return true; } -bool MACsecOrch::bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t port_id) +bool MACsecOrch::bindACLTabletoPort( + sai_object_id_t table_id, + sai_object_id_t port_id, + sai_macsec_direction_t direction) { sai_attribute_t attr; - attr.id = SAI_PORT_ATTR_INGRESS_MACSEC_ACL; + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + attr.id = SAI_PORT_ATTR_EGRESS_MACSEC_ACL; + } + else + { + attr.id = SAI_PORT_ATTR_INGRESS_MACSEC_ACL; + } attr.value.oid = table_id; if (sai_port_api->set_port_attribute( @@ -1986,11 +2201,20 @@ bool MACsecOrch::bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t po return true; } -bool MACsecOrch::unbindACLTable(sai_object_id_t port_id) +bool MACsecOrch::unbindACLTable( + sai_object_id_t port_id, + sai_macsec_direction_t direction) { sai_attribute_t attr; - attr.id = SAI_PORT_ATTR_INGRESS_MACSEC_ACL; + if (direction == SAI_MACSEC_DIRECTION_EGRESS) + { + attr.id = SAI_PORT_ATTR_EGRESS_MACSEC_ACL; + } + else + { + attr.id = SAI_PORT_ATTR_INGRESS_MACSEC_ACL; + } attr.value.oid = SAI_NULL_OBJECT_ID; if (sai_port_api->set_port_attribute( @@ -2165,9 +2389,9 @@ bool MACsecOrch::get_acl_maximum_priority(sai_object_id_t switch_id, sai_uint32_ attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY; attrs.push_back(attr); if (sai_switch_api->get_switch_attribute( - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Cannot fetch ACL maximum Priority from switch"); return false; @@ -2185,9 +2409,9 @@ bool MACsecOrch::get_acl_minimum_priority(sai_object_id_t switch_id, sai_uint32_ attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY; attrs.push_back(attr); if (sai_switch_api->get_switch_attribute( - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) + switch_id, + static_cast(attrs.size()), + attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Cannot fetch ACL maximum Priority from switch"); return false; @@ -2196,18 +2420,3 @@ bool MACsecOrch::get_acl_minimum_priority(sai_object_id_t switch_id, sai_uint32_ return true; } - -static void wait_break() -{ - std::this_thread::sleep_for(std::chrono::milliseconds(10)); -} - -void break_point() -{ - int state = 1; - while (state != 0) - { - wait_break(); - } -} - diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index ca7169d8d2..5725b051d2 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -38,8 +38,11 @@ using namespace swss; using macsec_an_t = std::uint32_t; +class MACsecOrchContext; + class MACsecOrch : public Orch { + friend class MACsecOrchContext; public: MACsecOrch( DBConnector *app_db, @@ -117,7 +120,7 @@ class MACsecOrch : public Orch { sai_object_id_t m_egress_id; sai_object_id_t m_ingress_id; - map > m_ports; + map > m_macsec_ports; bool m_sci_in_ingress_macsec_acl; }; map m_macsec_objs; @@ -128,66 +131,79 @@ class MACsecOrch : public Orch bool getGearboxSwitchId(const std::string &port_name, sai_object_id_t &switch_id) const; /* MACsec Object */ - map::iterator initMACsecObject(sai_object_id_t switch_id); - bool deinitMACsecObject(map::iterator switch_id); + bool initMACsecObject(sai_object_id_t switch_id); bool deinitMACsecObject(sai_object_id_t switch_id); /* MACsec Port */ - std::shared_ptr createMACsecPort( + bool createMACsecPort( + MACsecPort &macsec_port, const std::string &port_name, - sai_object_id_t port_id, + const TaskArgs & port_attr, + const MACsecObject &macsec_obj, + sai_object_id_t line_port_id, sai_object_id_t switch_id); - bool deleteMACsecPort(const std::string &port_name); + bool createMACsecPort( + sai_object_id_t &macsec_port_id, + sai_object_id_t line_port_id, + sai_object_id_t switch_id, + sai_macsec_direction_t direction); + bool updateMACsecPort(MACsecPort &macsec_port, const TaskArgs & port_attr); + bool deleteMACsecPort( + const MACsecPort &macsec_port, + const std::string &port_name, + const MACsecObject &macsec_obj, + sai_object_id_t line_port_id); + bool deleteMACsecPort(sai_object_id_t macsec_port_id); /* MACsec Flow */ bool createMACsecFlow( sai_object_id_t &flow_id, sai_object_id_t switch_id, - sai_int32_t direction); + sai_macsec_direction_t direction); bool deleteMACsecFlow(sai_object_id_t flow_id); /* MACsec SC */ task_process_status updateMACsecSC( const std::string &port_sci, const TaskArgs &sc_attr, - sai_int32_t direction); - task_process_status setEncodingAN( + sai_macsec_direction_t direction); + bool setEncodingAN( MACsecSC &sc, const TaskArgs &sc_attr, - sai_int32_t direction); - task_process_status createMACsecSC( + sai_macsec_direction_t direction); + bool createMACsecSC( MACsecPort &macsec_port, const std::string &port_name, const TaskArgs &sc_attr, const MACsecObject &macsec_obj, sai_uint64_t sci, sai_object_id_t switch_id, - sai_int32_t direction); - task_process_status deleteMACsecSC( - const std::string &port_sci, - sai_int32_t direction); + sai_macsec_direction_t direction); bool createMACsecSC( sai_object_id_t &sc_id, sai_object_id_t switch_id, - sai_int32_t direction, + sai_macsec_direction_t direction, sai_object_id_t flow_id, sai_uint64_t sci, sai_uint32_t ssci, bool xpn64_enable); + task_process_status deleteMACsecSC( + const std::string &port_sci, + sai_macsec_direction_t direction); bool deleteMACsecSC(sai_object_id_t sc_id); /* MACsec SA */ task_process_status createMACsecSA( const std::string &port_sci_an, const TaskArgs &sa_attr, - sai_int32_t direction); + sai_macsec_direction_t direction); task_process_status deleteMACsecSA( const std::string &port_sci_an, - sai_int32_t direction); + sai_macsec_direction_t direction); bool createMACsecSA( sai_object_id_t &sa_id, sai_object_id_t switch_id, - sai_int32_t direction, + sai_macsec_direction_t direction, sai_object_id_t sc_id, macsec_an_t an, bool encryption_enable, @@ -211,19 +227,20 @@ class MACsecOrch : public Orch ACLTable &acl_table, sai_object_id_t port_id, sai_object_id_t switch_id, - sai_int32_t direction, + sai_macsec_direction_t direction, bool sci_in_sectag); bool deinitACLTable( - ACLTable &acl_table, - sai_object_id_t port_id); + const ACLTable &acl_table, + sai_object_id_t port_id, + sai_macsec_direction_t direction); bool createACLTable( sai_object_id_t &table_id, sai_object_id_t switch_id, - sai_int32_t direction, + sai_macsec_direction_t direction, bool sci_in_sectag); bool deleteACLTable(sai_object_id_t table_id); - bool bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t port_id); - bool unbindACLTable(sai_object_id_t port_id); + bool bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t port_id, sai_macsec_direction_t direction); + bool unbindACLTable(sai_object_id_t port_id, sai_macsec_direction_t direction); bool createACLEAPOLEntry( sai_object_id_t &entry_id, sai_object_id_t table_id, @@ -250,22 +267,4 @@ class MACsecOrch : public Orch sai_uint32_t &priority) const; }; -// The following code is only for debugging - -// #undef SWSS_LOG_ERROR -// #undef SWSS_LOG_WARN -// #undef SWSS_LOG_NOTICE -// #undef SWSS_LOG_INFO -// #undef SWSS_LOG_DEBUG -// #undef SWSS_LOG_ENTER - -// #define SWSS_LOG_ERROR(MSG, ...) printf("ERROR %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -// #define SWSS_LOG_WARN(MSG, ...) printf("WARN %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -// #define SWSS_LOG_NOTICE(MSG, ...) printf("NOTICE %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -// #define SWSS_LOG_INFO(MSG, ...) printf("INFO %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -// #define SWSS_LOG_DEBUG(MSG, ...) printf("DEBUG %s :- %s: " MSG"\n", __FILE__, __FUNCTION__, ##__VA_ARGS__) -// #define SWSS_LOG_ENTER() printf("ENTER %s : - %s : %d\n", __FILE__, __FUNCTION__, __LINE__) - -void break_point(); - #endif // ORCHAGENT_MACSECORCH_H_ From 47d8fac723b9a283453cf7da20abea829f645aca Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 10 Sep 2020 17:36:01 +0800 Subject: [PATCH 06/31] Polish flex counter name Signed-off-by: Ze Gan --- orchagent/flex_counter/flex_counter_manager.cpp | 4 +++- orchagent/macsecorch.cpp | 8 ++++---- orchagent/macsecorch.h | 13 +++++++------ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/orchagent/flex_counter/flex_counter_manager.cpp b/orchagent/flex_counter/flex_counter_manager.cpp index 4df2c7a0ed..3d3f897f87 100644 --- a/orchagent/flex_counter/flex_counter_manager.cpp +++ b/orchagent/flex_counter/flex_counter_manager.cpp @@ -7,6 +7,8 @@ #include "logger.h" #include "sai_serialize.h" +#include + using std::shared_ptr; using std::string; using std::unordered_map; @@ -36,7 +38,7 @@ const unordered_map FlexCounterManager::counter_id_field_lo { CounterType::SWITCH_DEBUG, SWITCH_DEBUG_COUNTER_ID_LIST }, { CounterType::PORT, PORT_COUNTER_ID_LIST }, { CounterType::QUEUE, QUEUE_COUNTER_ID_LIST }, - { CounterType::MACSEC, "MACSEC_COUNTER_ID_LIST" }, + { CounterType::MACSEC, MACSEC_ATTR_ID_LIST }, }; FlexCounterManager::FlexCounterManager( diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 2c74ef9c91..77353b181e 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -597,8 +597,8 @@ MACsecOrch::MACsecOrch( m_state_macsec_ingress_sa(state_db, STATE_MACSEC_INGRESS_SA_TABLE_NAME), m_counter_db("COUNTERS_DB", 0), m_macsec_counters_map(&m_counter_db, COUNTERS_MACSEC_NAME_MAP), - m_macsec_stat_manager( - COUNTERS_MACSEC_TABLE, + m_macsec_attr_flex_counter_manager( + COUNTERS_MACSEC_ATTR_TABLE, StatsMode::READ, MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true), m_gearbox_table(app_db, "_GEARBOX_TABLE"), @@ -2012,12 +2012,12 @@ void MACsecOrch::installCounter( { counter_stats.emplace(stat); } - m_macsec_stat_manager.setCounterIdList(obj_id, CounterType::MACSEC, counter_stats); + m_macsec_attr_flex_counter_manager.setCounterIdList(obj_id, CounterType::MACSEC, counter_stats); } void MACsecOrch::uninstallCounter(const std::string &obj_name, sai_object_id_t obj_id) { - m_macsec_stat_manager.clearCounterIdList(obj_id); + m_macsec_attr_flex_counter_manager.clearCounterIdList(obj_id); RedisClient redisClient(&m_counter_db); redisClient.hdel(COUNTERS_PORT_NAME_MAP, obj_name); diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index 5725b051d2..7514d00105 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -16,7 +16,8 @@ #define STATE_MACSEC_INGRESS_SA_TABLE_NAME "MACSEC_INGRESS_SA_TABLE" #define COUNTERS_MACSEC_NAME_MAP "COUNTERS_MACSEC_NAME_MAP" -#define COUNTERS_MACSEC_TABLE "COUNTERS_MACSEC" +#define COUNTERS_MACSEC_ATTR_TABLE "COUNTERS_MACSEC_ATTR" +#define MACSEC_ATTR_ID_LIST "MACSEC_ATTR_ID_LIST" // End define @@ -80,12 +81,12 @@ class MACsecOrch : public Orch DBConnector m_counter_db; Table m_macsec_counters_map; - FlexCounterManager m_macsec_stat_manager; + FlexCounterManager m_macsec_attr_flex_counter_manager; - Table m_gearbox_table; - bool m_gearbox_enabled; - map m_gearbox_phy_map; - map m_gearbox_interface_map; + Table m_gearbox_table; + bool m_gearbox_enabled; + map m_gearbox_phy_map; + map m_gearbox_interface_map; struct ACLTable { sai_object_id_t m_table_id; From 8b8c7eee621c6ff5e318ead58ba4816424a4f6c7 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 10 Sep 2020 22:15:32 +0800 Subject: [PATCH 07/31] Polish flex counter name Signed-off-by: Ze Gan --- orchagent/flex_counter/flex_counter_manager.cpp | 2 +- orchagent/flex_counter/flex_counter_manager.h | 2 +- orchagent/macsecorch.cpp | 7 ++++--- orchagent/macsecorch.h | 4 +++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/orchagent/flex_counter/flex_counter_manager.cpp b/orchagent/flex_counter/flex_counter_manager.cpp index 3d3f897f87..b038d66776 100644 --- a/orchagent/flex_counter/flex_counter_manager.cpp +++ b/orchagent/flex_counter/flex_counter_manager.cpp @@ -38,7 +38,7 @@ const unordered_map FlexCounterManager::counter_id_field_lo { CounterType::SWITCH_DEBUG, SWITCH_DEBUG_COUNTER_ID_LIST }, { CounterType::PORT, PORT_COUNTER_ID_LIST }, { CounterType::QUEUE, QUEUE_COUNTER_ID_LIST }, - { CounterType::MACSEC, MACSEC_ATTR_ID_LIST }, + { CounterType::MACSEC_SA, MACSEC_SA_ATTR_ID_LIST }, }; FlexCounterManager::FlexCounterManager( diff --git a/orchagent/flex_counter/flex_counter_manager.h b/orchagent/flex_counter/flex_counter_manager.h index 12a0c65529..e8f077c246 100644 --- a/orchagent/flex_counter/flex_counter_manager.h +++ b/orchagent/flex_counter/flex_counter_manager.h @@ -23,7 +23,7 @@ enum class CounterType QUEUE, PORT_DEBUG, SWITCH_DEBUG, - MACSEC, + MACSEC_SA, }; // FlexCounterManager allows users to manage a group of flex counters. diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 77353b181e..d1b00af9ef 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -1837,12 +1837,12 @@ task_process_status MACsecOrch::createMACsecSA( fvVector.emplace_back("state", "ok"); if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - installCounter(port_sci_an, sc->m_sa_ids[an], macsec_egress_sa_stats); + installCounter(CounterType::MACSEC_SA, port_sci_an, sc->m_sa_ids[an], macsec_egress_sa_stats); m_state_macsec_egress_sa.set(join('|', port_name, sci, an), fvVector); } else { - installCounter(port_sci_an, sc->m_sa_ids[an], macsec_ingress_sa_stats); + installCounter(CounterType::MACSEC_SA, port_sci_an, sc->m_sa_ids[an], macsec_ingress_sa_stats); m_state_macsec_ingress_sa.set(join('|', port_name, sci, an), fvVector); } @@ -1998,6 +1998,7 @@ bool MACsecOrch::deleteMACsecSA(sai_object_id_t sa_id) } void MACsecOrch::installCounter( + CounterType counter_type, const std::string &obj_name, sai_object_id_t obj_id, const std::vector &stats) @@ -2012,7 +2013,7 @@ void MACsecOrch::installCounter( { counter_stats.emplace(stat); } - m_macsec_attr_flex_counter_manager.setCounterIdList(obj_id, CounterType::MACSEC, counter_stats); + m_macsec_attr_flex_counter_manager.setCounterIdList(obj_id, counter_type, counter_stats); } void MACsecOrch::uninstallCounter(const std::string &obj_name, sai_object_id_t obj_id) diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index 7514d00105..436e0b8acf 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -17,13 +17,14 @@ #define COUNTERS_MACSEC_NAME_MAP "COUNTERS_MACSEC_NAME_MAP" #define COUNTERS_MACSEC_ATTR_TABLE "COUNTERS_MACSEC_ATTR" -#define MACSEC_ATTR_ID_LIST "MACSEC_ATTR_ID_LIST" +#define MACSEC_SA_ATTR_ID_LIST "MACSEC_SA_ATTR_ID_LIST" // End define #include "orch.h" #include "portsorch.h" +#include "flex_counter_manager.h" #include @@ -218,6 +219,7 @@ class MACsecOrch : public Orch /* Counter */ void installCounter( + CounterType counter_type, const std::string &obj_name, sai_object_id_t obj_id, const std::vector &stats); From 2a53cb542f7e064955db4b4b5acabf8565eee90d Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 11 Sep 2020 14:44:17 +0800 Subject: [PATCH 08/31] Polish flex counter name Signed-off-by: Ze Gan --- orchagent/flex_counter/flex_counter_manager.cpp | 10 +++++----- orchagent/flex_counter/flex_counter_manager.h | 2 +- orchagent/macsecorch.cpp | 10 +++++----- orchagent/macsecorch.h | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/orchagent/flex_counter/flex_counter_manager.cpp b/orchagent/flex_counter/flex_counter_manager.cpp index b038d66776..299e238d37 100644 --- a/orchagent/flex_counter/flex_counter_manager.cpp +++ b/orchagent/flex_counter/flex_counter_manager.cpp @@ -34,11 +34,11 @@ const unordered_map FlexCounterManager::status_lookup = const unordered_map FlexCounterManager::counter_id_field_lookup = { - { CounterType::PORT_DEBUG, PORT_DEBUG_COUNTER_ID_LIST }, - { CounterType::SWITCH_DEBUG, SWITCH_DEBUG_COUNTER_ID_LIST }, - { CounterType::PORT, PORT_COUNTER_ID_LIST }, - { CounterType::QUEUE, QUEUE_COUNTER_ID_LIST }, - { CounterType::MACSEC_SA, MACSEC_SA_ATTR_ID_LIST }, + { CounterType::PORT_DEBUG, PORT_DEBUG_COUNTER_ID_LIST }, + { CounterType::SWITCH_DEBUG, SWITCH_DEBUG_COUNTER_ID_LIST }, + { CounterType::PORT, PORT_COUNTER_ID_LIST }, + { CounterType::QUEUE, QUEUE_COUNTER_ID_LIST }, + { CounterType::MACSEC_SA_ATTR, MACSEC_SA_ATTR_ID_LIST }, }; FlexCounterManager::FlexCounterManager( diff --git a/orchagent/flex_counter/flex_counter_manager.h b/orchagent/flex_counter/flex_counter_manager.h index e8f077c246..4df99c90bd 100644 --- a/orchagent/flex_counter/flex_counter_manager.h +++ b/orchagent/flex_counter/flex_counter_manager.h @@ -23,7 +23,7 @@ enum class CounterType QUEUE, PORT_DEBUG, SWITCH_DEBUG, - MACSEC_SA, + MACSEC_SA_ATTR, }; // FlexCounterManager allows users to manage a group of flex counters. diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index d1b00af9ef..e10f2014d6 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -597,7 +597,7 @@ MACsecOrch::MACsecOrch( m_state_macsec_ingress_sa(state_db, STATE_MACSEC_INGRESS_SA_TABLE_NAME), m_counter_db("COUNTERS_DB", 0), m_macsec_counters_map(&m_counter_db, COUNTERS_MACSEC_NAME_MAP), - m_macsec_attr_flex_counter_manager( + m_macsec_flex_counter_manager( COUNTERS_MACSEC_ATTR_TABLE, StatsMode::READ, MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true), @@ -1837,12 +1837,12 @@ task_process_status MACsecOrch::createMACsecSA( fvVector.emplace_back("state", "ok"); if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - installCounter(CounterType::MACSEC_SA, port_sci_an, sc->m_sa_ids[an], macsec_egress_sa_stats); + installCounter(CounterType::MACSEC_SA_ATTR, port_sci_an, sc->m_sa_ids[an], macsec_egress_sa_stats); m_state_macsec_egress_sa.set(join('|', port_name, sci, an), fvVector); } else { - installCounter(CounterType::MACSEC_SA, port_sci_an, sc->m_sa_ids[an], macsec_ingress_sa_stats); + installCounter(CounterType::MACSEC_SA_ATTR, port_sci_an, sc->m_sa_ids[an], macsec_ingress_sa_stats); m_state_macsec_ingress_sa.set(join('|', port_name, sci, an), fvVector); } @@ -2013,12 +2013,12 @@ void MACsecOrch::installCounter( { counter_stats.emplace(stat); } - m_macsec_attr_flex_counter_manager.setCounterIdList(obj_id, counter_type, counter_stats); + m_macsec_flex_counter_manager.setCounterIdList(obj_id, counter_type, counter_stats); } void MACsecOrch::uninstallCounter(const std::string &obj_name, sai_object_id_t obj_id) { - m_macsec_attr_flex_counter_manager.clearCounterIdList(obj_id); + m_macsec_flex_counter_manager.clearCounterIdList(obj_id); RedisClient redisClient(&m_counter_db); redisClient.hdel(COUNTERS_PORT_NAME_MAP, obj_name); diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index 436e0b8acf..cc9d5c0043 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -82,7 +82,7 @@ class MACsecOrch : public Orch DBConnector m_counter_db; Table m_macsec_counters_map; - FlexCounterManager m_macsec_attr_flex_counter_manager; + FlexCounterManager m_macsec_flex_counter_manager; Table m_gearbox_table; bool m_gearbox_enabled; From 563785079b379b0f441f4b6cbd2a21c8d40e500b Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 17 Sep 2020 01:02:43 +0800 Subject: [PATCH 09/31] add macsecorch to Makefile Signed-off-by: Ze Gan --- tests/mock_tests/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mock_tests/Makefile.am b/tests/mock_tests/Makefile.am index d8a8036fb1..6e6f30b348 100644 --- a/tests/mock_tests/Makefile.am +++ b/tests/mock_tests/Makefile.am @@ -63,7 +63,8 @@ tests_SOURCES = aclorch_ut.cpp \ $(top_srcdir)/orchagent/chassisorch.cpp \ $(top_srcdir)/orchagent/sfloworch.cpp \ $(top_srcdir)/orchagent/debugcounterorch.cpp \ - $(top_srcdir)/orchagent/natorch.cpp + $(top_srcdir)/orchagent/natorch.cpp \ + $(top_srcdir)/orchagent/macsecorch.cpp tests_SOURCES += $(FLEX_CTR_DIR)/flex_counter_manager.cpp $(FLEX_CTR_DIR)/flex_counter_stat_manager.cpp tests_SOURCES += $(DEBUG_CTR_DIR)/debug_counter.cpp $(DEBUG_CTR_DIR)/drop_counter.cpp From 8474ad4b9eb765c165f249bbe35face643bf6f33 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 17 Sep 2020 15:29:07 +0800 Subject: [PATCH 10/31] Fix uninstall macsec counter Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index e10f2014d6..7009e916ae 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -75,12 +75,12 @@ struct MockSAIAPI MockSAIFunc(set_acl_entry_attribute); }; -static MockSAIAPI mock_api; +// static MockSAIAPI mock_api; -static MockSAIAPI *sai_macsec_api = &mock_api; -static MockSAIAPI *sai_acl_api = &mock_api; -static MockSAIAPI *sai_port_api = &mock_api; -static MockSAIAPI *sai_switch_api = &mock_api; +// static MockSAIAPI *sai_macsec_api = &mock_api; +// static MockSAIAPI *sai_acl_api = &mock_api; +// static MockSAIAPI *sai_port_api = &mock_api; +// static MockSAIAPI *sai_switch_api = &mock_api; #define MOCK_RETURN_BOOL return true; @@ -92,10 +92,10 @@ static MockSAIAPI *sai_switch_api = &mock_api; #define EAPOL_ETHER_TYPE 0x888e #define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000 -// extern sai_macsec_api_t *sai_macsec_api; -// extern sai_acl_api_t *sai_acl_api; -// extern sai_port_api_t *sai_port_api; -// extern sai_switch_api_t *sai_switch_api; +extern sai_macsec_api_t *sai_macsec_api; +extern sai_acl_api_t *sai_acl_api; +extern sai_port_api_t *sai_port_api; +extern sai_switch_api_t *sai_switch_api; static const std::vector macsec_egress_sa_stats = { @@ -2021,7 +2021,7 @@ void MACsecOrch::uninstallCounter(const std::string &obj_name, sai_object_id_t o m_macsec_flex_counter_manager.clearCounterIdList(obj_id); RedisClient redisClient(&m_counter_db); - redisClient.hdel(COUNTERS_PORT_NAME_MAP, obj_name); + redisClient.hdel(COUNTERS_MACSEC_NAME_MAP, obj_name); } bool MACsecOrch::initACLTable( From d7d487876c289127ff285cf3a31acb88b0b824ac Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Tue, 22 Sep 2020 16:49:27 +0800 Subject: [PATCH 11/31] Integrate with Redis SAI Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 70 +++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 7009e916ae..1ba42f5bf3 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -82,7 +82,23 @@ struct MockSAIAPI // static MockSAIAPI *sai_port_api = &mock_api; // static MockSAIAPI *sai_switch_api = &mock_api; -#define MOCK_RETURN_BOOL return true; +extern sai_object_id_t gSwitchId; + +#define MOCK_GEARBOX_SWITCH_ID_AND_RETURN_TRUE \ +do \ +{ \ + switch_id = gSwitchId; \ + return true; \ +}while(0); + +#define MOCK_GEARBOX_LINE_PORT_ID(port) \ +do \ +{ \ + port->m_line_port_id = port->m_port_id; \ +}while(0); + +// #undef SWSS_LOG_ENTER +// #define SWSS_LOG_ENTER() swss::Logger::ScopeLogger logger ## __LINE__ (__LINE__, __PRETTY_FUNCTION__) /* Finish Debug */ @@ -192,7 +208,7 @@ static bool get_value( fvValue(*itr).c_str()); return true; } - SWSS_LOG_WARN("Cannot find field : %s", field.c_str()); + SWSS_LOG_DEBUG("Cannot find field : %s", field.c_str()); return false; } @@ -236,10 +252,18 @@ static bool hex_to_binary( return false; } std::stringstream stream; + if ( + !!!std::isxdigit(static_cast(hex_str[hex_cur])) + || !!!std::isxdigit(static_cast(hex_str[hex_cur + 1]))) + { + return false; + } stream << std::hex; stream << hex_str[hex_cur++]; stream << hex_str[hex_cur++]; - stream >> buffer[buffer_cur++]; + std::uint32_t value; + stream >> value; + buffer[buffer_cur++] = static_cast(value); } return hex_cur == hex_str.length(); } @@ -262,7 +286,7 @@ static std::istringstream &operator>>( sak.m_sak_256_enable = false; convert_done = hex_to_binary( buffer, - &sak.m_sak[8], + sak.m_sak, sizeof(sak.m_sak) / 2); } else if (buffer.length() == sizeof(sak.m_sak) * 2) @@ -406,6 +430,7 @@ class MACsecOrchContext return nullptr; } m_port = std::move(port); + MOCK_GEARBOX_LINE_PORT_ID(m_port); } return m_port.get(); } @@ -962,7 +987,7 @@ bool MACsecOrch::getGearboxSwitchId(const std::string &port_name, sai_object_id_ bool MACsecOrch::getGearboxSwitchId(const Port &port, sai_object_id_t &switch_id) const { - MOCK_RETURN_BOOL; + MOCK_GEARBOX_SWITCH_ID_AND_RETURN_TRUE; SWSS_LOG_ENTER(); auto phy_id = m_gearbox_interface_map.find(port.m_index); @@ -1669,20 +1694,21 @@ task_process_status MACsecOrch::deleteMACsecSC( deleteACLEntry(ctx.get_macsec_sc()->m_entry_id); ctx.get_acl_table()->m_available_acl_priorities.insert(ctx.get_macsec_sc()->m_acl_priority); + if (!deleteMACsecSC(ctx.get_macsec_sc()->m_sc_id)) + { + SWSS_LOG_WARN("The MACsec SC %s cannot be deleted", port_sci.c_str()); + result = task_failed; + } + if (ctx.get_macsec_obj()->m_sci_in_ingress_macsec_acl) { - if (deleteMACsecFlow(ctx.get_macsec_sc()->m_flow_id)) + if (!deleteMACsecFlow(ctx.get_macsec_sc()->m_flow_id)) { SWSS_LOG_WARN("Cannot delete MACsec flow"); result = task_failed; } } - if (!deleteMACsecSC(ctx.get_macsec_sc()->m_sc_id)) - { - SWSS_LOG_WARN("The MACsec SC %s cannot be deleted", port_sci.c_str()); - result = task_failed; - } auto scs = (direction == SAI_MACSEC_DIRECTION_EGRESS) ? &ctx.get_macsec_port()->m_egress_scs @@ -1940,23 +1966,24 @@ bool MACsecOrch::createMACsecSA( attrs.push_back(attr); attr.id = SAI_MACSEC_SA_ATTR_ENCRYPTION_ENABLE; - attr.value.u8 = encryption_enable; + attr.value.booldata = encryption_enable; attrs.push_back(attr); attr.id = SAI_MACSEC_SA_ATTR_SAK_256_BITS; - attr.value.u8 = sak_256_bit; + attr.value.booldata = sak_256_bit; attrs.push_back(attr); attr.id = SAI_MACSEC_SA_ATTR_SAK; std::copy(sak, sak + sizeof(attr.value.macsecsak), attr.value.macsecsak); attrs.push_back(attr); - if (xpn64_enable) - { + // Valid when SAI_MACSEC_SC_ATTR_MACSEC_XPN64_ENABLE == true. + // if (xpn64_enable) + // { attr.id = SAI_MACSEC_SA_ATTR_SALT; std::copy(salt, salt + sizeof(attr.value.macsecsalt), attr.value.macsecsalt); attrs.push_back(attr); - } + // } attr.id = SAI_MACSEC_SA_ATTR_AUTH_KEY; std::copy(auth_key, auth_key + sizeof(attr.value.macsecauthkey), attr.value.macsecauthkey); @@ -2235,6 +2262,9 @@ bool MACsecOrch::createACLEAPOLEntry( sai_attribute_t attr; std::vector attrs; + static const MacAddress nearest_non_tpmr_bridge("01:80:c2:00:00:03"); + static const MacAddress mac_address_mask("ff:ff:ff:ff:ff:ff"); + attr.id = SAI_ACL_ENTRY_ATTR_TABLE_ID; attr.value.oid = table_id; attrs.push_back(attr); @@ -2248,10 +2278,7 @@ bool MACsecOrch::createACLEAPOLEntry( attr.value.booldata = true; attrs.push_back(attr); attr.id = SAI_ACL_ENTRY_ATTR_FIELD_DST_MAC; - static const MacAddress nearest_non_tpmr_bridge("01:80:c2:00:00:03"); nearest_non_tpmr_bridge.getMac(attr.value.aclfield.data.mac); - attrs.push_back(attr); - static const MacAddress mac_address_mask("ff:ff:ff:ff:ff:ff"); mac_address_mask.getMac(attr.value.aclfield.mask.mac); attr.value.aclfield.enable = true; attrs.push_back(attr); @@ -2299,9 +2326,6 @@ bool MACsecOrch::createACLDataEntry( attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_DROP; attr.value.aclaction.enable = true; attrs.push_back(attr); - attr.id = SAI_ACL_TABLE_ATTR_FIELD_MACSEC_SCI; - attr.value.booldata = sci_in_sectag; - attrs.push_back(attr); if (sci_in_sectag) { attr.id = SAI_ACL_ENTRY_ATTR_FIELD_MACSEC_SCI; @@ -2324,6 +2348,7 @@ bool MACsecOrch::setACLEntryPacketAction(sai_object_id_t entry_id, sai_object_id sai_attribute_t attr; attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; + attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_DROP; attr.value.aclaction.enable = true; if (sai_acl_api->set_acl_entry_attribute( entry_id, @@ -2361,6 +2386,7 @@ bool MACsecOrch::setACLEntryMACsecFlow(sai_object_id_t entry_id, sai_object_id_t } attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; + attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_DROP; attr.value.aclaction.enable = false; if (sai_acl_api->set_acl_entry_attribute( entry_id, From 6ef8bf658f82b0b9f0bd1097f35c3aa25e645c1a Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 2 Oct 2020 10:07:01 +0800 Subject: [PATCH 12/31] fix typo bug Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 113 ++++++++++++++++----------------------- orchagent/macsecorch.h | 10 ++-- 2 files changed, 49 insertions(+), 74 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 1ba42f5bf3..d5d79416d2 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -104,7 +104,7 @@ do \ /* Global Variables*/ -#define PRIORITY_LIMITATION 32 +#define AVAILABLE_ACL_PRIORITIES_LIMITATION 32 #define EAPOL_ETHER_TYPE 0x888e #define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000 @@ -1238,7 +1238,7 @@ bool MACsecOrch::createMACsecPort( sai_attribute_t attr; std::vector attrs; - attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.id = SAI_MACSEC_PORT_ATTR_MACSEC_DIRECTION; attr.value.s32 = direction; attrs.push_back(attr); attr.id = SAI_MACSEC_PORT_ATTR_PORT_ID; @@ -1267,11 +1267,11 @@ bool MACsecOrch::updateMACsecPort(MACsecPort &macsec_port, const TaskArgs &port_ if (get_value(port_attr, "enable", macsec_port.m_enable)) { std::vector macsec_scs; - for (auto sc : macsec_port.m_egress_scs) + for (auto &sc : macsec_port.m_egress_scs) { macsec_scs.push_back(&sc.second); } - for (auto sc : macsec_port.m_ingress_scs) + for (auto &sc : macsec_port.m_ingress_scs) { macsec_scs.push_back(&sc.second); } @@ -1280,18 +1280,18 @@ bool MACsecOrch::updateMACsecPort(MACsecPort &macsec_port, const TaskArgs &port_ // Change the ACL entry action from packet action to MACsec flow if (macsec_port.m_enable) { - if (!setACLEntryMACsecFlow(macsec_sc->m_entry_id, macsec_sc->m_flow_id)) + if (!setACLEntryMACsecFlowActive(macsec_sc->m_entry_id, macsec_sc->m_flow_id, true)) { SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); return false; } auto an = macsec_sc->m_encoding_an; auto flow_id = macsec_sc->m_flow_id; - recover.add_action([this, an, flow_id]() { this->setACLEntryPacketAction(an, flow_id); }); + recover.add_action([this, an, flow_id]() { this->setACLEntryMACsecFlowActive(an, flow_id, false); }); } else { - setACLEntryPacketAction(macsec_sc->m_encoding_an, macsec_sc->m_flow_id); + setACLEntryMACsecFlowActive(macsec_sc->m_encoding_an, macsec_sc->m_flow_id, false); } } } @@ -1310,7 +1310,7 @@ bool MACsecOrch::deleteMACsecPort( bool result = true; - for (auto sc : macsec_port.m_egress_scs) + for (auto &sc : macsec_port.m_egress_scs) { const std::string port_sci = join(':', port_name, sc.first); if (deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS) != task_success) @@ -1318,7 +1318,7 @@ bool MACsecOrch::deleteMACsecPort( result &= false; } } - for (auto sc : macsec_port.m_ingress_scs) + for (auto &sc : macsec_port.m_ingress_scs) { const std::string port_sci = join(':', port_name, sc.first); if (deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS) != task_success) @@ -1396,7 +1396,7 @@ bool MACsecOrch::createMACsecFlow( sai_attribute_t attr; std::vector attrs; - attr.id = SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION; + attr.id = SAI_MACSEC_FLOW_ATTR_MACSEC_DIRECTION; attr.value.s32 = direction; attrs.push_back(attr); if (sai_macsec_api->create_macsec_flow( @@ -1685,7 +1685,7 @@ task_process_status MACsecOrch::deleteMACsecSC( auto result = task_success; - for (auto sa : ctx.get_macsec_sc()->m_sa_ids) + for (auto &sa : ctx.get_macsec_sc()->m_sa_ids) { const std::string port_sci_an = join(':', port_sci, sa.first); deleteMACsecSA(port_sci_an, direction); @@ -1821,6 +1821,23 @@ task_process_status MACsecOrch::createMACsecSA( RecoverStack recover; + // If this SA is the first SA + // change the ACL entry action from packet action to MACsec flow + if (ctx.get_macsec_port()->m_enable && sc->m_sa_ids.empty()) + { + if (!setACLEntryMACsecFlowActive(sc->m_entry_id, sc->m_flow_id, true)) + { + SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); + return task_failed; + } + recover.add_action([this, sc]() { + this->setACLEntryMACsecFlowActive( + sc->m_encoding_an, + sc->m_flow_id, + false); + }); + } + if (!createMACsecSA( sc->m_sa_ids[an], *ctx.get_switch_id(), @@ -1843,22 +1860,6 @@ task_process_status MACsecOrch::createMACsecSA( sc->m_sa_ids.erase(an); }); - // If this SA is the first SA - // change the ACL entry action from packet action to MACsec flow - if (ctx.get_macsec_port()->m_enable && sc->m_sa_ids.size() == 1) - { - if (!setACLEntryMACsecFlow(sc->m_entry_id, sc->m_flow_id)) - { - SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); - return task_failed; - } - recover.add_action([this, sc]() { - this->setACLEntryPacketAction( - sc->m_encoding_an, - sc->m_flow_id); - }); - } - std::vector fvVector; fvVector.emplace_back("state", "ok"); if (direction == SAI_MACSEC_DIRECTION_EGRESS) @@ -1901,16 +1902,6 @@ task_process_status MACsecOrch::deleteMACsecSA( return task_success; } - // If this SA is the last SA - // change the ACL entry action from MACsec flow to packet action - if (ctx.get_macsec_sc()->m_sa_ids.size() == 1) - { - if (!setACLEntryPacketAction(ctx.get_macsec_sc()->m_entry_id, ctx.get_macsec_sc()->m_flow_id)) - { - SWSS_LOG_WARN("Cannot change the ACL entry action from MACsec flow to packet action"); - } - } - auto result = task_success; uninstallCounter(port_sci_an, ctx.get_macsec_sc()->m_sa_ids[an]); @@ -1921,6 +1912,18 @@ task_process_status MACsecOrch::deleteMACsecSA( } ctx.get_macsec_sc()->m_sa_ids.erase(an); + // If this SA is the last SA + // change the ACL entry action from MACsec flow to packet action + if (ctx.get_macsec_sc()->m_sa_ids.empty()) + { + if (!setACLEntryMACsecFlowActive(ctx.get_macsec_sc()->m_entry_id, ctx.get_macsec_sc()->m_flow_id, false)) + { + SWSS_LOG_WARN("Cannot change the ACL entry action from MACsec flow to packet action"); + result = task_failed; + } + } + + if (direction == SAI_MACSEC_DIRECTION_EGRESS) { m_state_macsec_egress_sa.del(join('|', port_name, sci, an)); @@ -2105,7 +2108,7 @@ bool MACsecOrch::initACLTable( sai_uint32_t priority = minimum_priority + 1; while (priority < maximum_priority) { - if (acl_table.m_available_acl_priorities.size() >= PRIORITY_LIMITATION) + if (acl_table.m_available_acl_priorities.size() >= AVAILABLE_ACL_PRIORITIES_LIMITATION) { break; } @@ -2343,40 +2346,14 @@ bool MACsecOrch::createACLDataEntry( return true; } -bool MACsecOrch::setACLEntryPacketAction(sai_object_id_t entry_id, sai_object_id_t flow_id) +bool MACsecOrch::setACLEntryMACsecFlowActive(sai_object_id_t entry_id, sai_object_id_t flow_id, bool active) { sai_attribute_t attr; - attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; - attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_DROP; - attr.value.aclaction.enable = true; - if (sai_acl_api->set_acl_entry_attribute( - entry_id, - &attr) != SAI_STATUS_SUCCESS) - { - return false; - } - + SWSS_LOG_NOTICE("GANZE entry %lu flow %lu active %s", entry_id, flow_id, active ? "TRUE" : "FALSE"); attr.id = SAI_ACL_ENTRY_ATTR_ACTION_MACSEC_FLOW; attr.value.aclaction.parameter.oid = flow_id; - attr.value.aclaction.enable = false; - - if (sai_acl_api->set_acl_entry_attribute( - entry_id, - &attr) != SAI_STATUS_SUCCESS) - { - return false; - } - return true; -} - -bool MACsecOrch::setACLEntryMACsecFlow(sai_object_id_t entry_id, sai_object_id_t flow_id) -{ - sai_attribute_t attr; - - attr.id = SAI_ACL_ENTRY_ATTR_ACTION_MACSEC_FLOW; - attr.value.aclaction.parameter.oid = flow_id; - attr.value.aclaction.enable = true; + attr.value.aclaction.enable = active; if (sai_acl_api->set_acl_entry_attribute( entry_id, @@ -2387,7 +2364,7 @@ bool MACsecOrch::setACLEntryMACsecFlow(sai_object_id_t entry_id, sai_object_id_t attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_DROP; - attr.value.aclaction.enable = false; + attr.value.aclaction.enable = !active; if (sai_acl_api->set_acl_entry_attribute( entry_id, &attr) != SAI_STATUS_SUCCESS) diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index cc9d5c0043..9108fd0f50 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -38,7 +38,7 @@ using namespace swss; // AN is a 2 bit number, it can only be 0, 1, 2 or 3 #define MAX_SA_NUMBER (3) -using macsec_an_t = std::uint32_t; +using macsec_an_t = std::uint16_t; class MACsecOrchContext; @@ -255,12 +255,10 @@ class MACsecOrch : public Orch bool sci_in_sectag, sai_uint64_t sci, sai_uint32_t priority); - bool setACLEntryPacketAction( + bool setACLEntryMACsecFlowActive( sai_object_id_t entry_id, - sai_object_id_t flow_id); - bool setACLEntryMACsecFlow( - sai_object_id_t entry_id, - sai_object_id_t flow_id); + sai_object_id_t flow_id, + bool active); bool deleteACLEntry(sai_object_id_t entry_id); bool get_acl_maximum_priority( sai_object_id_t switch_id, From cedf1858bbc482c405c193230594958810ea15a8 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Mon, 12 Oct 2020 11:14:49 +0800 Subject: [PATCH 13/31] Remove gearbox Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 163 +++++++++++---------------------------- orchagent/macsecorch.h | 8 -- 2 files changed, 46 insertions(+), 125 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index d5d79416d2..72a321c21f 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -1,5 +1,4 @@ #include "macsecorch.h" -#include "gearboxutils.h" #include #include @@ -82,21 +81,6 @@ struct MockSAIAPI // static MockSAIAPI *sai_port_api = &mock_api; // static MockSAIAPI *sai_switch_api = &mock_api; -extern sai_object_id_t gSwitchId; - -#define MOCK_GEARBOX_SWITCH_ID_AND_RETURN_TRUE \ -do \ -{ \ - switch_id = gSwitchId; \ - return true; \ -}while(0); - -#define MOCK_GEARBOX_LINE_PORT_ID(port) \ -do \ -{ \ - port->m_line_port_id = port->m_port_id; \ -}while(0); - // #undef SWSS_LOG_ENTER // #define SWSS_LOG_ENTER() swss::Logger::ScopeLogger logger ## __LINE__ (__LINE__, __PRETTY_FUNCTION__) @@ -108,6 +92,7 @@ do \ #define EAPOL_ETHER_TYPE 0x888e #define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000 +extern sai_object_id_t gSwitchId; extern sai_macsec_api_t *sai_macsec_api; extern sai_acl_api_t *sai_acl_api; extern sai_port_api_t *sai_port_api; @@ -409,48 +394,31 @@ class MACsecOrchContext m_an.reset(new macsec_an_t(an)); } - Port *get_port() + sai_object_id_t *get_port_id() { - if (m_port == nullptr) + if(m_port_id == nullptr) { - if (m_orch == nullptr) - { - SWSS_LOG_ERROR("MACsec orch wasn't provided"); - return nullptr; - } - if (m_port_name == nullptr || m_port_name->empty()) - { - SWSS_LOG_ERROR("Port name wasn't provided."); - return nullptr; - } - auto port = std::make_unique(); - if (!m_orch->m_port_orch->getPort(*m_port_name, *port)) + auto port = get_port(); + if (port == nullptr) { - SWSS_LOG_INFO("Cannot find the port %s.", m_port_name->c_str()); return nullptr; } - m_port = std::move(port); - MOCK_GEARBOX_LINE_PORT_ID(m_port); + m_port_id = std::make_unique(port->m_port_id); + // TODO: If the MACsec was enabled at the gearbox, should use line port id as the port id. } - return m_port.get(); + return m_port_id.get(); } sai_object_id_t *get_switch_id() { if (m_switch_id == nullptr) { - auto port = get_port(); - if (port == nullptr) - { - return nullptr; - } - auto switch_id = std::make_unique(); - if (!m_orch->getGearboxSwitchId(*port, *switch_id)) + if (gSwitchId == SAI_NULL_OBJECT_ID) { - SWSS_LOG_INFO("Cannot find MACsec switch at the port %s.", m_port_name->c_str()); + SWSS_LOG_ERROR("Switch ID cannot be found"); return nullptr; } - m_switch_id = std::move(switch_id); + m_switch_id = std::make_unique(gSwitchId); } return m_switch_id.get(); } @@ -583,6 +551,7 @@ class MACsecOrchContext m_an(nullptr), m_port(nullptr), m_macsec_obj(nullptr), + m_port_id(nullptr), m_switch_id(nullptr), m_macsec_port(nullptr), m_acl_table(nullptr), @@ -590,6 +559,32 @@ class MACsecOrchContext m_macsec_sa(nullptr) { } + + const Port *get_port() + { + if (m_port == nullptr) + { + if (m_orch == nullptr) + { + SWSS_LOG_ERROR("MACsec orch wasn't provided"); + return nullptr; + } + if (m_port_name == nullptr || m_port_name->empty()) + { + SWSS_LOG_ERROR("Port name wasn't provided."); + return nullptr; + } + auto port = std::make_unique(); + if (!m_orch->m_port_orch->getPort(*m_port_name, *port)) + { + SWSS_LOG_INFO("Cannot find the port %s.", m_port_name->c_str()); + return nullptr; + } + m_port = std::move(port); + } + return m_port.get(); + } + MACsecOrch *m_orch; std::shared_ptr m_port_name; sai_macsec_direction_t m_direction; @@ -598,6 +593,7 @@ class MACsecOrchContext std::unique_ptr m_port; MACsecOrch::MACsecObject *m_macsec_obj; + std::unique_ptr m_port_id; std::unique_ptr m_switch_id; MACsecOrch::MACsecPort *m_macsec_port; @@ -625,9 +621,7 @@ MACsecOrch::MACsecOrch( m_macsec_flex_counter_manager( COUNTERS_MACSEC_ATTR_TABLE, StatsMode::READ, - MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true), - m_gearbox_table(app_db, "_GEARBOX_TABLE"), - m_gearbox_enabled(false) + MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true) { SWSS_LOG_ENTER(); } @@ -646,15 +640,6 @@ void MACsecOrch::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); - if (!m_gearbox_enabled) - { - if (!initGearbox()) - { - SWSS_LOG_WARN("Gearbox cannot be initialized."); - return; - } - } - using TaskType = std::tuple; using TaskFunc = task_process_status (MACsecOrch::*)( const std::string &, @@ -743,7 +728,7 @@ task_process_status MACsecOrch::updateMACsecPort( MACsecOrchContext ctx(this, port_name); RecoverStack recover; - if (ctx.get_port() == nullptr || ctx.get_switch_id() == nullptr) + if (ctx.get_port_id() == nullptr || ctx.get_switch_id() == nullptr) { return task_need_retry; } @@ -767,7 +752,7 @@ task_process_status MACsecOrch::updateMACsecPort( port_name, port_attr, *ctx.get_macsec_obj(), - ctx.get_port()->m_line_port_id, + *ctx.get_port_id(), *ctx.get_switch_id())) { return task_failed; @@ -778,7 +763,7 @@ task_process_status MACsecOrch::updateMACsecPort( *macsec_port_itr->second, port_name, *ctx.get_macsec_obj(), - ctx.get_port()->m_line_port_id); + *ctx.get_port_id()); }); } if (!updateMACsecPort(*ctx.get_macsec_port(), port_attr)) @@ -803,7 +788,7 @@ task_process_status MACsecOrch::disableMACsecPort( SWSS_LOG_WARN("Cannot find MACsec switch at the port %s.", port_name.c_str()); return task_failed; } - if (ctx.get_port() == nullptr) + if (ctx.get_port_id() == nullptr) { SWSS_LOG_WARN("Cannot find the port %s.", port_name.c_str()); return task_failed; @@ -820,7 +805,7 @@ task_process_status MACsecOrch::disableMACsecPort( *ctx.get_macsec_port(), port_name, *ctx.get_macsec_obj(), - ctx.get_port()->m_line_port_id)) + *ctx.get_port_id())) { result = task_failed; } @@ -955,62 +940,6 @@ task_process_status MACsecOrch::deleteIngressSA( return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_INGRESS); } -bool MACsecOrch::initGearbox() -{ - SWSS_LOG_ENTER(); - - GearboxUtils gearbox; - m_gearbox_enabled = gearbox.isGearboxEnabled(&m_gearbox_table); - if (m_gearbox_enabled) - { - m_gearbox_phy_map = gearbox.loadPhyMap(&m_gearbox_table); - m_gearbox_interface_map = gearbox.loadInterfaceMap(&m_gearbox_table); - - SWSS_LOG_NOTICE("BOX: m_gearbox_phy_map size = %d.", static_cast(m_gearbox_phy_map.size())); - SWSS_LOG_NOTICE("BOX: m_gearbox_interface_map size = %d.", static_cast(m_gearbox_interface_map.size())); - } - return m_gearbox_enabled; -} - -bool MACsecOrch::getGearboxSwitchId(const std::string &port_name, sai_object_id_t &switch_id) const -{ - SWSS_LOG_ENTER(); - - Port port; - if (!m_port_orch->getPort(port_name, port)) - { - SWSS_LOG_WARN("Port %s cannot be found.", port_name.c_str()); - return false; - } - return getGearboxSwitchId(port, switch_id); -} - -bool MACsecOrch::getGearboxSwitchId(const Port &port, sai_object_id_t &switch_id) const -{ - MOCK_GEARBOX_SWITCH_ID_AND_RETURN_TRUE; - SWSS_LOG_ENTER(); - - auto phy_id = m_gearbox_interface_map.find(port.m_index); - if (phy_id == m_gearbox_interface_map.end()) - { - SWSS_LOG_INFO("The port %s doesn't bind to any gearbox.", port.m_alias.c_str()); - return false; - } - auto phy_oid_str = m_gearbox_phy_map.find(phy_id->second.phy_id); - if (phy_oid_str == m_gearbox_phy_map.end()) - { - SWSS_LOG_ERROR("Cannot find phy object (%d).", phy_id->second.phy_id); - return false; - } - if (phy_oid_str->second.phy_oid.size() == 0) - { - SWSS_LOG_ERROR("BOX: Gearbox PHY phy_id:%d has an invalid phy_oid", phy_id->second.phy_id); - return false; - } - sai_deserialize_object_id(phy_oid_str->second.phy_oid, switch_id); - return true; -} - bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id) { SWSS_LOG_ENTER(); @@ -1444,7 +1373,7 @@ task_process_status MACsecOrch::updateMACsecSC( if (ctx.get_switch_id() == nullptr || ctx.get_macsec_obj() == nullptr) { - SWSS_LOG_ERROR("Cannot find gearbox at the port %s.", port_name.c_str()); + SWSS_LOG_ERROR("Cannot find switch id at the port %s.", port_name.c_str()); return task_failed; } diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index 9108fd0f50..2d71eb48b0 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -84,10 +84,6 @@ class MACsecOrch : public Orch Table m_macsec_counters_map; FlexCounterManager m_macsec_flex_counter_manager; - Table m_gearbox_table; - bool m_gearbox_enabled; - map m_gearbox_phy_map; - map m_gearbox_interface_map; struct ACLTable { sai_object_id_t m_table_id; @@ -128,10 +124,6 @@ class MACsecOrch : public Orch map m_macsec_objs; map > m_macsec_ports; - bool initGearbox(); - bool getGearboxSwitchId(const Port &port, sai_object_id_t &switch_id) const; - bool getGearboxSwitchId(const std::string &port_name, sai_object_id_t &switch_id) const; - /* MACsec Object */ bool initMACsecObject(sai_object_id_t switch_id); bool deinitMACsecObject(sai_object_id_t switch_id); From a065524bed5326c1a102bff49fd291508d362c81 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Mon, 19 Oct 2020 14:15:20 +0800 Subject: [PATCH 14/31] polish macro Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 72a321c21f..6e9099040d 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -88,9 +88,9 @@ struct MockSAIAPI /* Global Variables*/ -#define AVAILABLE_ACL_PRIORITIES_LIMITATION 32 -#define EAPOL_ETHER_TYPE 0x888e -#define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000 +#define AVAILABLE_ACL_PRIORITIES_LIMITATION (32) +#define EAPOL_ETHER_TYPE (0x888e) +#define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS (1000) extern sai_object_id_t gSwitchId; extern sai_macsec_api_t *sai_macsec_api; From 3ec481579d5dd0f9b505fc8890fd196b60bdc9b7 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Tue, 20 Oct 2020 15:45:10 +0800 Subject: [PATCH 15/31] Add auth key support Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 6e9099040d..4ea8d41c19 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -266,21 +266,27 @@ static std::istringstream &operator>>( SWSS_LOG_ENTER(); const std::string &buffer = istream.str(); bool convert_done = false; - if (buffer.length() == sizeof(sak.m_sak)) + memset(&sak, 0, sizeof(sak)); + // One hex indicates 4 bits + size_t bit_count = buffer.length() * 4; + // 128 bits SAK + if (bit_count == 128) { + // 128-bit SAK uses only Bytes 16..31. sak.m_sak_256_enable = false; convert_done = hex_to_binary( buffer, - sak.m_sak, - sizeof(sak.m_sak) / 2); + &sak.m_sak[16], + 16); } - else if (buffer.length() == sizeof(sak.m_sak) * 2) + // 256 bits SAK + else if (bit_count == 256) { sak.m_sak_256_enable = true; convert_done = hex_to_binary( buffer, sak.m_sak, - sizeof(sak.m_sak)); + 32); } if (!convert_done) { @@ -300,7 +306,7 @@ static std::istringstream &operator>>( { SWSS_LOG_ENTER(); const std::string &buffer = istream.str(); - + memset(&salt, 0, sizeof(salt)); if ( (buffer.length() != sizeof(salt.m_salt) * 2) || (!hex_to_binary(buffer, salt.m_salt, sizeof(salt.m_salt)))) { @@ -320,15 +326,15 @@ static std::istringstream &operator>>( { SWSS_LOG_ENTER(); const std::string &buffer = istream.str(); - // TODO : Implement auth_key - // if ( - // (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!hex_to_binary( - // buffer, - // auth_key.m_auth_key, - // sizeof(auth_key.m_auth_key)))) - // { - // throw std::invalid_argument("Invalid Auth Key : " + buffer); - // } + memset(&auth_key, 0, sizeof(auth_key)); + if ( + (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!hex_to_binary( + buffer, + auth_key.m_auth_key, + sizeof(auth_key.m_auth_key)))) + { + throw std::invalid_argument("Invalid Auth Key : " + buffer); + } return istream; } @@ -2279,7 +2285,6 @@ bool MACsecOrch::setACLEntryMACsecFlowActive(sai_object_id_t entry_id, sai_objec { sai_attribute_t attr; - SWSS_LOG_NOTICE("GANZE entry %lu flow %lu active %s", entry_id, flow_id, active ? "TRUE" : "FALSE"); attr.id = SAI_ACL_ENTRY_ATTR_ACTION_MACSEC_FLOW; attr.value.aclaction.parameter.oid = flow_id; attr.value.aclaction.enable = active; From 89012eb8ce4ad4372474510c80005cfded66e0b8 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 22 Oct 2020 17:47:54 +0800 Subject: [PATCH 16/31] Add SEND_SCI to MACsec SC Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 39 ++++++++++++++++++++++++++------------- orchagent/macsecorch.h | 1 + 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 4ea8d41c19..9f6efe0d11 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -228,21 +228,32 @@ static bool hex_to_binary( std::uint8_t *buffer, size_t buffer_length) { + SWSS_LOG_ENTER(); size_t buffer_cur = 0; size_t hex_cur = 0; - while (buffer_cur < buffer_length) + if (hex_str.length() %2 != 0) + { + SWSS_LOG_ERROR("Invalid hex string %s", hex_str.c_str()); + return false; + } + if (hex_str.length() > (buffer_length * 2)) + { + SWSS_LOG_ERROR("Buffer length isn't sufficient."); + return false; + } + while (hex_cur < hex_str.length()) { - if ((hex_cur + 1) >= hex_str.length()) + if (!std::isxdigit(static_cast(hex_str[hex_cur]))) { + SWSS_LOG_ERROR("Invalid hex string %s at %lu(%c)", hex_str.c_str(), hex_cur, hex_str[hex_cur]); return false; } - std::stringstream stream; - if ( - !!!std::isxdigit(static_cast(hex_str[hex_cur])) - || !!!std::isxdigit(static_cast(hex_str[hex_cur + 1]))) + if (!std::isxdigit(static_cast(hex_str[hex_cur + 1]))) { + SWSS_LOG_ERROR("Invalid hex string %s at %lu(%c)", hex_str.c_str(), hex_cur + 1, hex_str[hex_cur + 1]); return false; } + std::stringstream stream; stream << std::hex; stream << hex_str[hex_cur++]; stream << hex_str[hex_cur++]; @@ -250,7 +261,7 @@ static bool hex_to_binary( stream >> value; buffer[buffer_cur++] = static_cast(value); } - return hex_cur == hex_str.length(); + return true; } struct MACsecSAK @@ -1500,6 +1511,7 @@ bool MACsecOrch::createMACsecSC( sc->m_flow_id, sci, ssci, + macsec_port.m_sci_in_sectag, sc->m_xpn64_enable)) { SWSS_LOG_WARN("Create MACsec SC %s fail.", port_sci.c_str()); @@ -1558,6 +1570,7 @@ bool MACsecOrch::createMACsecSC( sai_object_id_t flow_id, sai_uint64_t sci, sai_uint32_t ssci, + bool send_sci, bool xpn64_enable) { SWSS_LOG_ENTER(); @@ -1583,6 +1596,9 @@ bool MACsecOrch::createMACsecSC( attr.id = SAI_MACSEC_SC_ATTR_MACSEC_XPN64_ENABLE; attr.value.booldata = xpn64_enable; attrs.push_back(attr); + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_EXPLICIT_SCI_ENABLE; + attr.value.booldata = send_sci; + attrs.push_back(attr); if (sai_macsec_api->create_macsec_sc( &sc_id, @@ -1916,12 +1932,9 @@ bool MACsecOrch::createMACsecSA( attrs.push_back(attr); // Valid when SAI_MACSEC_SC_ATTR_MACSEC_XPN64_ENABLE == true. - // if (xpn64_enable) - // { - attr.id = SAI_MACSEC_SA_ATTR_SALT; - std::copy(salt, salt + sizeof(attr.value.macsecsalt), attr.value.macsecsalt); - attrs.push_back(attr); - // } + attr.id = SAI_MACSEC_SA_ATTR_SALT; + std::copy(salt, salt + sizeof(attr.value.macsecsalt), attr.value.macsecsalt); + attrs.push_back(attr); attr.id = SAI_MACSEC_SA_ATTR_AUTH_KEY; std::copy(auth_key, auth_key + sizeof(attr.value.macsecauthkey), attr.value.macsecauthkey); diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index 2d71eb48b0..660cee7585 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -180,6 +180,7 @@ class MACsecOrch : public Orch sai_object_id_t flow_id, sai_uint64_t sci, sai_uint32_t ssci, + bool send_sci, bool xpn64_enable); task_process_status deleteMACsecSC( const std::string &port_sci, From 9ab3e2177524678ce69d4ce6ff1d1eaa06cfa82f Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 29 Oct 2020 23:19:35 +0800 Subject: [PATCH 17/31] Remove debuging code Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 83 +++------------------------------------- orchagent/macsecorch.h | 21 +--------- 2 files changed, 6 insertions(+), 98 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 9f6efe0d11..ea46aeb56d 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -12,85 +12,12 @@ #include #include -/* Only for Debug */ - -#define MockSAIFunc(FUNC_NAME) \ - sai_status_t FUNC_NAME(...) \ - { \ - return SAI_STATUS_SUCCESS; \ - } - -struct MockSAIAPI -{ - sai_status_t get_switch_attribute( - sai_object_id_t switch_id, - uint32_t attr_count, - sai_attribute_t *attr_list) - { - if (attr_count != 1) - { - return SAI_STATUS_FAILURE; - } - if (attr_list[0].id == SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY) - { - attr_list[0].value.u32 = 5; - } - else if (attr_list[0].id == SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY) - { - attr_list[0].value.u32 = 0; - } - return SAI_STATUS_SUCCESS; - } - MockSAIFunc(set_port_attribute); - MockSAIFunc(create_macsec); - MockSAIFunc(remove_macsec); - MockSAIFunc(create_macsec_port); - MockSAIFunc(remove_macsec_port); - sai_status_t get_macsec_attribute( - sai_object_id_t switch_id, - uint32_t attr_count, - sai_attribute_t *attr_list) - { - if (attr_count != 1) - { - return SAI_STATUS_FAILURE; - } - if (attr_list[0].id == SAI_MACSEC_ATTR_SCI_IN_INGRESS_MACSEC_ACL) - { - attr_list[0].value.booldata = true; - } - return SAI_STATUS_SUCCESS; - } - MockSAIFunc(create_macsec_flow); - MockSAIFunc(remove_macsec_flow); - MockSAIFunc(create_macsec_sc); - MockSAIFunc(remove_macsec_sc); - MockSAIFunc(create_macsec_sa); - MockSAIFunc(remove_macsec_sa); - MockSAIFunc(create_acl_table); - MockSAIFunc(remove_acl_table); - MockSAIFunc(create_acl_entry); - MockSAIFunc(remove_acl_entry); - MockSAIFunc(set_acl_entry_attribute); -}; - -// static MockSAIAPI mock_api; - -// static MockSAIAPI *sai_macsec_api = &mock_api; -// static MockSAIAPI *sai_acl_api = &mock_api; -// static MockSAIAPI *sai_port_api = &mock_api; -// static MockSAIAPI *sai_switch_api = &mock_api; - -// #undef SWSS_LOG_ENTER -// #define SWSS_LOG_ENTER() swss::Logger::ScopeLogger logger ## __LINE__ (__LINE__, __PRETTY_FUNCTION__) - -/* Finish Debug */ - /* Global Variables*/ -#define AVAILABLE_ACL_PRIORITIES_LIMITATION (32) -#define EAPOL_ETHER_TYPE (0x888e) -#define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS (1000) +#define AVAILABLE_ACL_PRIORITIES_LIMITATION (32) +#define EAPOL_ETHER_TYPE (0x888e) +#define MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS (1000) +#define COUNTERS_MACSEC_ATTR_GROUP "COUNTERS_MACSEC_ATTR" extern sai_object_id_t gSwitchId; extern sai_macsec_api_t *sai_macsec_api; @@ -636,7 +563,7 @@ MACsecOrch::MACsecOrch( m_counter_db("COUNTERS_DB", 0), m_macsec_counters_map(&m_counter_db, COUNTERS_MACSEC_NAME_MAP), m_macsec_flex_counter_manager( - COUNTERS_MACSEC_ATTR_TABLE, + COUNTERS_MACSEC_ATTR_GROUP, StatsMode::READ, MACSEC_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true) { diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index 660cee7585..5e1a358d16 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -1,32 +1,13 @@ #ifndef SWSS_MACSECSORCH_H #define SWSS_MACSECSORCH_H -// The following definitions should be moved to schema.h - -#define APP_MACSEC_PORT_TABLE_NAME "MACSEC_PORT_TABLE" -#define APP_MACSEC_EGRESS_SC_TABLE_NAME "MACSEC_EGRESS_SC_TABLE" -#define APP_MACSEC_INGRESS_SC_TABLE_NAME "MACSEC_INGRESS_SC_TABLE" -#define APP_MACSEC_EGRESS_SA_TABLE_NAME "MACSEC_EGRESS_SA_TABLE" -#define APP_MACSEC_INGRESS_SA_TABLE_NAME "MACSEC_INGRESS_SA_TABLE" - -#define STATE_MACSEC_PORT_TABLE_NAME "MACSEC_PORT_TABLE" -#define STATE_MACSEC_EGRESS_SC_TABLE_NAME "MACSEC_EGRESS_SC_TABLE" -#define STATE_MACSEC_INGRESS_SC_TABLE_NAME "MACSEC_INGRESS_SC_TABLE" -#define STATE_MACSEC_EGRESS_SA_TABLE_NAME "MACSEC_EGRESS_SA_TABLE" -#define STATE_MACSEC_INGRESS_SA_TABLE_NAME "MACSEC_INGRESS_SA_TABLE" - -#define COUNTERS_MACSEC_NAME_MAP "COUNTERS_MACSEC_NAME_MAP" -#define COUNTERS_MACSEC_ATTR_TABLE "COUNTERS_MACSEC_ATTR" -#define MACSEC_SA_ATTR_ID_LIST "MACSEC_SA_ATTR_ID_LIST" - -// End define - #include "orch.h" #include "portsorch.h" #include "flex_counter_manager.h" #include +#include #include #include From bb608b7b1c7a4372c0022b7c2c121f6f2694449f Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Wed, 4 Nov 2020 00:54:52 +0800 Subject: [PATCH 18/31] Update to support the latest SWSS library Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index ea46aeb56d..4b4cf4e0ba 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -1925,8 +1925,7 @@ void MACsecOrch::uninstallCounter(const std::string &obj_name, sai_object_id_t o { m_macsec_flex_counter_manager.clearCounterIdList(obj_id); - RedisClient redisClient(&m_counter_db); - redisClient.hdel(COUNTERS_MACSEC_NAME_MAP, obj_name); + m_counter_db.hdel(COUNTERS_MACSEC_NAME_MAP, obj_name); } bool MACsecOrch::initACLTable( From a0397b423f411512f77b3144a0a51fc2dd456c9c Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 19 Nov 2020 19:39:12 +0800 Subject: [PATCH 19/31] Fixbug: Duplicate set ACL Entry Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 4b4cf4e0ba..c808afbed8 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -1092,6 +1092,8 @@ bool MACsecOrch::createMACsecPort( SAI_MACSEC_DIRECTION_INGRESS); }); + SWSS_LOG_NOTICE("MACsec port %s is created.", port_name.c_str()); + std::vector fvVector; fvVector.emplace_back("state", "ok"); m_state_macsec_port.set(port_name, fvVector); @@ -1137,9 +1139,11 @@ bool MACsecOrch::updateMACsecPort(MACsecPort &macsec_port, const TaskArgs &port_ get_value(port_attr, "enable_encrypt", macsec_port.m_enable_encrypt); get_value(port_attr, "send_sci", macsec_port.m_sci_in_sectag); - if (get_value(port_attr, "enable", macsec_port.m_enable)) + bool enable = false; + if (get_value(port_attr, "enable", enable) && enable != macsec_port.m_enable) { std::vector macsec_scs; + macsec_port.m_enable = enable; for (auto &sc : macsec_port.m_egress_scs) { macsec_scs.push_back(&sc.second); From 52d7e35e828b110b989d0bd31f650d1e6c7d5ba7 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 20 Nov 2020 16:38:49 +0800 Subject: [PATCH 20/31] Clean modification about MACsec gearbox Signed-off-by: Ze Gan --- orchagent/port.h | 2 -- orchagent/portsorch.cpp | 1 - 2 files changed, 3 deletions(-) diff --git a/orchagent/port.h b/orchagent/port.h index e0e945f131..74f805ddec 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -114,8 +114,6 @@ class Port std::unordered_set m_ingress_acl_tables_uset; std::unordered_set m_egress_acl_tables_uset; - - sai_object_id_t m_line_port_id = 0; }; } diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 482ff81139..e75f8ec584 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -4448,7 +4448,6 @@ bool PortsOrch::initGearboxPort(Port &port) port.m_alias.c_str(), port.m_port_id, port.m_index, status); return false; } - port.m_line_port_id = linePort; SWSS_LOG_NOTICE("BOX: Created Gearbox line-side port 0x%lx for alias:%s index:%d", linePort, port.m_alias.c_str(), port.m_index); From 897bdff1cc3d3c3e00f7924cf3a96d15ccd9f944 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 20 Nov 2020 17:00:47 +0800 Subject: [PATCH 21/31] Rename ACL to MACsec ACL Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 86 ++++++++++++++++++++-------------------- orchagent/macsecorch.h | 36 ++++++++--------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index c808afbed8..e4067eea7c 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -412,7 +412,7 @@ class MACsecOrchContext return m_macsec_port; } - MACsecOrch::ACLTable *get_acl_table() + MACsecOrch::MACsecACLTable *get_acl_table() { if (m_acl_table == nullptr) { @@ -541,7 +541,7 @@ class MACsecOrchContext std::unique_ptr m_switch_id; MACsecOrch::MACsecPort *m_macsec_port; - MACsecOrch::ACLTable *m_acl_table; + MACsecOrch::MACsecACLTable *m_acl_table; MACsecOrch::MACsecSC *m_macsec_sc; sai_object_id_t *m_macsec_sa; @@ -1058,7 +1058,7 @@ bool MACsecOrch::createMACsecPort( }); } - if (!initACLTable( + if (!initMACsecACLTable( macsec_port.m_egress_acl_table, line_port_id, switch_id, @@ -1069,13 +1069,13 @@ bool MACsecOrch::createMACsecPort( return false; } recover.add_action([this, &macsec_port, line_port_id]() { - this->deinitACLTable( + this->deinitMACsecACLTable( macsec_port.m_egress_acl_table, line_port_id, SAI_MACSEC_DIRECTION_EGRESS); }); - if (!initACLTable( + if (!initMACsecACLTable( macsec_port.m_ingress_acl_table, line_port_id, switch_id, @@ -1086,7 +1086,7 @@ bool MACsecOrch::createMACsecPort( return false; } recover.add_action([this, &macsec_port, line_port_id]() { - this->deinitACLTable( + this->deinitMACsecACLTable( macsec_port.m_ingress_acl_table, line_port_id, SAI_MACSEC_DIRECTION_INGRESS); @@ -1157,18 +1157,18 @@ bool MACsecOrch::updateMACsecPort(MACsecPort &macsec_port, const TaskArgs &port_ // Change the ACL entry action from packet action to MACsec flow if (macsec_port.m_enable) { - if (!setACLEntryMACsecFlowActive(macsec_sc->m_entry_id, macsec_sc->m_flow_id, true)) + if (!setMACsecFlowActive(macsec_sc->m_entry_id, macsec_sc->m_flow_id, true)) { SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); return false; } auto an = macsec_sc->m_encoding_an; auto flow_id = macsec_sc->m_flow_id; - recover.add_action([this, an, flow_id]() { this->setACLEntryMACsecFlowActive(an, flow_id, false); }); + recover.add_action([this, an, flow_id]() { this->setMACsecFlowActive(an, flow_id, false); }); } else { - setACLEntryMACsecFlowActive(macsec_sc->m_encoding_an, macsec_sc->m_flow_id, false); + setMACsecFlowActive(macsec_sc->m_encoding_an, macsec_sc->m_flow_id, false); } } } @@ -1219,13 +1219,13 @@ bool MACsecOrch::deleteMACsecPort( } } - if (!deinitACLTable(macsec_port.m_ingress_acl_table, line_port_id, SAI_MACSEC_DIRECTION_INGRESS)) + if (!deinitMACsecACLTable(macsec_port.m_ingress_acl_table, line_port_id, SAI_MACSEC_DIRECTION_INGRESS)) { SWSS_LOG_WARN("Cannot deinit ingress ACL table at the port %s.", port_name.c_str()); result &= false; } - if (!deinitACLTable(macsec_port.m_egress_acl_table, line_port_id, SAI_MACSEC_DIRECTION_EGRESS)) + if (!deinitMACsecACLTable(macsec_port.m_egress_acl_table, line_port_id, SAI_MACSEC_DIRECTION_EGRESS)) { SWSS_LOG_WARN("Cannot deinit egress ACL table at the port %s.", port_name.c_str()); result &= false; @@ -1461,7 +1461,7 @@ bool MACsecOrch::createMACsecSC( } sc->m_acl_priority = *(table->m_available_acl_priorities.begin()); table->m_available_acl_priorities.erase(table->m_available_acl_priorities.begin()); - if (!createACLDataEntry( + if (!createMACsecACLDataEntry( sc->m_entry_id, table->m_table_id, switch_id, @@ -1473,7 +1473,7 @@ bool MACsecOrch::createMACsecSC( return false; } recover.add_action([this, sc, table]() { - deleteACLEntry(sc->m_entry_id); + deleteMACsecACLEntry(sc->m_entry_id); table->m_available_acl_priorities.insert(sc->m_acl_priority); }); @@ -1573,7 +1573,7 @@ task_process_status MACsecOrch::deleteMACsecSC( deleteMACsecSA(port_sci_an, direction); } - deleteACLEntry(ctx.get_macsec_sc()->m_entry_id); + deleteMACsecACLEntry(ctx.get_macsec_sc()->m_entry_id); ctx.get_acl_table()->m_available_acl_priorities.insert(ctx.get_macsec_sc()->m_acl_priority); if (!deleteMACsecSC(ctx.get_macsec_sc()->m_sc_id)) @@ -1707,13 +1707,13 @@ task_process_status MACsecOrch::createMACsecSA( // change the ACL entry action from packet action to MACsec flow if (ctx.get_macsec_port()->m_enable && sc->m_sa_ids.empty()) { - if (!setACLEntryMACsecFlowActive(sc->m_entry_id, sc->m_flow_id, true)) + if (!setMACsecFlowActive(sc->m_entry_id, sc->m_flow_id, true)) { SWSS_LOG_WARN("Cannot change the ACL entry action from packet action to MACsec flow"); return task_failed; } recover.add_action([this, sc]() { - this->setACLEntryMACsecFlowActive( + this->setMACsecFlowActive( sc->m_encoding_an, sc->m_flow_id, false); @@ -1798,7 +1798,7 @@ task_process_status MACsecOrch::deleteMACsecSA( // change the ACL entry action from MACsec flow to packet action if (ctx.get_macsec_sc()->m_sa_ids.empty()) { - if (!setACLEntryMACsecFlowActive(ctx.get_macsec_sc()->m_entry_id, ctx.get_macsec_sc()->m_flow_id, false)) + if (!setMACsecFlowActive(ctx.get_macsec_sc()->m_entry_id, ctx.get_macsec_sc()->m_flow_id, false)) { SWSS_LOG_WARN("Cannot change the ACL entry action from MACsec flow to packet action"); result = task_failed; @@ -1932,8 +1932,8 @@ void MACsecOrch::uninstallCounter(const std::string &obj_name, sai_object_id_t o m_counter_db.hdel(COUNTERS_MACSEC_NAME_MAP, obj_name); } -bool MACsecOrch::initACLTable( - ACLTable &acl_table, +bool MACsecOrch::initMACsecACLTable( + MACsecACLTable &acl_table, sai_object_id_t port_id, sai_object_id_t switch_id, sai_macsec_direction_t direction, @@ -1943,17 +1943,17 @@ bool MACsecOrch::initACLTable( RecoverStack recover; - if (!createACLTable(acl_table.m_table_id, switch_id, direction, sci_in_sectag)) + if (!createMACsecACLTable(acl_table.m_table_id, switch_id, direction, sci_in_sectag)) { SWSS_LOG_WARN("Cannot create ACL table"); return false; } recover.add_action([this, &acl_table]() { - this->deleteACLTable(acl_table.m_table_id); + this->deleteMACsecACLTable(acl_table.m_table_id); acl_table.m_table_id = SAI_NULL_OBJECT_ID; }); - if (!createACLEAPOLEntry( + if (!createMACsecACLEAPOLEntry( acl_table.m_eapol_packet_forward_entry_id, acl_table.m_table_id, switch_id)) @@ -1962,24 +1962,24 @@ bool MACsecOrch::initACLTable( return false; } recover.add_action([this, &acl_table]() { - this->deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id); + this->deleteMACsecACLEntry(acl_table.m_eapol_packet_forward_entry_id); acl_table.m_eapol_packet_forward_entry_id = SAI_NULL_OBJECT_ID; }); - if (!bindACLTabletoPort(acl_table.m_table_id, port_id, direction)) + if (!bindMACsecACLTabletoPort(acl_table.m_table_id, port_id, direction)) { SWSS_LOG_WARN("Cannot bind ACL table"); return false; } - recover.add_action([this, port_id, direction]() { this->unbindACLTable(port_id, direction); }); + recover.add_action([this, port_id, direction]() { this->unbindMACsecACLTable(port_id, direction); }); sai_uint32_t minimum_priority = 0; - if (!get_acl_minimum_priority(switch_id, minimum_priority)) + if (!getAclMinimumPriority(switch_id, minimum_priority)) { return false; } sai_uint32_t maximum_priority = 0; - if (!get_acl_maximum_priority(switch_id, maximum_priority)) + if (!getAclMaximumPriority(switch_id, maximum_priority)) { return false; } @@ -1999,24 +1999,24 @@ bool MACsecOrch::initACLTable( return true; } -bool MACsecOrch::deinitACLTable( - const ACLTable &acl_table, +bool MACsecOrch::deinitMACsecACLTable( + const MACsecACLTable &acl_table, sai_object_id_t port_id, sai_macsec_direction_t direction) { bool result = true; - if (!unbindACLTable(port_id, direction)) + if (!unbindMACsecACLTable(port_id, direction)) { SWSS_LOG_WARN("Cannot unbind ACL table"); result &= false; } - if (!deleteACLEntry(acl_table.m_eapol_packet_forward_entry_id)) + if (!deleteMACsecACLEntry(acl_table.m_eapol_packet_forward_entry_id)) { SWSS_LOG_WARN("Cannot delete ACL entry"); result &= false; } - if (!deleteACLTable(acl_table.m_table_id)) + if (!deleteMACsecACLTable(acl_table.m_table_id)) { SWSS_LOG_WARN("Cannot delete ACL table"); result &= false; @@ -2025,7 +2025,7 @@ bool MACsecOrch::deinitACLTable( return result; } -bool MACsecOrch::createACLTable( +bool MACsecOrch::createMACsecACLTable( sai_object_id_t &table_id, sai_object_id_t switch_id, sai_macsec_direction_t direction, @@ -2075,7 +2075,7 @@ bool MACsecOrch::createACLTable( return true; } -bool MACsecOrch::deleteACLTable(sai_object_id_t table_id) +bool MACsecOrch::deleteMACsecACLTable(sai_object_id_t table_id) { if (sai_acl_api->remove_acl_table(table_id) != SAI_STATUS_SUCCESS) { @@ -2084,7 +2084,7 @@ bool MACsecOrch::deleteACLTable(sai_object_id_t table_id) return true; } -bool MACsecOrch::bindACLTabletoPort( +bool MACsecOrch::bindMACsecACLTabletoPort( sai_object_id_t table_id, sai_object_id_t port_id, sai_macsec_direction_t direction) @@ -2110,7 +2110,7 @@ bool MACsecOrch::bindACLTabletoPort( return true; } -bool MACsecOrch::unbindACLTable( +bool MACsecOrch::unbindMACsecACLTable( sai_object_id_t port_id, sai_macsec_direction_t direction) { @@ -2135,7 +2135,7 @@ bool MACsecOrch::unbindACLTable( return true; } -bool MACsecOrch::createACLEAPOLEntry( +bool MACsecOrch::createMACsecACLEAPOLEntry( sai_object_id_t &entry_id, sai_object_id_t table_id, sai_object_id_t switch_id) @@ -2150,7 +2150,7 @@ bool MACsecOrch::createACLEAPOLEntry( attr.value.oid = table_id; attrs.push_back(attr); attr.id = SAI_ACL_ENTRY_ATTR_PRIORITY; - if (!get_acl_maximum_priority(switch_id, attr.value.u32)) + if (!getAclMaximumPriority(switch_id, attr.value.u32)) { return false; } @@ -2183,7 +2183,7 @@ bool MACsecOrch::createACLEAPOLEntry( return true; } -bool MACsecOrch::createACLDataEntry( +bool MACsecOrch::createMACsecACLDataEntry( sai_object_id_t &entry_id, sai_object_id_t table_id, sai_object_id_t switch_id, @@ -2224,7 +2224,7 @@ bool MACsecOrch::createACLDataEntry( return true; } -bool MACsecOrch::setACLEntryMACsecFlowActive(sai_object_id_t entry_id, sai_object_id_t flow_id, bool active) +bool MACsecOrch::setMACsecFlowActive(sai_object_id_t entry_id, sai_object_id_t flow_id, bool active) { sai_attribute_t attr; @@ -2252,7 +2252,7 @@ bool MACsecOrch::setACLEntryMACsecFlowActive(sai_object_id_t entry_id, sai_objec return true; } -bool MACsecOrch::deleteACLEntry(sai_object_id_t entry_id) +bool MACsecOrch::deleteMACsecACLEntry(sai_object_id_t entry_id) { if (sai_acl_api->remove_acl_entry( entry_id) != SAI_STATUS_SUCCESS) @@ -2262,7 +2262,7 @@ bool MACsecOrch::deleteACLEntry(sai_object_id_t entry_id) return true; } -bool MACsecOrch::get_acl_maximum_priority(sai_object_id_t switch_id, sai_uint32_t &priority) const +bool MACsecOrch::getAclMaximumPriority(sai_object_id_t switch_id, sai_uint32_t &priority) const { sai_attribute_t attr; std::vector attrs; @@ -2282,7 +2282,7 @@ bool MACsecOrch::get_acl_maximum_priority(sai_object_id_t switch_id, sai_uint32_ return true; } -bool MACsecOrch::get_acl_minimum_priority(sai_object_id_t switch_id, sai_uint32_t &priority) const +bool MACsecOrch::getAclMinimumPriority(sai_object_id_t switch_id, sai_uint32_t &priority) const { sai_attribute_t attr; std::vector attrs; diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index 5e1a358d16..d72545414e 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -65,7 +65,7 @@ class MACsecOrch : public Orch Table m_macsec_counters_map; FlexCounterManager m_macsec_flex_counter_manager; - struct ACLTable + struct MACsecACLTable { sai_object_id_t m_table_id; sai_object_id_t m_eapol_packet_forward_entry_id; @@ -89,8 +89,8 @@ class MACsecOrch : public Orch sai_object_id_t m_ingress_flow_id; std::map m_egress_scs; std::map m_ingress_scs; - ACLTable m_egress_acl_table; - ACLTable m_ingress_acl_table; + MACsecACLTable m_egress_acl_table; + MACsecACLTable m_ingress_acl_table; bool m_enable_encrypt; bool m_sci_in_sectag; bool m_enable; @@ -199,45 +199,45 @@ class MACsecOrch : public Orch const std::vector &stats); void uninstallCounter(const std::string &obj_name, sai_object_id_t obj_id); - /* ACL */ - bool initACLTable( - ACLTable &acl_table, + /* MACsec ACL */ + bool initMACsecACLTable( + MACsecACLTable &acl_table, sai_object_id_t port_id, sai_object_id_t switch_id, sai_macsec_direction_t direction, bool sci_in_sectag); - bool deinitACLTable( - const ACLTable &acl_table, + bool deinitMACsecACLTable( + const MACsecACLTable &acl_table, sai_object_id_t port_id, sai_macsec_direction_t direction); - bool createACLTable( + bool createMACsecACLTable( sai_object_id_t &table_id, sai_object_id_t switch_id, sai_macsec_direction_t direction, bool sci_in_sectag); - bool deleteACLTable(sai_object_id_t table_id); - bool bindACLTabletoPort(sai_object_id_t table_id, sai_object_id_t port_id, sai_macsec_direction_t direction); - bool unbindACLTable(sai_object_id_t port_id, sai_macsec_direction_t direction); - bool createACLEAPOLEntry( + bool deleteMACsecACLTable(sai_object_id_t table_id); + bool bindMACsecACLTabletoPort(sai_object_id_t table_id, sai_object_id_t port_id, sai_macsec_direction_t direction); + bool unbindMACsecACLTable(sai_object_id_t port_id, sai_macsec_direction_t direction); + bool createMACsecACLEAPOLEntry( sai_object_id_t &entry_id, sai_object_id_t table_id, sai_object_id_t switch_id); - bool createACLDataEntry( + bool createMACsecACLDataEntry( sai_object_id_t &entry_id, sai_object_id_t table_id, sai_object_id_t switch_id, bool sci_in_sectag, sai_uint64_t sci, sai_uint32_t priority); - bool setACLEntryMACsecFlowActive( + bool setMACsecFlowActive( sai_object_id_t entry_id, sai_object_id_t flow_id, bool active); - bool deleteACLEntry(sai_object_id_t entry_id); - bool get_acl_maximum_priority( + bool deleteMACsecACLEntry(sai_object_id_t entry_id); + bool getAclMaximumPriority( sai_object_id_t switch_id, sai_uint32_t &priority) const; - bool get_acl_minimum_priority( + bool getAclMinimumPriority( sai_object_id_t switch_id, sai_uint32_t &priority) const; }; From d7409ac5eafc8808741a0691aa196f060ef665a0 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 20 Nov 2020 17:26:21 +0800 Subject: [PATCH 22/31] Polish function getAclPriority --- orchagent/macsecorch.cpp | 32 ++++++-------------------------- orchagent/macsecorch.h | 6 ++---- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index e4067eea7c..d9607a87a5 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -1974,12 +1974,12 @@ bool MACsecOrch::initMACsecACLTable( recover.add_action([this, port_id, direction]() { this->unbindMACsecACLTable(port_id, direction); }); sai_uint32_t minimum_priority = 0; - if (!getAclMinimumPriority(switch_id, minimum_priority)) + if (!getAclPriority(switch_id, SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY, minimum_priority)) { return false; } sai_uint32_t maximum_priority = 0; - if (!getAclMaximumPriority(switch_id, maximum_priority)) + if (!getAclPriority(switch_id, SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY, maximum_priority)) { return false; } @@ -2150,7 +2150,7 @@ bool MACsecOrch::createMACsecACLEAPOLEntry( attr.value.oid = table_id; attrs.push_back(attr); attr.id = SAI_ACL_ENTRY_ATTR_PRIORITY; - if (!getAclMaximumPriority(switch_id, attr.value.u32)) + if (!getAclPriority(switch_id, SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY, attr.value.u32)) { return false; } @@ -2262,39 +2262,19 @@ bool MACsecOrch::deleteMACsecACLEntry(sai_object_id_t entry_id) return true; } -bool MACsecOrch::getAclMaximumPriority(sai_object_id_t switch_id, sai_uint32_t &priority) const +bool MACsecOrch::getAclPriority(sai_object_id_t switch_id, sai_attr_id_t priority_id, sai_uint32_t &priority) const { sai_attribute_t attr; std::vector attrs; - attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY; + attr.id = priority_id; attrs.push_back(attr); if (sai_switch_api->get_switch_attribute( switch_id, static_cast(attrs.size()), attrs.data()) != SAI_STATUS_SUCCESS) { - SWSS_LOG_ERROR("Cannot fetch ACL maximum Priority from switch"); - return false; - } - priority = attrs.front().value.u32; - - return true; -} - -bool MACsecOrch::getAclMinimumPriority(sai_object_id_t switch_id, sai_uint32_t &priority) const -{ - sai_attribute_t attr; - std::vector attrs; - - attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY; - attrs.push_back(attr); - if (sai_switch_api->get_switch_attribute( - switch_id, - static_cast(attrs.size()), - attrs.data()) != SAI_STATUS_SUCCESS) - { - SWSS_LOG_ERROR("Cannot fetch ACL maximum Priority from switch"); + SWSS_LOG_ERROR("Cannot fetch ACL Priority from switch"); return false; } priority = attrs.front().value.u32; diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index d72545414e..af8cde1e5d 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -234,11 +234,9 @@ class MACsecOrch : public Orch sai_object_id_t flow_id, bool active); bool deleteMACsecACLEntry(sai_object_id_t entry_id); - bool getAclMaximumPriority( - sai_object_id_t switch_id, - sai_uint32_t &priority) const; - bool getAclMinimumPriority( + bool getAclPriority( sai_object_id_t switch_id, + sai_attr_id_t priority_id, sai_uint32_t &priority) const; }; From f5c9cbf6772edc98f343fc07f3b462e97cf9fc20 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 26 Nov 2020 01:00:23 +0800 Subject: [PATCH 23/31] [tests]: test_macsec_term_orch (#3) Signed-off-by: Ze Gan --- tests/test_macsec.py | 693 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 693 insertions(+) create mode 100644 tests/test_macsec.py diff --git a/tests/test_macsec.py b/tests/test_macsec.py new file mode 100644 index 0000000000..0fcc317f86 --- /dev/null +++ b/tests/test_macsec.py @@ -0,0 +1,693 @@ +from swsscommon import swsscommon +import conftest + +import sys +import pytest +import functools +import typing +import re + + +class Table(object): + def __init__(self, database: conftest.DVSDatabase, table_name: str): + self.db = database + self.table_name = table_name + + def convert_key(self, key: str): + return key + + def __setitem__(self, key: str, pairs: dict): + pairs_str = {} + for k, v in pairs.items(): + pairs_str[str(k)] = str(v) + key = self.convert_key(key) + if self.__getitem__(key) is None: + self.db.create_entry(self.table_name, key, pairs_str) + else: + self.db.update_entry(self.table_name, key, pairs_str) + + def __getitem__(self, key: str): + key = self.convert_key(key) + return self.db.get_entry(self.table_name, key) + + def __delitem__(self, key: str): + key = self.convert_key(key) + self.db.delete_entry(self.table_name, key) + + def wait(self, key: str): + key = self.convert_key(key) + # return True + return self.db.wait_for_entry(self.table_name, key) + + def wait_delete(self, key: str): + key = self.convert_key(key) + # return True + return self.db.wait_for_deleted_entry(self.table_name, key) + + +class ProduceStateTable(object): + def __init__(self, database: conftest.DVSDatabase, table_name: str): + self.table = swsscommon.ProducerStateTable( + database.db_connection, + table_name) + + def __setitem__(self, key: str, pairs: typing.Union[dict, list, tuple]): + pairs_str = [] + if isinstance(pairs, dict): + pairs = pairs.items() + for k, v in pairs: + pairs_str.append((str(k), str(v))) + self.table.set(key, pairs_str) + + def __delitem__(self, key: str): + self.table.delete(key) + + +class AppDBTable(ProduceStateTable): + SEPARATOR = ":" + + def __init__(self, dvs: conftest.DockerVirtualSwitch, table_name: str): + super(AppDBTable, self).__init__(dvs.get_app_db(), table_name) + + +class StateDBTable(Table): + SEPARATOR = "|" + + def __init__(self, dvs: conftest.DockerVirtualSwitch, table_name: str): + super(StateDBTable, self).__init__(dvs.get_state_db(), table_name) + + def convert_key(self, key: str): + return key.translate( + str.maketrans( + AppDBTable.SEPARATOR, + StateDBTable.SEPARATOR)) + + +def gen_sci(macsec_system_identifier: str, macsec_port_identifier: int) -> str: + macsec_system_identifier = macsec_system_identifier.translate( + str.maketrans("", "", ":.-")) + sci = "{}{}".format( + macsec_system_identifier, + str(macsec_port_identifier).zfill(4)) + sci = int(sci, 16) + if sys.byteorder == "little": + sci = int.from_bytes(sci.to_bytes(8, 'big'), 'little', signed=False) + return str(sci) + + +def gen_sc_key( + seperator: str, + port_name: str, + macsec_system_identifier: str, + macsec_port_identifier: int) -> str: + sci = gen_sci(macsec_system_identifier, macsec_port_identifier) + key = "{}{}{}".format( + port_name, + seperator, + sci) + return key + + +def gen_sa_key( + seperator: str, + port_name: str, + macsec_system_identifier: str, + macsec_port_identifier: int, + an: int): + sc_key = gen_sc_key( + seperator, + port_name, + macsec_system_identifier, + macsec_port_identifier) + key = "{}{}{}".format(sc_key, seperator, an) + return key + + +def macsec_sc(seperator: str = AppDBTable.SEPARATOR): + def inner(func: typing.Callable) -> typing.Callable: + @functools.wraps(func) + def wrap_func( + self, + port_name: str, + macsec_system_identifier: str, + macsec_port_identifier: int, + *args, + **kwargs) -> typing.Any: + key = gen_sc_key( + seperator, + port_name, + macsec_system_identifier, + macsec_port_identifier) + return func(self, key, *args, **kwargs) + return wrap_func + return inner + + +def macsec_sa(seperator: str = AppDBTable.SEPARATOR): + def inner(func: typing.Callable) -> typing.Callable: + @functools.wraps(func) + def wrap_func( + self, + port_name: str, + macsec_system_identifier: str, + macsec_port_identifier: int, + an: int, + *args, + **kwargs) -> typing.Any: + key = gen_sa_key( + seperator, + port_name, + macsec_system_identifier, + macsec_port_identifier, + an) + return func(self, key, *args, **kwargs) + return wrap_func + return inner + + +class WPASupplicantMock(object): + def __init__(self, dvs: conftest.DockerVirtualSwitch): + self.dvs = dvs + self.app_port_table = AppDBTable( + self.dvs, swsscommon.APP_MACSEC_PORT_TABLE_NAME) + self.app_receive_sc_table = AppDBTable( + self.dvs, swsscommon.APP_MACSEC_INGRESS_SC_TABLE_NAME) + self.app_transmit_sc_table = AppDBTable( + self.dvs, swsscommon.APP_MACSEC_EGRESS_SC_TABLE_NAME) + self.app_receive_sa_table = AppDBTable( + self.dvs, swsscommon.APP_MACSEC_INGRESS_SA_TABLE_NAME) + self.app_transmit_sa_table = AppDBTable( + self.dvs, swsscommon.APP_MACSEC_EGRESS_SA_TABLE_NAME) + self.state_port_table = StateDBTable( + self.dvs, swsscommon.STATE_MACSEC_PORT_TABLE_NAME) + self.state_receive_sc_table = StateDBTable( + self.dvs, swsscommon.STATE_MACSEC_INGRESS_SC_TABLE_NAME) + self.state_transmit_sc_table = StateDBTable( + self.dvs, swsscommon.STATE_MACSEC_EGRESS_SC_TABLE_NAME) + self.state_receive_sa_table = StateDBTable( + self.dvs, swsscommon.STATE_MACSEC_INGRESS_SA_TABLE_NAME) + self.state_transmit_sa_table = StateDBTable( + self.dvs, swsscommon.STATE_MACSEC_EGRESS_SA_TABLE_NAME) + + def init_macsec_port(self, port_name: str): + self.app_port_table[port_name] = { + "enable": False, + "cipher_suite": "GCM-AES-128", + } + self.state_port_table.wait(port_name) + + def deinit_macsec_port(self, port_name: str): + del self.app_port_table[port_name] + self.state_port_table.wait_delete(port_name) + + def config_macsec_port( + self, + port_name: str, + config: typing.Dict[str, typing.Any]): + self.app_port_table[port_name] = config + + def set_macsec_control(self, port_name: str, enable: bool): + self.app_port_table[port_name] = {"enable": True} + + @macsec_sc() + def create_receive_sc(self, sci: str, ssci: int): + self.app_receive_sc_table[sci] = {"ssci": ssci} + self.state_receive_sc_table.wait(sci) + + @macsec_sc() + def delete_receive_sc(self, sci: str): + del self.app_receive_sc_table[sci] + self.state_receive_sc_table.wait_delete(sci) + + @macsec_sc() + def create_transmit_sc(self, sci: str, ssci: int): + self.app_transmit_sc_table[sci] = {"sci": sci, "encoding_an": 0} + self.state_transmit_sc_table.wait(sci) + + @macsec_sc() + def delete_transmit_sc(self, sci: str): + del self.app_transmit_sc_table[sci] + self.state_transmit_sc_table.wait_delete(sci) + + def check_valid_sa_parameter( + self, + sak: str, + auth_key: str, + lowest_acceptable_pn: int, + salt: str) -> bool: + # Check SAK is hex string + int(sak, 16) + assert( + len(sak) == 32 or len(sak) == 64, + "Wrong length {} sak {}".format( + len(sak), + sak)) + # Check auth_key is valid + int(auth_key, 16) + assert( + len(auth_key) == 32, + "Wrong length {} auth_key {}".format( + len(auth_key), + auth_key)) + # Check lowest acceptable packet number is valid + assert( + lowest_acceptable_pn > 0, + "Wrong packet number {}".format(lowest_acceptable_pn)) + return True + + @macsec_sa() + def create_receive_sa( + self, + sai: str, + sak: str, + auth_key: str, + lowest_acceptable_pn: int, + salt: str): + assert( + self.check_valid_sa_parameter( + sak, + auth_key, + lowest_acceptable_pn, + salt), + "Wrong parameter to MACsec receive SA") + self.app_receive_sa_table[sai] = { + "active": False, "sak": sak, "auth_key": auth_key, + "lowest_acceptable_pn": lowest_acceptable_pn, "salt": salt} + + @macsec_sa() + def delete_receive_sa(self, sai: str): + del self.app_receive_sa_table[sai] + self.state_receive_sa_table.wait_delete(sai) + + @macsec_sa() + def set_enable_receive_sa(self, sai: str, enable: bool): + self.app_receive_sa_table[sai] = {"active": enable} + if enable: + self.state_receive_sa_table.wait(sai) + + @macsec_sa() + def create_transmit_sa( + self, + sai: str, + sak: str, + auth_key: str, + init_pn: int, + salt: str): + assert( + self.check_valid_sa_parameter( + sak, + auth_key, + init_pn, + salt), + "Wrong parameter to MACsec receive SA") + self.app_transmit_sa_table[sai] = { + "sak": sak, "auth_key": auth_key, + "init_pn": init_pn, "salt": salt} + + @macsec_sa() + def delete_transmit_sa(self, sai: str): + del self.app_transmit_sa_table[sai] + self.state_transmit_sa_table.wait_delete(sai) + + @macsec_sc() + def set_enable_transmit_sa(self, sci: str, an: int, enable: bool): + if enable: + self.app_transmit_sc_table[sci] = {"encoding_an": an} + assert( + self.state_transmit_sa_table.wait( + "{}{}{}".format( + sci, + StateDBTable.SEPARATOR, + an))) + + +class MACsecInspector(object): + def __init__(self, dvs: conftest.DockerVirtualSwitch): + self.dvs = dvs + + def __load_macsec_info(self, port_name: str) -> (bool, str): + return self.dvs.runcmd("ip macsec show {}".format(port_name)) + + def get_macsec_port(self, port_name: str) -> str: + exitcode, info = self.__load_macsec_info(port_name) + if exitcode != 0 or not info: + return "" + print(info) + return info + + def get_macsec_sc( + self, + port_name: str, + macsec_system_identifier: str, + macsec_port_identifier: int) -> str: + info = self.get_macsec_port(port_name) + if not info: + return "" + macsec_system_identifier = macsec_system_identifier.translate( + str.maketrans("", "", ":.-")) + sci = "{}{}".format( + macsec_system_identifier, + str(macsec_port_identifier).zfill(4)) + sc_pattern = r"(TXSC|RXSC):\s*{}[ \w,]+\n?(?:\s*\d:[,\w ]+\n?)*".format( + sci) + info = re.search(sc_pattern, info, re.IGNORECASE) + if not info: + return "" + print(info.group(0)) + return info.group(0) + + def get_macsec_sa( + self, + port_name: str, + macsec_system_identifier: str, + macsec_port_identifier: str, + an: int) -> str: + info = self.get_macsec_sc( + port_name, + macsec_system_identifier, + macsec_port_identifier) + if not info: + return "" + sa_pattern = r"\s*{}:\s*PN\s*\d+[,\w ]+\n?".format(an) + info = re.search(sa_pattern, info, re.IGNORECASE) + if not info: + return "" + print(info.group(0)) + return info.group(0) + + +class TestMACsec(object): + def init_macsec( + self, + wpa: WPASupplicantMock, + port_name: str, + local_mac_address: str, + macsec_port_identifier: int, + ssci: int): + wpa.init_macsec_port(port_name) + wpa.config_macsec_port(port_name, {"enable_protect": True}) + wpa.config_macsec_port(port_name, {"enable_encrypt": True}) + wpa.config_macsec_port( + port_name, + { + "enable_replay_protect": True, + "replay_window": 0 + }) + wpa.set_macsec_control(port_name, False) + wpa.create_transmit_sc( + port_name, + local_mac_address, + macsec_port_identifier, + ssci) + + def establish_macsec( + self, + wpa: WPASupplicantMock, + port_name: str, + local_mac_address: str, + peer_mac_address: str, + macsec_port_identifier: int, + an: int, + sak: str, + packet_number: int, + auth_key: str, + ssci: int, + salt: str): + wpa.create_receive_sc( + port_name, + peer_mac_address, + macsec_port_identifier, + ssci) + wpa.create_receive_sa( + port_name, + peer_mac_address, + macsec_port_identifier, + an, + sak, + auth_key, + packet_number, + salt) + wpa.create_transmit_sa( + port_name, + local_mac_address, + macsec_port_identifier, + an, + sak, + auth_key, + packet_number, + salt) + wpa.set_enable_receive_sa( + port_name, + peer_mac_address, + macsec_port_identifier, + an, + True) + wpa.set_macsec_control(port_name, True) + wpa.set_enable_transmit_sa( + port_name, + local_mac_address, + macsec_port_identifier, + an, + True) + + def rekey_macsec( + self, + wpa: WPASupplicantMock, + port_name: str, + local_mac_address: str, + peer_mac_address: str, + macsec_port_identifier: int, + an: int, + last_an: int, + sak: str, + packet_number: int, + auth_key: str, + salt: str): + wpa.create_receive_sa( + port_name, + peer_mac_address, + macsec_port_identifier, + an, + sak, + auth_key, + packet_number, + salt) + wpa.create_transmit_sa( + port_name, + local_mac_address, + macsec_port_identifier, + an, + sak, + auth_key, + packet_number, + salt) + wpa.set_enable_receive_sa( + port_name, + peer_mac_address, + macsec_port_identifier, + an, + True) + wpa.set_macsec_control(port_name, True) + wpa.set_enable_transmit_sa( + port_name, + local_mac_address, + macsec_port_identifier, + an, + True) + wpa.set_enable_transmit_sa( + port_name, + local_mac_address, + macsec_port_identifier, + last_an, + False) + wpa.delete_transmit_sa( + port_name, + local_mac_address, + macsec_port_identifier, + last_an) + wpa.set_enable_receive_sa( + port_name, + peer_mac_address, + macsec_port_identifier, + last_an, + False) + wpa.delete_receive_sa( + port_name, + peer_mac_address, + macsec_port_identifier, + last_an) + + def deinit_macsec( + self, + wpa: WPASupplicantMock, + inspector: MACsecInspector, + port_name: str, + macsec_port: str, + local_mac_address: str, + peer_mac_address: str, + macsec_port_identifier: int, + last_an: int): + wpa.set_enable_receive_sa( + port_name, + peer_mac_address, + macsec_port_identifier, + last_an, + False) + wpa.delete_receive_sa( + port_name, + peer_mac_address, + macsec_port_identifier, + last_an) + assert( + not inspector.get_macsec_sa( + macsec_port, + peer_mac_address, + macsec_port_identifier, + last_an)) + wpa.delete_receive_sc( + port_name, + peer_mac_address, + macsec_port_identifier) + assert( + not inspector.get_macsec_sc( + macsec_port, + peer_mac_address, + macsec_port_identifier)) + wpa.set_enable_transmit_sa( + port_name, + local_mac_address, + macsec_port_identifier, + last_an, + False) + wpa.delete_transmit_sa( + port_name, + local_mac_address, + macsec_port_identifier, + last_an) + assert( + not inspector.get_macsec_sa( + macsec_port, + local_mac_address, + macsec_port_identifier, + last_an)) + wpa.delete_transmit_sc( + port_name, + local_mac_address, + macsec_port_identifier) + assert( + not inspector.get_macsec_sc( + macsec_port, + local_mac_address, + macsec_port_identifier)) + wpa.deinit_macsec_port(port_name) + + def test_macsec_term_orch(self, dvs: conftest.DockerVirtualSwitch, testlog): + port_name = "Ethernet0" + local_mac_address = "00-15-5D-78-FF-C1" + peer_mac_address = "00-15-5D-78-FF-C2" + macsec_port_identifier = 1 + macsec_port = "macsec_eth1" + sak = "0" * 32 + auth_key = "0" * 32 + packet_number = 1 + ssci = 1 + salt = "0" * 24 + + wpa = WPASupplicantMock(dvs) + inspector = MACsecInspector(dvs) + + self.init_macsec( + wpa, + port_name, + local_mac_address, + macsec_port_identifier, + ssci) + self.establish_macsec( + wpa, + port_name, + local_mac_address, + peer_mac_address, + macsec_port_identifier, + 0, + sak, + packet_number, + auth_key, + ssci, + salt) + assert(inspector.get_macsec_port(macsec_port)) + assert( + inspector.get_macsec_sc( + macsec_port, + local_mac_address, + macsec_port_identifier)) + assert( + inspector.get_macsec_sc( + macsec_port, + peer_mac_address, + macsec_port_identifier)) + assert( + inspector.get_macsec_sa( + macsec_port, + local_mac_address, + macsec_port_identifier, + 0)) + assert( + inspector.get_macsec_sa( + macsec_port, + peer_mac_address, + macsec_port_identifier, + 0)) + self.rekey_macsec( + wpa, + port_name, + local_mac_address, + peer_mac_address, + macsec_port_identifier, + 1, + 0, + sak, + packet_number, + auth_key, + salt) + assert( + inspector.get_macsec_sa( + macsec_port, + local_mac_address, + macsec_port_identifier, + 1)) + assert( + inspector.get_macsec_sa( + macsec_port, + peer_mac_address, + macsec_port_identifier, + 1)) + assert( + not inspector.get_macsec_sa( + macsec_port, + local_mac_address, + macsec_port_identifier, + 0)) + assert( + not inspector.get_macsec_sa( + macsec_port, + peer_mac_address, + macsec_port_identifier, + 0)) + # Exit MACsec port + self.deinit_macsec( + wpa, + inspector, + port_name, + macsec_port, + local_mac_address, + peer_mac_address, + macsec_port_identifier, + 1) + assert(not inspector.get_macsec_port(macsec_port)) + + +# Add Dummy always-pass test at end as workaroud +# for issue when Flaky fail on final test it invokes module tear-down +# before retrying +def test_nonflaky_dummy(): + pass From d9d583cd61e733cc852699b8b79153a765c1e979 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 27 Nov 2020 00:01:01 +0800 Subject: [PATCH 24/31] Change the name for clarity Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index d9607a87a5..103b508065 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -1686,7 +1686,7 @@ task_process_status MACsecOrch::createMACsecSA( sai_uint64_t pn = 1; if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - if (!get_value(sa_attr, "init_pn", pn)) + if (!get_value(sa_attr, "next_pn", pn)) { SWSS_LOG_WARN("The init pn isn't existed at SA %s", port_sci_an.c_str()); return task_failed; From a1e7d804db12b69a4bc70af96df99433432bba94 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Mon, 21 Dec 2020 17:08:46 +0800 Subject: [PATCH 25/31] Fix copy-n-paste error and polish print format Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 36 ++++++++++++++++++------------------ orchagent/saihelper.cpp | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 103b508065..a1b0922cad 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -25,12 +25,12 @@ extern sai_acl_api_t *sai_acl_api; extern sai_port_api_t *sai_port_api; extern sai_switch_api_t *sai_switch_api; -static const std::vector macsec_egress_sa_stats = +static const std::vector macsec_egress_sa_attrs = { "SAI_MACSEC_SA_ATTR_XPN", }; -static const std::vector macsec_ingress_sa_stats = +static const std::vector macsec_ingress_sa_attrs = { "SAI_MACSEC_SA_ATTR_MINIMUM_XPN", }; @@ -172,12 +172,12 @@ static bool hex_to_binary( { if (!std::isxdigit(static_cast(hex_str[hex_cur]))) { - SWSS_LOG_ERROR("Invalid hex string %s at %lu(%c)", hex_str.c_str(), hex_cur, hex_str[hex_cur]); + SWSS_LOG_ERROR("Invalid hex string %s at %" PRIu64 "(%c)", hex_str.c_str(), hex_cur, hex_str[hex_cur]); return false; } if (!std::isxdigit(static_cast(hex_str[hex_cur + 1]))) { - SWSS_LOG_ERROR("Invalid hex string %s at %lu(%c)", hex_str.c_str(), hex_cur + 1, hex_str[hex_cur + 1]); + SWSS_LOG_ERROR("Invalid hex string %s at %" PRIu64 "(%c)", hex_str.c_str(), hex_cur + 1, hex_str[hex_cur + 1]); return false; } std::stringstream stream; @@ -450,7 +450,7 @@ class MACsecOrchContext auto sc = scs.find(*m_sci); if (sc == scs.end()) { - SWSS_LOG_INFO("Cannot find the MACsec SC %lu at the port %s.", *m_sci, m_port_name->c_str()); + SWSS_LOG_INFO("Cannot find the MACsec SC 0x%" PRIx64 " at the port %s.", *m_sci, m_port_name->c_str()); return nullptr; } m_macsec_sc = &sc->second; @@ -476,7 +476,7 @@ class MACsecOrchContext if (an == sc->m_sa_ids.end()) { SWSS_LOG_INFO( - "Cannot find the MACsec SA %u of SC %lu at the port %s.", + "Cannot find the MACsec SA %u of SC 0x%" PRIx64 " at the port %s.", *m_an, *m_sci, m_port_name->c_str()); @@ -817,7 +817,7 @@ task_process_status MACsecOrch::updateEgressSA( MACsecOrchContext ctx(this, port_name, SAI_MACSEC_DIRECTION_EGRESS, sci, an); if (ctx.get_macsec_sc() == nullptr) { - SWSS_LOG_INFO("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); + SWSS_LOG_INFO("The MACsec SC 0x%" PRIx64 " hasn't been created at the port %s.", sci, port_name.c_str()); return task_need_retry; } if (ctx.get_macsec_sc()->m_encoding_an == an) @@ -893,7 +893,7 @@ bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id) auto macsec_obj = m_macsec_objs.emplace(switch_id, MACsecObject()); if (!macsec_obj.second) { - SWSS_LOG_INFO("The MACsec has been initialized at the switch %lu", switch_id); + SWSS_LOG_INFO("The MACsec has been initialized at the switch 0x%" PRIx64, switch_id); return true; } recover.add_action([&]() { m_macsec_objs.erase(macsec_obj.first); }); @@ -910,7 +910,7 @@ bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id) static_cast(attrs.size()), attrs.data()) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot initialize MACsec egress object at the switch %lu", switch_id); + SWSS_LOG_WARN("Cannot initialize MACsec egress object at the switch 0x%" PRIx64, switch_id); return false; } recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_egress_id); }); @@ -925,7 +925,7 @@ bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id) static_cast(attrs.size()), attrs.data()) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot initialize MACsec ingress object at the switch %lu", switch_id); + SWSS_LOG_WARN("Cannot initialize MACsec ingress object at the switch 0x%" PRIx64, switch_id); return false; } recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_ingress_id); }); @@ -939,7 +939,7 @@ bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id) attrs.data()) != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN( - "Cannot get MACsec attribution SAI_MACSEC_ATTR_SCI_IN_INGRESS_MACSEC_ACL at the switch %lu", + "Cannot get MACsec attribution SAI_MACSEC_ATTR_SCI_IN_INGRESS_MACSEC_ACL at the switch 0x%" PRIx64, switch_id); return false; } @@ -956,7 +956,7 @@ bool MACsecOrch::deinitMACsecObject(sai_object_id_t switch_id) auto macsec_obj = m_macsec_objs.find(switch_id); if (macsec_obj == m_macsec_objs.end()) { - SWSS_LOG_INFO("The MACsec wasn't initialized at the switch %lu", switch_id); + SWSS_LOG_INFO("The MACsec wasn't initialized at the switch 0x%" PRIx64, switch_id); return true; } @@ -965,14 +965,14 @@ bool MACsecOrch::deinitMACsecObject(sai_object_id_t switch_id) if (sai_macsec_api->remove_macsec( macsec_obj->second.m_egress_id) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot deinitialize MACsec egress object at the switch %lu", macsec_obj->first); + SWSS_LOG_WARN("Cannot deinitialize MACsec egress object at the switch 0x%" PRIx64, macsec_obj->first); result &= false; } if (sai_macsec_api->remove_macsec( macsec_obj->second.m_ingress_id) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot deinitialize MACsec ingress object at the switch %lu", macsec_obj->first); + SWSS_LOG_WARN("Cannot deinitialize MACsec ingress object at the switch 0x%" PRIx64, macsec_obj->first); result &= false; } @@ -1537,7 +1537,7 @@ bool MACsecOrch::createMACsecSC( static_cast(attrs.size()), attrs.data()) != SAI_STATUS_SUCCESS) { - SWSS_LOG_WARN("Cannot create MACsec egress SC %lu", sci); + SWSS_LOG_WARN("Cannot create MACsec egress SC 0x%" PRIx64, sci); return false; } return true; @@ -1649,7 +1649,7 @@ task_process_status MACsecOrch::createMACsecSA( if (ctx.get_macsec_sc() == nullptr) { - SWSS_LOG_INFO("The MACsec SC %lu hasn't been created at the port %s.", sci, port_name.c_str()); + SWSS_LOG_INFO("The MACsec SC 0x%" PRIx64 " hasn't been created at the port %s.", sci, port_name.c_str()); return task_need_retry; } auto sc = ctx.get_macsec_sc(); @@ -1746,12 +1746,12 @@ task_process_status MACsecOrch::createMACsecSA( fvVector.emplace_back("state", "ok"); if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - installCounter(CounterType::MACSEC_SA_ATTR, port_sci_an, sc->m_sa_ids[an], macsec_egress_sa_stats); + installCounter(CounterType::MACSEC_SA_ATTR, port_sci_an, sc->m_sa_ids[an], macsec_egress_sa_attrs); m_state_macsec_egress_sa.set(join('|', port_name, sci, an), fvVector); } else { - installCounter(CounterType::MACSEC_SA_ATTR, port_sci_an, sc->m_sa_ids[an], macsec_ingress_sa_stats); + installCounter(CounterType::MACSEC_SA_ATTR, port_sci_an, sc->m_sa_ids[an], macsec_ingress_sa_attrs); m_state_macsec_ingress_sa.set(join('|', port_name, sci, an), fvVector); } diff --git a/orchagent/saihelper.cpp b/orchagent/saihelper.cpp index 2341165459..d0b04cd88d 100644 --- a/orchagent/saihelper.cpp +++ b/orchagent/saihelper.cpp @@ -199,7 +199,7 @@ void initSaiApi() sai_log_set(SAI_API_SAMPLEPACKET, SAI_LOG_LEVEL_NOTICE); sai_log_set(SAI_API_DEBUG_COUNTER, SAI_LOG_LEVEL_NOTICE); sai_log_set((sai_api_t)SAI_API_NAT, SAI_LOG_LEVEL_NOTICE); - sai_log_set(SAI_API_NAT, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_MACSEC, SAI_LOG_LEVEL_NOTICE); } void initSaiRedis(const string &record_location) From 142d20a6a9cda78b6e7f2d71e9f87b89dc57a7a4 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Tue, 22 Dec 2020 20:10:16 +0800 Subject: [PATCH 26/31] Fix default value and typo Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index a1b0922cad..0cc17dda0e 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -25,6 +25,9 @@ extern sai_acl_api_t *sai_acl_api; extern sai_port_api_t *sai_port_api; extern sai_switch_api_t *sai_switch_api; +constexpr bool DEFAULT_ENABLE_ENCRYPT = true; +constexpr bool SCI_IN_SECTAG = false; + static const std::vector macsec_egress_sa_attrs = { "SAI_MACSEC_SA_ATTR_XPN", @@ -913,7 +916,7 @@ bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id) SWSS_LOG_WARN("Cannot initialize MACsec egress object at the switch 0x%" PRIx64, switch_id); return false; } - recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_egress_id); }); + recover.add_action([&]() { sai_macsec_api->remove_macsec(macsec_obj.first->second.m_egress_id); }); attrs.clear(); attr.id = SAI_MACSEC_ATTR_DIRECTION; @@ -928,7 +931,7 @@ bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id) SWSS_LOG_WARN("Cannot initialize MACsec ingress object at the switch 0x%" PRIx64, switch_id); return false; } - recover.add_action([&]() { sai_macsec_api->remove_macsec_port(macsec_obj.first->second.m_ingress_id); }); + recover.add_action([&]() { sai_macsec_api->remove_macsec(macsec_obj.first->second.m_ingress_id); }); attrs.clear(); attr.id = SAI_MACSEC_ATTR_SCI_IN_INGRESS_MACSEC_ACL; @@ -1020,8 +1023,8 @@ bool MACsecOrch::createMACsecPort( macsec_port.m_ingress_port_id = SAI_NULL_OBJECT_ID; }); - macsec_port.m_enable_encrypt = true; - macsec_port.m_sci_in_sectag = true; + macsec_port.m_enable_encrypt = DEFAULT_ENABLE_ENCRYPT; + macsec_port.m_sci_in_sectag = SCI_IN_SECTAG; macsec_port.m_enable = false; // If hardware matches SCI in ACL, the macsec_flow maps to an IEEE 802.1ae SecY object. From 24a7b3ac8fcd2d4eba5f7843d502a4b9bafbc1f3 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Tue, 22 Dec 2020 20:13:09 +0800 Subject: [PATCH 27/31] rename task functions Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 42 ++++++++++++++++++++-------------------- orchagent/macsecorch.h | 20 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 0cc17dda0e..aa972108d5 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -579,7 +579,7 @@ MACsecOrch::~MACsecOrch() { auto port = m_macsec_ports.begin(); const MACsecOrch::TaskArgs temp; - disableMACsecPort(port->first, temp); + taskDisableMACsecPort(port->first, temp); } } @@ -593,25 +593,25 @@ void MACsecOrch::doTask(Consumer &consumer) const TaskArgs &); const static std::map TaskMap = { {{APP_MACSEC_PORT_TABLE_NAME, SET_COMMAND}, - &MACsecOrch::updateMACsecPort}, + &MACsecOrch::taskUpdateMACsecPort}, {{APP_MACSEC_PORT_TABLE_NAME, DEL_COMMAND}, - &MACsecOrch::disableMACsecPort}, + &MACsecOrch::taskDisableMACsecPort}, {{APP_MACSEC_EGRESS_SC_TABLE_NAME, SET_COMMAND}, - &MACsecOrch::updateEgressSC}, + &MACsecOrch::taskUpdateEgressSC}, {{APP_MACSEC_EGRESS_SC_TABLE_NAME, DEL_COMMAND}, - &MACsecOrch::deleteEgressSC}, + &MACsecOrch::taskDeleteEgressSC}, {{APP_MACSEC_INGRESS_SC_TABLE_NAME, SET_COMMAND}, - &MACsecOrch::updateIngressSC}, + &MACsecOrch::taskUpdateIngressSC}, {{APP_MACSEC_INGRESS_SC_TABLE_NAME, DEL_COMMAND}, - &MACsecOrch::deleteIngressSC}, + &MACsecOrch::taskDeleteIngressSC}, {{APP_MACSEC_EGRESS_SA_TABLE_NAME, SET_COMMAND}, - &MACsecOrch::updateEgressSA}, + &MACsecOrch::taskUpdateEgressSA}, {{APP_MACSEC_EGRESS_SA_TABLE_NAME, DEL_COMMAND}, - &MACsecOrch::deleteEgressSA}, + &MACsecOrch::taskDeleteEgressSA}, {{APP_MACSEC_INGRESS_SA_TABLE_NAME, SET_COMMAND}, - &MACsecOrch::updateIngressSA}, + &MACsecOrch::taskUpdateIngressSA}, {{APP_MACSEC_INGRESS_SA_TABLE_NAME, DEL_COMMAND}, - &MACsecOrch::deleteIngressSA}, + &MACsecOrch::taskDeleteIngressSA}, }; const std::string &table_name = consumer.getTableName(); @@ -666,7 +666,7 @@ void MACsecOrch::doTask(Consumer &consumer) } } -task_process_status MACsecOrch::updateMACsecPort( +task_process_status MACsecOrch::taskUpdateMACsecPort( const std::string &port_name, const TaskArgs &port_attr) { @@ -722,7 +722,7 @@ task_process_status MACsecOrch::updateMACsecPort( return task_success; } -task_process_status MACsecOrch::disableMACsecPort( +task_process_status MACsecOrch::taskDisableMACsecPort( const std::string &port_name, const TaskArgs &port_attr) { @@ -771,7 +771,7 @@ task_process_status MACsecOrch::disableMACsecPort( return result; } -task_process_status MACsecOrch::updateEgressSC( +task_process_status MACsecOrch::taskUpdateEgressSC( const std::string &port_sci, const TaskArgs &sc_attr) { @@ -779,7 +779,7 @@ task_process_status MACsecOrch::updateEgressSC( return updateMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_EGRESS); } -task_process_status MACsecOrch::deleteEgressSC( +task_process_status MACsecOrch::taskDeleteEgressSC( const std::string &port_sci, const TaskArgs &sc_attr) { @@ -787,7 +787,7 @@ task_process_status MACsecOrch::deleteEgressSC( return deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS); } -task_process_status MACsecOrch::updateIngressSC( +task_process_status MACsecOrch::taskUpdateIngressSC( const std::string &port_sci, const TaskArgs &sc_attr) { @@ -795,7 +795,7 @@ task_process_status MACsecOrch::updateIngressSC( return updateMACsecSC(port_sci, sc_attr, SAI_MACSEC_DIRECTION_INGRESS); } -task_process_status MACsecOrch::deleteIngressSC( +task_process_status MACsecOrch::taskDeleteIngressSC( const std::string &port_sci, const TaskArgs &sc_attr) { @@ -803,7 +803,7 @@ task_process_status MACsecOrch::deleteIngressSC( return deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS); } -task_process_status MACsecOrch::updateEgressSA( +task_process_status MACsecOrch::taskUpdateEgressSA( const std::string &port_sci_an, const TaskArgs &sa_attr) { @@ -830,7 +830,7 @@ task_process_status MACsecOrch::updateEgressSA( return task_need_retry; } -task_process_status MACsecOrch::deleteEgressSA( +task_process_status MACsecOrch::taskDeleteEgressSA( const std::string &port_sci_an, const TaskArgs &sa_attr) { @@ -838,7 +838,7 @@ task_process_status MACsecOrch::deleteEgressSA( return deleteMACsecSA(port_sci_an, SAI_MACSEC_DIRECTION_EGRESS); } -task_process_status MACsecOrch::updateIngressSA( +task_process_status MACsecOrch::taskUpdateIngressSA( const std::string &port_sci_an, const TaskArgs &sa_attr) { @@ -879,7 +879,7 @@ task_process_status MACsecOrch::updateIngressSA( } } -task_process_status MACsecOrch::deleteIngressSA( +task_process_status MACsecOrch::taskDeleteIngressSA( const std::string &port_sci_an, const TaskArgs &sa_attr) { diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index af8cde1e5d..6817e1a28e 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -42,16 +42,16 @@ class MACsecOrch : public Orch private: - task_process_status updateMACsecPort(const std::string & port_name, const TaskArgs & port_attr); - task_process_status disableMACsecPort(const std::string & port_name, const TaskArgs & port_attr); - task_process_status updateEgressSC(const std::string & port_sci, const TaskArgs & sc_attr); - task_process_status deleteEgressSC(const std::string & port_sci, const TaskArgs & sc_attr); - task_process_status updateIngressSC(const std::string & port_sci, const TaskArgs & sc_attr); - task_process_status deleteIngressSC(const std::string & port_sci, const TaskArgs & sc_attr); - task_process_status updateEgressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); - task_process_status deleteEgressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); - task_process_status updateIngressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); - task_process_status deleteIngressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); + task_process_status taskUpdateMACsecPort(const std::string & port_name, const TaskArgs & port_attr); + task_process_status taskDisableMACsecPort(const std::string & port_name, const TaskArgs & port_attr); + task_process_status taskUpdateEgressSC(const std::string & port_sci, const TaskArgs & sc_attr); + task_process_status taskDeleteEgressSC(const std::string & port_sci, const TaskArgs & sc_attr); + task_process_status taskUpdateIngressSC(const std::string & port_sci, const TaskArgs & sc_attr); + task_process_status taskDeleteIngressSC(const std::string & port_sci, const TaskArgs & sc_attr); + task_process_status taskUpdateEgressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); + task_process_status taskDeleteEgressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); + task_process_status taskUpdateIngressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); + task_process_status taskDeleteIngressSA(const std::string & port_sci_an, const TaskArgs & sa_attr); PortsOrch * m_port_orch; From 497b72de3b40da216aa2a6c453765ef27e687696 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Wed, 23 Dec 2020 01:29:32 +0800 Subject: [PATCH 28/31] Adapt MACsec SAI 1.7.1 Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 106 ++++++++++++++++++++++++++------------- orchagent/macsecorch.h | 10 ++-- 2 files changed, 75 insertions(+), 41 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index aa972108d5..1ff0d63df2 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -26,7 +26,8 @@ extern sai_port_api_t *sai_port_api; extern sai_switch_api_t *sai_switch_api; constexpr bool DEFAULT_ENABLE_ENCRYPT = true; -constexpr bool SCI_IN_SECTAG = false; +constexpr bool DEFAULT_SCI_IN_SECTAG = false; +constexpr sai_macsec_cipher_suite_t DEFAULT_CIPHER_SUITE = SAI_MACSEC_CIPHER_SUITE_GCM_AES_128; static const std::vector macsec_egress_sa_attrs = { @@ -1024,7 +1025,8 @@ bool MACsecOrch::createMACsecPort( }); macsec_port.m_enable_encrypt = DEFAULT_ENABLE_ENCRYPT; - macsec_port.m_sci_in_sectag = SCI_IN_SECTAG; + macsec_port.m_sci_in_sectag = DEFAULT_SCI_IN_SECTAG; + macsec_port.m_cipher_suite = DEFAULT_CIPHER_SUITE; macsec_port.m_enable = false; // If hardware matches SCI in ACL, the macsec_flow maps to an IEEE 802.1ae SecY object. @@ -1142,6 +1144,31 @@ bool MACsecOrch::updateMACsecPort(MACsecPort &macsec_port, const TaskArgs &port_ get_value(port_attr, "enable_encrypt", macsec_port.m_enable_encrypt); get_value(port_attr, "send_sci", macsec_port.m_sci_in_sectag); + std::string cipher_suite; + if (get_value(port_attr, "cipher_suite", cipher_suite)) + { + if (cipher_suite == "GCM-AES-128") + { + macsec_port.m_cipher_suite = SAI_MACSEC_CIPHER_SUITE_GCM_AES_128; + } + else if (cipher_suite == "GCM-AES-256") + { + macsec_port.m_cipher_suite = SAI_MACSEC_CIPHER_SUITE_GCM_AES_256; + } + else if (cipher_suite == "GCM-AES-XPN-128") + { + macsec_port.m_cipher_suite = SAI_MACSEC_CIPHER_SUITE_GCM_AES_XPN_128; + } + else if (cipher_suite == "GCM-AES-XPN-256") + { + macsec_port.m_cipher_suite = SAI_MACSEC_CIPHER_SUITE_GCM_AES_XPN_256; + } + else + { + SWSS_LOG_WARN("Unknow Cipher Suite %s", cipher_suite.c_str()); + return false; + } + } bool enable = false; if (get_value(port_attr, "enable", enable) && enable != macsec_port.m_enable) { @@ -1407,12 +1434,6 @@ bool MACsecOrch::createMACsecSC( }); auto sc = &sc_itr.first->second; - sai_uint32_t ssci = 0; - sc->m_xpn64_enable = false; - if (get_value(sc_attr, "ssci", ssci) && ssci) - { - sc->m_xpn64_enable = true; - } if (direction == SAI_MACSEC_DIRECTION_EGRESS) { get_value(sc_attr, "encoding_an", sc->m_encoding_an); @@ -1444,9 +1465,9 @@ bool MACsecOrch::createMACsecSC( direction, sc->m_flow_id, sci, - ssci, + macsec_port.m_enable_encrypt, macsec_port.m_sci_in_sectag, - sc->m_xpn64_enable)) + macsec_port.m_cipher_suite)) { SWSS_LOG_WARN("Create MACsec SC %s fail.", port_sci.c_str()); return false; @@ -1503,9 +1524,9 @@ bool MACsecOrch::createMACsecSC( sai_macsec_direction_t direction, sai_object_id_t flow_id, sai_uint64_t sci, - sai_uint32_t ssci, + bool encryption_enable, bool send_sci, - bool xpn64_enable) + sai_macsec_cipher_suite_t cipher_suite) { SWSS_LOG_ENTER(); @@ -1521,18 +1542,15 @@ bool MACsecOrch::createMACsecSC( attr.id = SAI_MACSEC_SC_ATTR_MACSEC_SCI; attr.value.u64 = sci; attrs.push_back(attr); - if (xpn64_enable) - { - attr.id = SAI_MACSEC_SC_ATTR_MACSEC_SSCI; - attr.value.u32 = ssci; - attrs.push_back(attr); - } - attr.id = SAI_MACSEC_SC_ATTR_MACSEC_XPN64_ENABLE; - attr.value.booldata = xpn64_enable; + attr.id = SAI_MACSEC_SC_ATTR_ENCRYPTION_ENABLE; + attr.value.booldata = encryption_enable; attrs.push_back(attr); attr.id = SAI_MACSEC_SC_ATTR_MACSEC_EXPLICIT_SCI_ENABLE; attr.value.booldata = send_sci; attrs.push_back(attr); + attr.id = SAI_MACSEC_SC_ATTR_MACSEC_CIPHER_SUITE; + attr.value.s32 = cipher_suite; + attrs.push_back(attr); if (sai_macsec_api->create_macsec_sc( &sc_id, @@ -1659,6 +1677,7 @@ task_process_status MACsecOrch::createMACsecSA( MACsecSAK sak = {{0}, false}; MACsecSalt salt = {0}; + sai_uint32_t ssci = 0; MACsecAuthKey auth_key = {0}; try { @@ -1667,13 +1686,37 @@ task_process_status MACsecOrch::createMACsecSA( SWSS_LOG_WARN("The SAK isn't existed at SA %s", port_sci_an.c_str()); return task_failed; } - if (sc->m_xpn64_enable) + if (sak.m_sak_256_enable) + { + if (ctx.get_macsec_port()->m_cipher_suite == SAI_MACSEC_CIPHER_SUITE_GCM_AES_128 + && ctx.get_macsec_port()->m_cipher_suite == SAI_MACSEC_CIPHER_SUITE_GCM_AES_XPN_128) + { + SWSS_LOG_WARN("Wrong SAK with 256 bit, expect 128 bit"); + return task_failed; + } + } + else + { + if (ctx.get_macsec_port()->m_cipher_suite == SAI_MACSEC_CIPHER_SUITE_GCM_AES_256 + && ctx.get_macsec_port()->m_cipher_suite == SAI_MACSEC_CIPHER_SUITE_GCM_AES_XPN_256) + { + SWSS_LOG_WARN("Wrong SAK with 128 bit, expect 256 bit"); + return task_failed; + } + } + if (ctx.get_macsec_port()->m_cipher_suite == SAI_MACSEC_CIPHER_SUITE_GCM_AES_XPN_128 + || ctx.get_macsec_port()->m_cipher_suite == SAI_MACSEC_CIPHER_SUITE_GCM_AES_XPN_256) { if (!get_value(sa_attr, "salt", salt)) { SWSS_LOG_WARN("The salt isn't existed at SA %s", port_sci_an.c_str()); return task_failed; } + if (!get_value(sa_attr, "ssci", ssci)) + { + SWSS_LOG_WARN("The ssci isn't existed at SA %s", port_sci_an.c_str()); + return task_failed; + } } if (!get_value(sa_attr, "auth_key", auth_key)) { @@ -1729,11 +1772,9 @@ task_process_status MACsecOrch::createMACsecSA( direction, sc->m_sc_id, an, - ctx.get_macsec_port()->m_enable_encrypt, - sak.m_sak_256_enable, sak.m_sak, - sc->m_xpn64_enable, salt.m_salt, + ssci, auth_key.m_auth_key, pn)) { @@ -1828,11 +1869,9 @@ bool MACsecOrch::createMACsecSA( sai_macsec_direction_t direction, sai_object_id_t sc_id, macsec_an_t an, - bool encryption_enable, - bool sak_256_bit, sai_macsec_sak_t sak, - bool xpn64_enable, sai_macsec_salt_t salt, + sai_uint32_t ssci, sai_macsec_auth_key_t auth_key, sai_uint64_t pn) { @@ -1853,14 +1892,6 @@ bool MACsecOrch::createMACsecSA( attr.value.u8 = static_cast(an); attrs.push_back(attr); - attr.id = SAI_MACSEC_SA_ATTR_ENCRYPTION_ENABLE; - attr.value.booldata = encryption_enable; - attrs.push_back(attr); - - attr.id = SAI_MACSEC_SA_ATTR_SAK_256_BITS; - attr.value.booldata = sak_256_bit; - attrs.push_back(attr); - attr.id = SAI_MACSEC_SA_ATTR_SAK; std::copy(sak, sak + sizeof(attr.value.macsecsak), attr.value.macsecsak); attrs.push_back(attr); @@ -1870,6 +1901,11 @@ bool MACsecOrch::createMACsecSA( std::copy(salt, salt + sizeof(attr.value.macsecsalt), attr.value.macsecsalt); attrs.push_back(attr); + // Valid when SAI_MACSEC_SC_ATTR_MACSEC_XPN64_ENABLE == true. + attr.id = SAI_MACSEC_SA_ATTR_MACSEC_SSCI; + attr.value.u32 = ssci; + attrs.push_back(attr); + attr.id = SAI_MACSEC_SA_ATTR_AUTH_KEY; std::copy(auth_key, auth_key + sizeof(attr.value.macsecauthkey), attr.value.macsecauthkey); attrs.push_back(attr); diff --git a/orchagent/macsecorch.h b/orchagent/macsecorch.h index 6817e1a28e..8e6b9e8675 100644 --- a/orchagent/macsecorch.h +++ b/orchagent/macsecorch.h @@ -74,7 +74,6 @@ class MACsecOrch : public Orch struct MACsecSC { macsec_an_t m_encoding_an; - bool m_xpn64_enable; sai_object_id_t m_sc_id; std::map m_sa_ids; sai_object_id_t m_flow_id; @@ -91,6 +90,7 @@ class MACsecOrch : public Orch std::map m_ingress_scs; MACsecACLTable m_egress_acl_table; MACsecACLTable m_ingress_acl_table; + sai_macsec_cipher_suite_t m_cipher_suite; bool m_enable_encrypt; bool m_sci_in_sectag; bool m_enable; @@ -160,9 +160,9 @@ class MACsecOrch : public Orch sai_macsec_direction_t direction, sai_object_id_t flow_id, sai_uint64_t sci, - sai_uint32_t ssci, + bool encryption_enable, bool send_sci, - bool xpn64_enable); + sai_macsec_cipher_suite_t cipher_suite); task_process_status deleteMACsecSC( const std::string &port_sci, sai_macsec_direction_t direction); @@ -182,11 +182,9 @@ class MACsecOrch : public Orch sai_macsec_direction_t direction, sai_object_id_t sc_id, macsec_an_t an, - bool encryption_enable, - bool sak_256_bit, sai_macsec_sak_t sak, - bool xpn64_enable, sai_macsec_salt_t salt, + sai_uint32_t ssci, sai_macsec_auth_key_t auth_key, sai_uint64_t pn); bool deleteMACsecSA(sai_object_id_t sa_id); From e1da4a5c649747e15b9e07b659c81dd846999068 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Wed, 30 Dec 2020 23:40:52 +0800 Subject: [PATCH 29/31] Move common functions to swss-common Signed-off-by: Ze Gan --- orchagent/macsecorch.cpp | 253 +++++++++++---------------------------- 1 file changed, 72 insertions(+), 181 deletions(-) diff --git a/orchagent/macsecorch.cpp b/orchagent/macsecorch.cpp index 1ff0d63df2..e43b9504f9 100644 --- a/orchagent/macsecorch.cpp +++ b/orchagent/macsecorch.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include #include @@ -11,6 +14,7 @@ #include #include #include +#include /* Global Variables*/ @@ -39,160 +43,46 @@ static const std::vector macsec_ingress_sa_attrs = "SAI_MACSEC_SA_ATTR_MINIMUM_XPN", }; -/* Helpers */ - -template -static bool split(const std::string &input, char delimiter, T &output) +template +static bool extract_variables(const std::string &input, char delimiter, T &output, Args &... args) { - if (input.find(delimiter) != std::string::npos) + const auto tokens = swss::tokenize(input, delimiter); + try { - return false; + swss::lexical_convert(tokens, output, args...); + return true; } - std::istringstream istream(input); - istream >> output; - return true; -} - -template -static bool split(const std::string &input, char delimiter, T &output, Args &... args) -{ - auto pos = input.find(delimiter); - if (pos == std::string::npos) + catch(const std::exception& e) { return false; } - std::istringstream istream(input.substr(0, pos)); - istream >> output; - return split(input.substr(pos + 1, input.length() - pos - 1), delimiter, args...); } -template -static std::string join(const T &input) -{ - std::ostringstream ostream; - ostream << input; - return ostream.str(); -} - -template -static std::string join(char delimiter, const T &input) -{ - return join(input); -} - -template -static std::string join(char delimiter, const T &input, const Args &... args) -{ - std::ostringstream ostream; - ostream << input << delimiter << join(delimiter, args...); - return ostream.str(); -} - -template +template static bool get_value( - const MACsecOrch::TaskArgs &ta, - const std::string &field, - T &value) + const MACsecOrch::TaskArgs & ta, + const std::string & field, + T & value) { SWSS_LOG_ENTER(); - std::string target_field = field; - std::transform( - target_field.begin(), - target_field.end(), - target_field.begin(), - ::tolower); - auto itr = std::find_if( - ta.begin(), - ta.end(), - [&](const MACsecOrch::TaskArgs::value_type &entry) { - std::string field = fvField(entry); - std::transform( - field.begin(), - field.end(), - field.begin(), - ::tolower); - return field == target_field; - }); - if (itr != ta.end()) - { - std::istringstream istream(fvValue(*itr)); - istream >> value; - SWSS_LOG_DEBUG( - "Set field '%s' as '%s'", - field.c_str(), - fvValue(*itr).c_str()); - return true; - } - SWSS_LOG_DEBUG("Cannot find field : %s", field.c_str()); - return false; -} - -static std::istringstream &operator>>( - std::istringstream &istream, - bool &b) -{ - std::string buffer = istream.str(); - std::transform( - buffer.begin(), - buffer.end(), - buffer.begin(), - ::tolower); - if (buffer == "true" || buffer == "1") + auto value_opt = swss::fvsGetValue(ta, field, true); + if (!value_opt) { - b = true; - } - else if (buffer == "false" || buffer == "0") - { - b = false; - } - else - { - throw std::invalid_argument("Invalid bool string : " + buffer); + SWSS_LOG_DEBUG("Cannot find field : %s", field.c_str()); + return false; } - return istream; -} - -static bool hex_to_binary( - const std::string &hex_str, - std::uint8_t *buffer, - size_t buffer_length) -{ - SWSS_LOG_ENTER(); - size_t buffer_cur = 0; - size_t hex_cur = 0; - if (hex_str.length() %2 != 0) + try { - SWSS_LOG_ERROR("Invalid hex string %s", hex_str.c_str()); - return false; + lexical_convert(*value_opt, value); + return true; } - if (hex_str.length() > (buffer_length * 2)) + catch(const std::exception &err) { - SWSS_LOG_ERROR("Buffer length isn't sufficient."); + SWSS_LOG_DEBUG("Cannot convert field : %s to type : %s", field.c_str(), typeid(T).name()); return false; } - while (hex_cur < hex_str.length()) - { - if (!std::isxdigit(static_cast(hex_str[hex_cur]))) - { - SWSS_LOG_ERROR("Invalid hex string %s at %" PRIu64 "(%c)", hex_str.c_str(), hex_cur, hex_str[hex_cur]); - return false; - } - if (!std::isxdigit(static_cast(hex_str[hex_cur + 1]))) - { - SWSS_LOG_ERROR("Invalid hex string %s at %" PRIu64 "(%c)", hex_str.c_str(), hex_cur + 1, hex_str[hex_cur + 1]); - return false; - } - std::stringstream stream; - stream << std::hex; - stream << hex_str[hex_cur++]; - stream << hex_str[hex_cur++]; - std::uint32_t value; - stream >> value; - buffer[buffer_cur++] = static_cast(value); - } - return true; } struct MACsecSAK @@ -201,12 +91,10 @@ struct MACsecSAK bool m_sak_256_enable; }; -static std::istringstream &operator>>( - std::istringstream &istream, - MACsecSAK &sak) +static void lexical_convert(const std::string &buffer, MACsecSAK &sak) { SWSS_LOG_ENTER(); - const std::string &buffer = istream.str(); + bool convert_done = false; memset(&sak, 0, sizeof(sak)); // One hex indicates 4 bits @@ -216,7 +104,7 @@ static std::istringstream &operator>>( { // 128-bit SAK uses only Bytes 16..31. sak.m_sak_256_enable = false; - convert_done = hex_to_binary( + convert_done = swss::hex_to_binary( buffer, &sak.m_sak[16], 16); @@ -225,16 +113,16 @@ static std::istringstream &operator>>( else if (bit_count == 256) { sak.m_sak_256_enable = true; - convert_done = hex_to_binary( + convert_done = swss::hex_to_binary( buffer, sak.m_sak, 32); } + if (!convert_done) { - throw std::invalid_argument("Invalid SAK : " + buffer); + SWSS_LOG_THROW("Invalid SAK %s", buffer.c_str()); } - return istream; } struct MACsecSalt @@ -242,19 +130,16 @@ struct MACsecSalt sai_macsec_salt_t m_salt; }; -static std::istringstream &operator>>( - std::istringstream &istream, - MACsecSalt &salt) +static void lexical_convert(const std::string &buffer, MACsecSalt &salt) { SWSS_LOG_ENTER(); - const std::string &buffer = istream.str(); + memset(&salt, 0, sizeof(salt)); if ( - (buffer.length() != sizeof(salt.m_salt) * 2) || (!hex_to_binary(buffer, salt.m_salt, sizeof(salt.m_salt)))) + (buffer.length() != sizeof(salt.m_salt) * 2) || (!swss::hex_to_binary(buffer, salt.m_salt, sizeof(salt.m_salt)))) { - throw std::invalid_argument("Invalid SALT : " + buffer); + SWSS_LOG_THROW("Invalid SALT %s", buffer.c_str()); } - return istream; } struct MACsecAuthKey @@ -262,22 +147,19 @@ struct MACsecAuthKey sai_macsec_auth_key_t m_auth_key; }; -static std::istringstream &operator>>( - std::istringstream &istream, - MACsecAuthKey &auth_key) +static void lexical_convert(const std::string &buffer, MACsecAuthKey &auth_key) { SWSS_LOG_ENTER(); - const std::string &buffer = istream.str(); + memset(&auth_key, 0, sizeof(auth_key)); if ( - (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!hex_to_binary( + (buffer.length() != sizeof(auth_key.m_auth_key) * 2) || (!swss::hex_to_binary( buffer, auth_key.m_auth_key, sizeof(auth_key.m_auth_key)))) { - throw std::invalid_argument("Invalid Auth Key : " + buffer); + SWSS_LOG_THROW("Invalid Auth Key %s", buffer.c_str()); } - return istream; } /* Recover from a fail action by a serial of pre-defined recover actions */ @@ -812,7 +694,7 @@ task_process_status MACsecOrch::taskUpdateEgressSA( std::string port_name; sai_uint64_t sci = 0; macsec_an_t an = 0; - if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) + if (!extract_variables(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); return task_failed; @@ -845,8 +727,9 @@ task_process_status MACsecOrch::taskUpdateIngressSA( { SWSS_LOG_ENTER(); - bool active = false; - get_value(sa_attr, "active", active); + swss::AlphaBoolean alpha_boolean = false; + get_value(sa_attr, "active", alpha_boolean); + bool active = alpha_boolean.operator bool(); if (active) { return createMACsecSA(port_sci_an, sa_attr, SAI_MACSEC_DIRECTION_INGRESS); @@ -857,7 +740,7 @@ task_process_status MACsecOrch::taskUpdateIngressSA( std::string port_name; sai_uint64_t sci = 0; macsec_an_t an = 0; - if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) + if (!extract_variables(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); return task_failed; @@ -1142,8 +1025,16 @@ bool MACsecOrch::updateMACsecPort(MACsecPort &macsec_port, const TaskArgs &port_ RecoverStack recover; - get_value(port_attr, "enable_encrypt", macsec_port.m_enable_encrypt); - get_value(port_attr, "send_sci", macsec_port.m_sci_in_sectag); + swss::AlphaBoolean alpha_boolean; + + if (get_value(port_attr, "enable_encrypt", alpha_boolean)) + { + macsec_port.m_enable_encrypt = alpha_boolean.operator bool(); + } + if (get_value(port_attr, "send_sci", alpha_boolean)) + { + macsec_port.m_sci_in_sectag = alpha_boolean.operator bool(); + } std::string cipher_suite; if (get_value(port_attr, "cipher_suite", cipher_suite)) { @@ -1169,11 +1060,11 @@ bool MACsecOrch::updateMACsecPort(MACsecPort &macsec_port, const TaskArgs &port_ return false; } } - bool enable = false; - if (get_value(port_attr, "enable", enable) && enable != macsec_port.m_enable) + swss::AlphaBoolean enable = false; + if (get_value(port_attr, "enable", enable) && enable.operator bool() != macsec_port.m_enable) { std::vector macsec_scs; - macsec_port.m_enable = enable; + macsec_port.m_enable = enable.operator bool(); for (auto &sc : macsec_port.m_egress_scs) { macsec_scs.push_back(&sc.second); @@ -1219,7 +1110,7 @@ bool MACsecOrch::deleteMACsecPort( for (auto &sc : macsec_port.m_egress_scs) { - const std::string port_sci = join(':', port_name, sc.first); + const std::string port_sci = swss::join(':', port_name, sc.first); if (deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_EGRESS) != task_success) { result &= false; @@ -1227,7 +1118,7 @@ bool MACsecOrch::deleteMACsecPort( } for (auto &sc : macsec_port.m_ingress_scs) { - const std::string port_sci = join(':', port_name, sc.first); + const std::string port_sci = swss::join(':', port_name, sc.first); if (deleteMACsecSC(port_sci, SAI_MACSEC_DIRECTION_INGRESS) != task_success) { result &= false; @@ -1336,7 +1227,7 @@ task_process_status MACsecOrch::updateMACsecSC( std::string port_name; sai_uint64_t sci = {0}; - if (!split(port_sci, ':', port_name, sci)) + if (!extract_variables(port_sci, ':', port_name, sci)) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci.c_str()); return task_failed; @@ -1414,7 +1305,7 @@ bool MACsecOrch::createMACsecSC( RecoverStack recover; - const std::string port_sci = join(':', port_name, sci); + const std::string port_sci = swss::join(':', port_name, sci); auto scs = (direction == SAI_MACSEC_DIRECTION_EGRESS) @@ -1507,11 +1398,11 @@ bool MACsecOrch::createMACsecSC( fvVector.emplace_back("state", "ok"); if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - m_state_macsec_egress_sc.set(join('|', port_name, sci), fvVector); + m_state_macsec_egress_sc.set(swss::join('|', port_name, sci), fvVector); } else { - m_state_macsec_ingress_sc.set(join('|', port_name, sci), fvVector); + m_state_macsec_ingress_sc.set(swss::join('|', port_name, sci), fvVector); } recover.clear(); @@ -1572,7 +1463,7 @@ task_process_status MACsecOrch::deleteMACsecSC( std::string port_name; sai_uint64_t sci = 0; - if (!split(port_sci, ':', port_name, sci)) + if (!extract_variables(port_sci, ':', port_name, sci)) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci.c_str()); return task_failed; @@ -1590,7 +1481,7 @@ task_process_status MACsecOrch::deleteMACsecSC( for (auto &sa : ctx.get_macsec_sc()->m_sa_ids) { - const std::string port_sci_an = join(':', port_sci, sa.first); + const std::string port_sci_an = swss::join(':', port_sci, sa.first); deleteMACsecSA(port_sci_an, direction); } @@ -1622,11 +1513,11 @@ task_process_status MACsecOrch::deleteMACsecSC( if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - m_state_macsec_egress_sc.del(join('|', port_name, sci)); + m_state_macsec_egress_sc.del(swss::join('|', port_name, sci)); } else { - m_state_macsec_ingress_sc.del(join('|', port_name, sci)); + m_state_macsec_ingress_sc.del(swss::join('|', port_name, sci)); } return result; @@ -1654,7 +1545,7 @@ task_process_status MACsecOrch::createMACsecSA( std::string port_name; sai_uint64_t sci = 0; macsec_an_t an = 0; - if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) + if (!extract_variables(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); return task_failed; @@ -1791,12 +1682,12 @@ task_process_status MACsecOrch::createMACsecSA( if (direction == SAI_MACSEC_DIRECTION_EGRESS) { installCounter(CounterType::MACSEC_SA_ATTR, port_sci_an, sc->m_sa_ids[an], macsec_egress_sa_attrs); - m_state_macsec_egress_sa.set(join('|', port_name, sci, an), fvVector); + m_state_macsec_egress_sa.set(swss::join('|', port_name, sci, an), fvVector); } else { installCounter(CounterType::MACSEC_SA_ATTR, port_sci_an, sc->m_sa_ids[an], macsec_ingress_sa_attrs); - m_state_macsec_ingress_sa.set(join('|', port_name, sci, an), fvVector); + m_state_macsec_ingress_sa.set(swss::join('|', port_name, sci, an), fvVector); } SWSS_LOG_NOTICE("MACsec SA %s is created.", port_sci_an.c_str()); @@ -1814,7 +1705,7 @@ task_process_status MACsecOrch::deleteMACsecSA( std::string port_name = ""; sai_uint64_t sci = 0; macsec_an_t an = 0; - if (!split(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) + if (!extract_variables(port_sci_an, ':', port_name, sci, an) || an > MAX_SA_NUMBER) { SWSS_LOG_WARN("The key %s isn't correct.", port_sci_an.c_str()); return task_failed; @@ -1852,11 +1743,11 @@ task_process_status MACsecOrch::deleteMACsecSA( if (direction == SAI_MACSEC_DIRECTION_EGRESS) { - m_state_macsec_egress_sa.del(join('|', port_name, sci, an)); + m_state_macsec_egress_sa.del(swss::join('|', port_name, sci, an)); } else { - m_state_macsec_ingress_sa.del(join('|', port_name, sci, an)); + m_state_macsec_ingress_sa.del(swss::join('|', port_name, sci, an)); } SWSS_LOG_NOTICE("MACsec SA %s is deleted.", port_sci_an.c_str()); From abd4068c79bfbd1388069c591acd832e550f4738 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Tue, 19 Jan 2021 20:17:18 +0800 Subject: [PATCH 30/31] Fix test script Signed-off-by: Ze Gan --- tests/test_macsec.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/test_macsec.py b/tests/test_macsec.py index 0fcc317f86..318ab0bc89 100644 --- a/tests/test_macsec.py +++ b/tests/test_macsec.py @@ -6,6 +6,13 @@ import functools import typing import re +import time + + +def to_string(value): + if isinstance(value, bool): + return "true" if value else "false" + return str(value) class Table(object): @@ -19,7 +26,7 @@ def convert_key(self, key: str): def __setitem__(self, key: str, pairs: dict): pairs_str = {} for k, v in pairs.items(): - pairs_str[str(k)] = str(v) + pairs_str[to_string(k)] = to_string(v) key = self.convert_key(key) if self.__getitem__(key) is None: self.db.create_entry(self.table_name, key, pairs_str) @@ -56,7 +63,7 @@ def __setitem__(self, key: str, pairs: typing.Union[dict, list, tuple]): if isinstance(pairs, dict): pairs = pairs.items() for k, v in pairs: - pairs_str.append((str(k), str(v))) + pairs_str.append((to_string(k), to_string(v))) self.table.set(key, pairs_str) def __delitem__(self, key: str): @@ -302,7 +309,7 @@ def create_transmit_sa( "Wrong parameter to MACsec receive SA") self.app_transmit_sa_table[sai] = { "sak": sak, "auth_key": auth_key, - "init_pn": init_pn, "salt": salt} + "next_pn": init_pn, "salt": salt} @macsec_sa() def delete_transmit_sa(self, sai: str): From a035ec4a6b2755c348ab1bd8a57c0a5fca517d5c Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Sun, 24 Jan 2021 23:27:47 +0800 Subject: [PATCH 31/31] Trigger CI Signed-off-by: Ze Gan