Skip to content

Commit d621542

Browse files
authored
[teammgr]: Waiting MACsec ready before doLagMemberTask (#2286)
Signed-off-by: Ze Gan ganze718@gmail.com, Judy Joseph jujoseph@microsoft.com What I did If a member of portchannel has macsec profile attached in config, enable MACsec on the port before it's been added as a member of portchannel. Why I did it Due to some hardware limitation, cannot enable MACsec on a member of portchannel. So we enable the macsec on interface first and then add it as part of portchannel. Note: This is a work around which will be removed when h/w supports it future releases. The approach taken in this PR is In the teamdMgr when an interface is added as part of the LAG, we wait for the macsecPort creation done in SAI and Ingress SA creation complete (if macsec is enabled on the interface) The above takes care of config reload, reboot scenario's where we cannot guarantee the sequence of macsec attach to interface, add interface as part of portchannel. If we do a manual removal of port from portchannel, or remove macsec config from the interface, Please follow this steps First remove the portchannel member out of portchannel Remove the macsec profile attached to interface. How I verified it Verified with config reload, reboot with the macsec profile attached to portchannel member interfaces. Verified case when SAK rekey is enabled on macsec on portchannel members Verified case when member interface link flaps
1 parent a8e238a commit d621542

File tree

3 files changed

+150
-2
lines changed

3 files changed

+150
-2
lines changed

cfgmgr/teammgr.cpp

+59-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ TeamMgr::TeamMgr(DBConnector *confDb, DBConnector *applDb, DBConnector *statDb,
3333
m_appPortTable(applDb, APP_PORT_TABLE_NAME),
3434
m_appLagTable(applDb, APP_LAG_TABLE_NAME),
3535
m_statePortTable(statDb, STATE_PORT_TABLE_NAME),
36-
m_stateLagTable(statDb, STATE_LAG_TABLE_NAME)
36+
m_stateLagTable(statDb, STATE_LAG_TABLE_NAME),
37+
m_stateMACsecIngressSATable(statDb, STATE_MACSEC_INGRESS_SA_TABLE_NAME)
3738
{
3839
SWSS_LOG_ENTER();
3940

@@ -98,6 +99,51 @@ bool TeamMgr::isLagStateOk(const string &alias)
9899
return true;
99100
}
100101

102+
bool TeamMgr::isMACsecAttached(const std::string &port)
103+
{
104+
SWSS_LOG_ENTER();
105+
106+
vector<FieldValueTuple> temp;
107+
108+
if (!m_cfgPortTable.get(port, temp))
109+
{
110+
SWSS_LOG_INFO("Port %s is not ready", port.c_str());
111+
return false;
112+
}
113+
114+
auto macsec_opt = swss::fvsGetValue(temp, "macsec", true);
115+
if (!macsec_opt || macsec_opt->empty())
116+
{
117+
SWSS_LOG_INFO("MACsec isn't setted on the port %s", port.c_str());
118+
return false;
119+
}
120+
121+
return true;
122+
}
123+
124+
bool TeamMgr::isMACsecIngressSAOk(const std::string &port)
125+
{
126+
SWSS_LOG_ENTER();
127+
128+
vector<string> keys;
129+
m_stateMACsecIngressSATable.getKeys(keys);
130+
131+
for (auto key: keys)
132+
{
133+
auto tokens = tokenize(key, state_db_key_delimiter);
134+
auto interface = tokens[0];
135+
136+
if (port == interface)
137+
{
138+
SWSS_LOG_NOTICE(" MACsec is ready on the port %s", port.c_str());
139+
return true;
140+
}
141+
}
142+
143+
SWSS_LOG_INFO("MACsec is NOT ready on the port %s", port.c_str());
144+
return false;
145+
}
146+
101147
void TeamMgr::doTask(Consumer &consumer)
102148
{
103149
SWSS_LOG_ENTER();
@@ -309,7 +355,11 @@ void TeamMgr::doLagMemberTask(Consumer &consumer)
309355
it++;
310356
continue;
311357
}
312-
358+
if (isMACsecAttached(member) && !isMACsecIngressSAOk(member))
359+
{
360+
it++;
361+
continue;
362+
}
313363
if (addLagMember(lag, member) == task_need_retry)
314364
{
315365
it++;
@@ -400,6 +450,13 @@ void TeamMgr::doPortUpdateTask(Consumer &consumer)
400450
string lag;
401451
if (findPortMaster(lag, alias))
402452
{
453+
if (isMACsecAttached(alias) && !isMACsecIngressSAOk(alias))
454+
{
455+
it++;
456+
SWSS_LOG_INFO("MACsec is NOT ready on the port %s", alias.c_str());
457+
continue;
458+
}
459+
403460
if (addLagMember(lag, alias) == task_need_retry)
404461
{
405462
it++;

cfgmgr/teammgr.h

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class TeamMgr : public Orch
2727
Table m_cfgLagMemberTable;
2828
Table m_statePortTable;
2929
Table m_stateLagTable;
30+
Table m_stateMACsecIngressSATable;
3031

3132
ProducerStateTable m_appPortTable;
3233
ProducerStateTable m_appLagTable;
@@ -55,6 +56,8 @@ class TeamMgr : public Orch
5556
bool checkPortIffUp(const std::string &);
5657
bool isPortStateOk(const std::string&);
5758
bool isLagStateOk(const std::string&);
59+
bool isMACsecAttached(const std::string &);
60+
bool isMACsecIngressSAOk(const std::string &);
5861
uint16_t generateLacpKey(const std::string&);
5962
};
6063

tests/test_macsec.py

+88
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from swsscommon.swsscommon import CounterTable, MacsecCounter
33
import conftest
44

5+
import time
56
import functools
67
import typing
78
import re
@@ -89,6 +90,12 @@ def convert_key(self, key: str):
8990
StateDBTable.SEPARATOR))
9091

9192

93+
class ConfigTable(Table):
94+
95+
def __init__(self, dvs: conftest.DockerVirtualSwitch, table_name: str):
96+
super(ConfigTable, self).__init__(dvs.get_config_db(), table_name)
97+
98+
9299
def gen_sci(macsec_system_identifier: str, macsec_port_identifier: int) -> str:
93100
macsec_system_identifier = macsec_system_identifier.translate(
94101
str.maketrans("", "", ":.-"))
@@ -808,6 +815,87 @@ def test_macsec_attribute_change(self, dvs: conftest.DockerVirtualSwitch, testlo
808815
macsec_port_identifier,
809816
0)
810817

818+
def test_macsec_with_portchannel(self, dvs: conftest.DockerVirtualSwitch, testlog):
819+
820+
# Set MACsec enabled on Ethernet0
821+
ConfigTable(dvs, "PORT")["Ethernet0"] = {"macsec" : "test"}
822+
StateDBTable(dvs, "FEATURE")["macsec"] = {"state": "enabled"}
823+
824+
# Setup Port-channel
825+
ConfigTable(dvs, "PORTCHANNEL")["PortChannel001"] = {"admin": "up", "mtu": "9100", "oper_status": "up"}
826+
time.sleep(1)
827+
828+
# create port channel member
829+
ConfigTable(dvs, "PORTCHANNEL_MEMBER")["PortChannel001|Ethernet0"] = {"NULL": "NULL"}
830+
ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001"] = {"NULL": "NULL"}
831+
ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001|40.0.0.0/31"] = {"NULL": "NULL"}
832+
time.sleep(3)
833+
834+
# Check Portchannel member in ASIC db that shouldn't been created before MACsec enabled
835+
lagmtbl = swsscommon.Table(swsscommon.DBConnector(1, dvs.redis_sock, 0), "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER")
836+
lagms = lagmtbl.getKeys()
837+
assert len(lagms) == 0
838+
839+
# Create MACsec session
840+
port_name = "Ethernet0"
841+
local_mac_address = "00-15-5D-78-FF-C1"
842+
peer_mac_address = "00-15-5D-78-FF-C2"
843+
macsec_port_identifier = 1
844+
macsec_port = "macsec_eth1"
845+
sak = "0" * 32
846+
auth_key = "0" * 32
847+
packet_number = 1
848+
ssci = 1
849+
salt = "0" * 24
850+
851+
wpa = WPASupplicantMock(dvs)
852+
inspector = MACsecInspector(dvs)
853+
854+
self.init_macsec(
855+
wpa,
856+
port_name,
857+
local_mac_address,
858+
macsec_port_identifier)
859+
self.establish_macsec(
860+
wpa,
861+
port_name,
862+
local_mac_address,
863+
peer_mac_address,
864+
macsec_port_identifier,
865+
0,
866+
sak,
867+
packet_number,
868+
auth_key,
869+
ssci,
870+
salt)
871+
time.sleep(3)
872+
873+
# Check Portchannel member in ASIC db that should been created after MACsec enabled
874+
lagmtbl = swsscommon.Table(swsscommon.DBConnector(1, dvs.redis_sock, 0), "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER")
875+
lagms = lagmtbl.getKeys()
876+
assert len(lagms) == 1
877+
878+
self.deinit_macsec(
879+
wpa,
880+
inspector,
881+
port_name,
882+
macsec_port,
883+
local_mac_address,
884+
peer_mac_address,
885+
macsec_port_identifier,
886+
0)
887+
888+
# remove port channel member
889+
del ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001"]
890+
del ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001|40.0.0.0/31"]
891+
del ConfigTable(dvs, "PORTCHANNEL_MEMBER")["PortChannel001|Ethernet0"]
892+
893+
# remove port channel
894+
del ConfigTable(dvs, "PORTCHANNEL")["PortChannel001"]
895+
896+
# Clear MACsec enabled on Ethernet0
897+
ConfigTable(dvs, "PORT")["Ethernet0"] = {"macsec" : ""}
898+
811899

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

0 commit comments

Comments
 (0)