Skip to content

Commit 3b128ec

Browse files
Pterosaurjudyjoseph
authored andcommitted
[macsec]: Add MACsec clear CLI support (#11731)
Why I did it To support clear MACsec counters by sonic-clear macsec How I did it Add macsec sub-command in sonic-clear to cache the current macsec stats, and in the show macsec command to check the cache and return the diff with cache file. How to verify it admin@vlab-02:~$ show macsec Ethernet0 MACsec port(Ethernet0) --------------------- ----------- cipher_suite GCM-AES-128 enable true enable_encrypt true enable_protect true enable_replay_protect false replay_window 0 send_sci true --------------------- ----------- MACsec Egress SC (52540067daa70001) ----------- - encoding_an 0 ----------- - MACsec Egress SA (0) ------------------------------------- -------------------------------- auth_key 9DDD4C69220A1FA9B6763F229B75CB6F next_pn 1 sak BA86574D054FCF48B9CD7CF54F21304A salt 000000000000000000000000 ssci 0 SAI_MACSEC_SA_ATTR_CURRENT_XPN 52 SAI_MACSEC_SA_STAT_OCTETS_ENCRYPTED 0 SAI_MACSEC_SA_STAT_OCTETS_PROTECTED 0 SAI_MACSEC_SA_STAT_OUT_PKTS_ENCRYPTED 0 SAI_MACSEC_SA_STAT_OUT_PKTS_PROTECTED 0 ------------------------------------- -------------------------------- MACsec Ingress SC (525400d4fd3f0001) MACsec Ingress SA (0) --------------------------------------- -------------------------------- active true auth_key 9DDD4C69220A1FA9B6763F229B75CB6F lowest_acceptable_pn 1 sak BA86574D054FCF48B9CD7CF54F21304A salt 000000000000000000000000 ssci 0 SAI_MACSEC_SA_ATTR_CURRENT_XPN 56 SAI_MACSEC_SA_STAT_IN_PKTS_DELAYED 0 SAI_MACSEC_SA_STAT_IN_PKTS_INVALID 0 SAI_MACSEC_SA_STAT_IN_PKTS_LATE 0 SAI_MACSEC_SA_STAT_IN_PKTS_NOT_USING_SA 0 SAI_MACSEC_SA_STAT_IN_PKTS_NOT_VALID 0 SAI_MACSEC_SA_STAT_IN_PKTS_OK 0 SAI_MACSEC_SA_STAT_IN_PKTS_UNCHECKED 0 SAI_MACSEC_SA_STAT_IN_PKTS_UNUSED_SA 0 SAI_MACSEC_SA_STAT_OCTETS_ENCRYPTED 0 SAI_MACSEC_SA_STAT_OCTETS_PROTECTED 0 --------------------------------------- -------------------------------- admin@vlab-02:~$ sonic-clear macsec Clear MACsec counters admin@vlab-02:~$ show macsec Ethernet0 MACsec port(Ethernet0) --------------------- ----------- cipher_suite GCM-AES-128 enable true enable_encrypt true enable_protect true enable_replay_protect false replay_window 0 send_sci true --------------------- ----------- MACsec Egress SC (52540067daa70001) ----------- - encoding_an 0 ----------- - MACsec Egress SA (0) ------------------------------------- -------------------------------- auth_key 9DDD4C69220A1FA9B6763F229B75CB6F next_pn 1 sak BA86574D054FCF48B9CD7CF54F21304A salt 000000000000000000000000 ssci 0 SAI_MACSEC_SA_ATTR_CURRENT_XPN 52 SAI_MACSEC_SA_STAT_OCTETS_ENCRYPTED 0 SAI_MACSEC_SA_STAT_OCTETS_PROTECTED 0 SAI_MACSEC_SA_STAT_OUT_PKTS_ENCRYPTED 0 SAI_MACSEC_SA_STAT_OUT_PKTS_PROTECTED 0 ------------------------------------- -------------------------------- MACsec Ingress SC (525400d4fd3f0001) MACsec Ingress SA (0) --------------------------------------- -------------------------------- active true auth_key 9DDD4C69220A1FA9B6763F229B75CB6F lowest_acceptable_pn 1 sak BA86574D054FCF48B9CD7CF54F21304A salt 000000000000000000000000 ssci 0 SAI_MACSEC_SA_ATTR_CURRENT_XPN 0 <---this counters was cleared. SAI_MACSEC_SA_STAT_IN_PKTS_DELAYED 0 SAI_MACSEC_SA_STAT_IN_PKTS_INVALID 0 SAI_MACSEC_SA_STAT_IN_PKTS_LATE 0 SAI_MACSEC_SA_STAT_IN_PKTS_NOT_USING_SA 0 SAI_MACSEC_SA_STAT_IN_PKTS_NOT_VALID 0 SAI_MACSEC_SA_STAT_IN_PKTS_OK 0 SAI_MACSEC_SA_STAT_IN_PKTS_UNCHECKED 0 SAI_MACSEC_SA_STAT_IN_PKTS_UNUSED_SA 0 SAI_MACSEC_SA_STAT_OCTETS_ENCRYPTED 0 SAI_MACSEC_SA_STAT_OCTETS_PROTECTED 0 --------------------------------------- -------------------------------- Signed-off-by: Ze Gan <[email protected]> Co-authored-by: Judy Joseph <[email protected]>
1 parent 8431d3a commit 3b128ec

File tree

3 files changed

+94
-15
lines changed

3 files changed

+94
-15
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import os
2+
import click
3+
4+
import show.plugins.macsec as show_macsec
5+
import utilities_common.cli as clicommon
6+
from sonic_py_common import multi_asic
7+
8+
@click.group(cls=clicommon.AliasedGroup)
9+
def macsec():
10+
pass
11+
12+
13+
@macsec.command('macsec')
14+
@click.option('--clean-cache', type=bool, required=False, default=False, help="If the option of clean cache is true, next show commands will show the raw counters which based on the service booted instead of the last clear command.")
15+
def macsec_clear_counters(clean_cache):
16+
"""
17+
Clear MACsec counts.
18+
This clear command will generated a cache for next show commands which will base on this cache as the zero baseline to show the increment of counters.
19+
"""
20+
21+
if clean_cache:
22+
for namespace in multi_asic.get_namespace_list():
23+
if os.path.isfile(show_macsec.CACHE_FILE.format(namespace)):
24+
os.remove(show_macsec.CACHE_FILE.format(namespace))
25+
print("Cleaned cache")
26+
return
27+
28+
clicommon.run_command("show macsec --dump-file")
29+
print("Clear MACsec counters")
30+
31+
def register(cli):
32+
cli.add_command(macsec_clear_counters)
33+
34+
35+
if __name__ == '__main__':
36+
macsec_clear_counters(None)

dockers/docker-macsec/cli/show/plugins/show_macsec.py

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
import typing
22
from natsort import natsorted
3+
import datetime
4+
import pickle
5+
import os
6+
import copy
37

48
import click
59
from tabulate import tabulate
610

711
import utilities_common.multi_asic as multi_asic_util
812
from swsscommon.swsscommon import CounterTable, MacsecCounter
13+
from utilities_common.cli import UserCache
914

15+
CACHE_MANAGER = UserCache(app_name="macsec")
16+
CACHE_FILE = os.path.join(CACHE_MANAGER.get_directory(), "macsecstats{}")
1017

1118
DB_CONNECTOR = None
1219
COUNTER_TABLE = None
@@ -15,12 +22,12 @@
1522
class MACsecAppMeta(object):
1623
def __init__(self, *args) -> None:
1724
SEPARATOR = DB_CONNECTOR.get_db_separator(DB_CONNECTOR.APPL_DB)
18-
key = self.__class__.get_appl_table_name() + SEPARATOR + \
25+
self.key = self.__class__.get_appl_table_name() + SEPARATOR + \
1926
SEPARATOR.join(args)
2027
self.meta = DB_CONNECTOR.get_all(
21-
DB_CONNECTOR.APPL_DB, key)
28+
DB_CONNECTOR.APPL_DB, self.key)
2229
if len(self.meta) == 0:
23-
raise ValueError("No such MACsecAppMeta: {}".format(key))
30+
raise ValueError("No such MACsecAppMeta: {}".format(self.key))
2431
for k, v in self.meta.items():
2532
setattr(self, k, v)
2633

