Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[teammgr]: Waiting MACsec ready before doLagMemberTask #2286

Merged
merged 6 commits into from
Jul 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 59 additions & 2 deletions cfgmgr/teammgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ TeamMgr::TeamMgr(DBConnector *confDb, DBConnector *applDb, DBConnector *statDb,
m_appPortTable(applDb, APP_PORT_TABLE_NAME),
m_appLagTable(applDb, APP_LAG_TABLE_NAME),
m_statePortTable(statDb, STATE_PORT_TABLE_NAME),
m_stateLagTable(statDb, STATE_LAG_TABLE_NAME)
m_stateLagTable(statDb, STATE_LAG_TABLE_NAME),
m_stateMACsecIngressSATable(statDb, STATE_MACSEC_INGRESS_SA_TABLE_NAME)
{
SWSS_LOG_ENTER();

Expand Down Expand Up @@ -98,6 +99,51 @@ bool TeamMgr::isLagStateOk(const string &alias)
return true;
}

bool TeamMgr::isMACsecAttached(const std::string &port)
{
SWSS_LOG_ENTER();

vector<FieldValueTuple> temp;

if (!m_cfgPortTable.get(port, temp))
{
SWSS_LOG_INFO("Port %s is not ready", port.c_str());
return false;
}

auto macsec_opt = swss::fvsGetValue(temp, "macsec", true);
if (!macsec_opt || macsec_opt->empty())
{
SWSS_LOG_INFO("MACsec isn't setted on the port %s", port.c_str());
return false;
}

return true;
}

bool TeamMgr::isMACsecIngressSAOk(const std::string &port)
{
SWSS_LOG_ENTER();

vector<string> keys;
m_stateMACsecIngressSATable.getKeys(keys);

for (auto key: keys)
{
auto tokens = tokenize(key, state_db_key_delimiter);
auto interface = tokens[0];

if (port == interface)
{
SWSS_LOG_NOTICE(" MACsec is ready on the port %s", port.c_str());
return true;
}
}

SWSS_LOG_INFO("MACsec is NOT ready on the port %s", port.c_str());
return false;
}

void TeamMgr::doTask(Consumer &consumer)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -309,7 +355,11 @@ void TeamMgr::doLagMemberTask(Consumer &consumer)
it++;
continue;
}

if (isMACsecAttached(member) && !isMACsecIngressSAOk(member))
{
it++;
continue;
}
if (addLagMember(lag, member) == task_need_retry)
{
it++;
Expand Down Expand Up @@ -400,6 +450,13 @@ void TeamMgr::doPortUpdateTask(Consumer &consumer)
string lag;
if (findPortMaster(lag, alias))
{
if (isMACsecAttached(alias) && !isMACsecIngressSAOk(alias))
{
it++;
SWSS_LOG_INFO("MACsec is NOT ready on the port %s", alias.c_str());
continue;
}

if (addLagMember(lag, alias) == task_need_retry)
{
it++;
Expand Down
3 changes: 3 additions & 0 deletions cfgmgr/teammgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class TeamMgr : public Orch
Table m_cfgLagMemberTable;
Table m_statePortTable;
Table m_stateLagTable;
Table m_stateMACsecIngressSATable;

ProducerStateTable m_appPortTable;
ProducerStateTable m_appLagTable;
Expand Down Expand Up @@ -55,6 +56,8 @@ class TeamMgr : public Orch
bool checkPortIffUp(const std::string &);
bool isPortStateOk(const std::string&);
bool isLagStateOk(const std::string&);
bool isMACsecAttached(const std::string &);
bool isMACsecIngressSAOk(const std::string &);
uint16_t generateLacpKey(const std::string&);
};

Expand Down
88 changes: 88 additions & 0 deletions tests/test_macsec.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from swsscommon import swsscommon
import conftest

import time
import functools
import typing
import re
Expand Down Expand Up @@ -87,6 +88,12 @@ def convert_key(self, key: str):
StateDBTable.SEPARATOR))


class ConfigTable(Table):

def __init__(self, dvs: conftest.DockerVirtualSwitch, table_name: str):
super(ConfigTable, self).__init__(dvs.get_config_db(), table_name)


def gen_sci(macsec_system_identifier: str, macsec_port_identifier: int) -> str:
macsec_system_identifier = macsec_system_identifier.translate(
str.maketrans("", "", ":.-"))
Expand Down Expand Up @@ -755,6 +762,87 @@ def test_macsec_attribute_change(self, dvs: conftest.DockerVirtualSwitch, testlo
macsec_port_identifier,
0)

def test_macsec_with_portchannel(self, dvs: conftest.DockerVirtualSwitch, testlog):

# Set MACsec enabled on Ethernet0
ConfigTable(dvs, "PORT")["Ethernet0"] = {"macsec" : "test"}
StateDBTable(dvs, "FEATURE")["macsec"] = {"state": "enabled"}

# Setup Port-channel
ConfigTable(dvs, "PORTCHANNEL")["PortChannel001"] = {"admin": "up", "mtu": "9100", "oper_status": "up"}
time.sleep(1)

# create port channel member
ConfigTable(dvs, "PORTCHANNEL_MEMBER")["PortChannel001|Ethernet0"] = {"NULL": "NULL"}
ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001"] = {"NULL": "NULL"}
ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001|40.0.0.0/31"] = {"NULL": "NULL"}
time.sleep(3)

# Check Portchannel member in ASIC db that shouldn't been created before MACsec enabled
lagmtbl = swsscommon.Table(swsscommon.DBConnector(1, dvs.redis_sock, 0), "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER")
lagms = lagmtbl.getKeys()
assert len(lagms) == 0

# Create MACsec session
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)
self.establish_macsec(
wpa,
port_name,
local_mac_address,
peer_mac_address,
macsec_port_identifier,
0,
sak,
packet_number,
auth_key,
ssci,
salt)
time.sleep(3)

# Check Portchannel member in ASIC db that should been created after MACsec enabled
lagmtbl = swsscommon.Table(swsscommon.DBConnector(1, dvs.redis_sock, 0), "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER")
lagms = lagmtbl.getKeys()
assert len(lagms) == 1

self.deinit_macsec(
wpa,
inspector,
port_name,
macsec_port,
local_mac_address,
peer_mac_address,
macsec_port_identifier,
0)

# remove port channel member
del ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001"]
del ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001|40.0.0.0/31"]
del ConfigTable(dvs, "PORTCHANNEL_MEMBER")["PortChannel001|Ethernet0"]

# remove port channel
del ConfigTable(dvs, "PORTCHANNEL")["PortChannel001"]

# Clear MACsec enabled on Ethernet0
ConfigTable(dvs, "PORT")["Ethernet0"] = {"macsec" : ""}


# Add Dummy always-pass test at end as workaroud
# for issue when Flaky fail on final test it invokes module tear-down
Expand Down