@@ -39,10 +46,15 @@ def __init__(self, port_name: str, sci: str, an: str) -> None:
3946
MACsecAppMeta.__init__(self, port_name, sci, an)
4047
MACsecCounters.__init__(self, port_name, sci, an)
4148

42-
def dump_str(self) -> str:
49+
def dump_str(self, cache = None) -> str:
4350
buffer = self.get_header()
4451
meta = sorted(self.meta.items(), key=lambda x: x[0])
45-
counters = sorted(self.counters.items(), key=lambda x: x[0])
52+
counters = copy.deepcopy(self.counters)
53+
if cache:
54+
for k, v in counters.items():
55+
if k in cache.counters:
56+
counters[k] = int(counters[k]) - int(cache.counters[k])
57+
counters = sorted(counters.items(), key=lambda x: x[0])
4658
buffer += tabulate(meta + counters)
4759
buffer = "\n".join(["\t\t" + line for line in buffer.splitlines()])
4860
return buffer
@@ -87,7 +99,7 @@ def __init__(self, port_name: str, sci: str) -> None:
8799
def get_appl_table_name(cls) -> str:
88100
return "MACSEC_INGRESS_SC_TABLE"
89101

90-
def dump_str(self) -> str:
102+
def dump_str(self, cache = None) -> str:
91103
buffer = self.get_header()
92104
buffer = "\n".join(["\t" + line for line in buffer.splitlines()])
93105
return buffer
@@ -104,7 +116,7 @@ def __init__(self, port_name: str, sci: str) -> None:
104116
def get_appl_table_name(cls) -> str:
105117
return "MACSEC_EGRESS_SC_TABLE"
106118

107-
def dump_str(self) -> str:
119+
def dump_str(self, cache = None) -> str:
108120
buffer = self.get_header()
109121
buffer += tabulate(sorted(self.meta.items(), key=lambda x: x[0]))
110122
buffer = "\n".join(["\t" + line for line in buffer.splitlines()])
@@ -123,7 +135,7 @@ def __init__(self, port_name: str) -> None:
123135
def get_appl_table_name(cls) -> str:
124136
return "MACSEC_PORT_TABLE"
125137

126-
def dump_str(self) -> str:
138+
def dump_str(self, cache = None) -> str:
127139
buffer = self.get_header()
128140
buffer += tabulate(sorted(self.meta.items(), key=lambda x: x[0]))
129141
return buffer
@@ -149,6 +161,7 @@ def create_macsec_obj(key: str) -> MACsecAppMeta:
149161
except ValueError as e:
150162
return None
151163

164+
152165
def create_macsec_objs(interface_name: str) -> typing.List[MACsecAppMeta]:
153166
objs = []
154167
objs.append(create_macsec_obj(MACsecPort.get_appl_table_name() + ":" + interface_name))
@@ -179,12 +192,25 @@ def create_macsec_objs(interface_name: str) -> typing.List[MACsecAppMeta]:
179192
return objs
180193

181194

195+
def cache_find(cache: dict, target: MACsecAppMeta) -> MACsecAppMeta:
196+
if not cache or not cache["objs"]:
197+
return None
198+
for obj in cache["objs"]:
199+
if type(obj) == type(target) and obj.key == target.key:
200+
# MACsec SA may be refreshed by a cycle that use the same key
201+
# So, use the SA as the identifier
202+
if isinstance(obj, MACsecSA) and obj.sak != target.sak:
203+
continue
204+
return obj
205+
return None
206+
207+
182208
@click.command()
183209
@click.argument('interface_name', required=False)
210+
@click.option('--dump-file', is_flag=True, required=False, default=False)
184211
@multi_asic_util.multi_asic_click_options
185-
def macsec(interface_name, namespace, display):
186-
MacsecContext(namespace, display).show(interface_name)
187-
212+
def macsec(interface_name, dump_file, namespace, display):
213+
MacsecContext(namespace, display).show(interface_name, dump_file)
188214

189215
class MacsecContext(object):
190216

@@ -194,7 +220,7 @@ def __init__(self, namespace_option, display_option):
194220
display_option, namespace_option)
195221

196222
@multi_asic_util.run_on_multi_asic
197-
def show(self, interface_name):
223+
def show(self, interface_name, dump_file):
198224
global DB_CONNECTOR
199225
global COUNTER_TABLE
200226
DB_CONNECTOR = self.db
@@ -205,13 +231,29 @@ def show(self, interface_name):
205231
if interface_name not in interface_names:
206232
return
207233
interface_names = [interface_name]
208-
209234
objs = []
235+
210236
for interface_name in natsorted(interface_names):
211237
objs += create_macsec_objs(interface_name)
212-
for obj in objs:
213-
print(obj.dump_str())
214238

239+
cache = {}
240+
if os.path.isfile(CACHE_FILE.format(self.multi_asic.current_namespace)):
241+
cache = pickle.load(open(CACHE_FILE.format(self.multi_asic.current_namespace), "rb"))
242+
243+
if not dump_file:
244+
if cache and cache["time"] and objs:
245+
print("Last cached time was {}".format(cache["time"]))
246+
for obj in objs:
247+
cache_obj = cache_find(cache, obj)
248+
print(obj.dump_str(cache_obj))
249+
else:
250+
dump_obj = {
251+
"time": datetime.datetime.now(),
252+
"objs": objs
253+
}
254+
with open(CACHE_FILE.format(self.multi_asic.current_namespace), 'wb') as dump_file:
255+
pickle.dump(dump_obj, dump_file)
256+
dump_file.flush()
215257

216258
def register(cli):
217259
cli.add_command(macsec)

rules/docker-macsec.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,6 @@ $(DOCKER_MACSEC)_RUN_OPT += -v /host/warmboot:/var/warmboot
4444

4545
$(DOCKER_MACSEC)_CLI_CONFIG_PLUGIN = /cli/config/plugins/macsec.py
4646
$(DOCKER_MACSEC)_CLI_SHOW_PLUGIN = /cli/show/plugins/show_macsec.py
47+
$(DOCKER_MACSEC)_CLI_CLEAR_PLUGIN = /cli/clear/plugins/clear_macsec_counter.py
4748

4849
$(DOCKER_MACSEC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)

0 commit comments

Comments
 (0)