Skip to content

Commit c0838d7

Browse files
CLI for Configuring PFC Historical Statistics (#3779)
* Add pfc stat history options to PFCWD CLI * Unit tests for PFCWD pfc history cli Includes modifications made to pass pre-commit (fixing import *). * Add pfc-stat-history command and flag for PFCWD to docs
1 parent d623c25 commit c0838d7

File tree

8 files changed

+596
-160
lines changed

8 files changed

+596
-160
lines changed

config/main.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3125,10 +3125,11 @@ def pfcwd():
31253125
@pfcwd.command()
31263126
@click.option('--action', '-a', type=click.Choice(['drop', 'forward', 'alert']))
31273127
@click.option('--restoration-time', '-r', type=click.IntRange(100, 60000))
3128+
@click.option('--pfc-stat-history', is_flag=True, help="Enable historical statistics tracking")
31283129
@click.option('--verbose', is_flag=True, help="Enable verbose output")
31293130
@click.argument('ports', nargs=-1)
31303131
@click.argument('detection-time', type=click.IntRange(100, 5000))
3131-
def start(action, restoration_time, ports, detection_time, verbose):
3132+
def start(action, restoration_time, pfc_stat_history, ports, detection_time, verbose):
31323133
"""
31333134
Start PFC watchdog on port(s). To config all ports, use all as input.
31343135
@@ -3150,6 +3151,9 @@ def start(action, restoration_time, ports, detection_time, verbose):
31503151
if restoration_time:
31513152
cmd += ['--restoration-time', str(restoration_time)]
31523153

3154+
if pfc_stat_history:
3155+
cmd += ['--pfc-stat-history']
3156+
31533157
clicommon.run_command(cmd, display_cmd=verbose)
31543158

31553159
@pfcwd.command()
@@ -3191,6 +3195,21 @@ def big_red_switch(big_red_switch, verbose):
31913195

31923196
clicommon.run_command(cmd, display_cmd=verbose)
31933197

3198+
3199+
@pfcwd.command('pfc_stat_history')
3200+
@click.option('--verbose', is_flag=True, help="Enable verbose output")
3201+
@click.argument('pfc_stat_history', type=click.Choice(['enable', 'disable']))
3202+
@click.argument('ports', nargs=-1)
3203+
def pfc_stat_history(ports, pfc_stat_history, verbose):
3204+
""" Enable/disable PFC Historical Statistics mode on ports"""
3205+
3206+
cmd = ['pfcwd', 'pfc_stat_history', pfc_stat_history]
3207+
ports = set(ports) - set(['ports'])
3208+
cmd += list(ports)
3209+
3210+
clicommon.run_command(cmd, display_cmd=verbose)
3211+
3212+
31943213
@pfcwd.command('start_default')
31953214
@click.option('--verbose', is_flag=True, help="Enable verbose output")
31963215
def start_default(verbose):

doc/Command-Reference.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8663,6 +8663,7 @@ This command starts PFC Watchdog
86638663
```
86648664
config pfcwd start --action drop all 400 --restoration-time 400
86658665
config pfcwd start --action forward Ethernet0 Ethernet8 400
8666+
config pfcwd start --action drop all 400 --restoration-time 400 --pfc-stat-history
86668667
```
86678668

86688669
**config pfcwd stop**
@@ -8701,6 +8702,18 @@ This command enables or disables PFCWD's "BIG RED SWITCH"(BRS). After enabling B
87018702
config pfcwd big_red_switch enable
87028703
```
87038704

8705+
**config pfcwd pfc_stat_history \<enable/disable\> \<ports>**
8706+
8707+
This command enables or disables PFCWD's PFC Historical Statistics estimation. After enabling, PFC Watchdog will be configured to estimate pause transitions, total pause time, and the pause time and timstamp of the most recent pause activity on those ports.
8708+
8709+
NOTE: The estimation will only be performed on ports the PFCWD has been started on, alternatively use the --pfc-stat-history flag with the `start` command to simultaneously enable history on those ports.
8710+
8711+
- Usage:
8712+
```
8713+
config pfcwd pfc_stat_history enable all
8714+
config pfcwd pfc_stat_history disable Ethernet0 Ethernet8
8715+
```
8716+
87048717
**config pfcwd start_default**
87058718

87068719
This command starts PFC Watchdog with the default settings.
@@ -8716,6 +8729,7 @@ Default values are the following:
87168729
- restoration time - 200ms
87178730
- polling interval - 200ms
87188731
- action - 'drop'
8732+
- pfc stat history - disable
87198733

87208734
Additionally if number of ports in the system exceeds 32, all times will be multiplied by roughly <num_ports\>/32.
87218735

pfcwd/main.py

Lines changed: 74 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
DEFAULT_POLL_INTERVAL = 200
3939
DEFAULT_PORT_NUM = 32
4040
DEFAULT_ACTION = 'drop'
41+
DEFAULT_PFC_HISTORY_STATUS = "disable"
4142

4243
STATS_DESCRIPTION = [
4344
('STORM DETECTED/RESTORED', 'PFC_WD_QUEUE_STATS_DEADLOCK_DETECTED', 'PFC_WD_QUEUE_STATS_DEADLOCK_RESTORED'),
@@ -50,7 +51,8 @@
5051
CONFIG_DESCRIPTION = [
5152
('ACTION', 'action', 'drop'),
5253
('DETECTION TIME', 'detection_time', 'N/A'),
53-
('RESTORATION TIME', 'restoration_time', 'infinite')
54+
('RESTORATION TIME', 'restoration_time', 'infinite'),
55+
('HISTORY', 'pfc_stat_history', 'disable')
5456
]
5557

5658
STATS_HEADER = ('QUEUE', 'STATUS',) + list(zip(*STATS_DESCRIPTION))[0]
@@ -248,34 +250,47 @@ def config(self, ports):
248250
tablefmt='simple'
249251
))
250252

251-
def start(self, action, restoration_time, ports, detection_time):
253+
def start(self, action, restoration_time, ports, detection_time, pfc_stat_history):
252254
invalid_ports = self.get_invalid_ports(ports)
253255
if len(invalid_ports):
254256
click.echo("Failed to run command, invalid options:")
255257
for opt in invalid_ports:
256258
click.echo(opt)
257259
sys.exit(1)
258-
self.start_cmd(action, restoration_time, ports, detection_time)
260+
self.start_cmd(action, restoration_time, ports, detection_time, pfc_stat_history)
259261

262+
def pfc_stat_history(self, pfc_stat_history, ports):
263+
invalid_ports = self.get_invalid_ports(ports)
264+
if len(invalid_ports):
265+
click.echo("Failed to run command, invalid options:")
266+
for opt in invalid_ports:
267+
click.echo(opt)
268+
sys.exit(1)
269+
self.pfc_stat_history_cmd(pfc_stat_history, ports)
260270

261-
def verify_pfc_enable_status_per_port(self, port, pfcwd_info):
271+
def verify_pfc_enable_status_per_port(self, port, pfcwd_info, overwrite=True):
262272
pfc_status = self.config_db.get_entry(PORT_QOS_MAP, port).get('pfc_enable')
263273
if pfc_status is None:
264274
log.log_warning("SKIPPED: PFC is not enabled on port: {}".format(port), also_print_to_console=True)
265275
return
266276

267-
self.config_db.mod_entry(
268-
CONFIG_DB_PFC_WD_TABLE_NAME, port, None
269-
)
270-
self.config_db.mod_entry(
271-
CONFIG_DB_PFC_WD_TABLE_NAME, port, pfcwd_info
272-
)
277+
if overwrite:
278+
# don't clear existing pfc history setting unless set explicitely
279+
cur_pfc_history = self.config_db.get_entry(
280+
CONFIG_DB_PFC_WD_TABLE_NAME, port
281+
).get("pfc_stat_history", DEFAULT_PFC_HISTORY_STATUS)
273282

274-
@multi_asic_util.run_on_multi_asic
275-
def start_cmd(self, action, restoration_time, ports, detection_time):
276-
if os.geteuid() != 0:
277-
sys.exit("Root privileges are required for this operation")
283+
pfcwd_info.setdefault("pfc_stat_history", cur_pfc_history)
278284

285+
self.config_db.set_entry(
286+
CONFIG_DB_PFC_WD_TABLE_NAME, port, pfcwd_info
287+
)
288+
else:
289+
self.config_db.mod_entry(
290+
CONFIG_DB_PFC_WD_TABLE_NAME, port, pfcwd_info
291+
)
292+
293+
def configure_ports(self, ports, pfcwd_info, overwrite=True):
279294
all_ports = get_all_ports(
280295
self.db, self.multi_asic.current_namespace,
281296
self.multi_asic.display_option
@@ -284,6 +299,20 @@ def start_cmd(self, action, restoration_time, ports, detection_time):
284299
if len(ports) == 0:
285300
ports = all_ports
286301

302+
for port in ports:
303+
if port == "all":
304+
for p in all_ports:
305+
self.verify_pfc_enable_status_per_port(p, pfcwd_info, overwrite)
306+
else:
307+
if port not in all_ports:
308+
continue
309+
self.verify_pfc_enable_status_per_port(port, pfcwd_info, overwrite)
310+
311+
@multi_asic_util.run_on_multi_asic
312+
def start_cmd(self, action, restoration_time, ports, detection_time, pfc_stat_history):
313+
if os.geteuid() != 0:
314+
sys.exit("Root privileges are required for this operation")
315+
287316
pfcwd_info = {
288317
'detection_time': detection_time,
289318
}
@@ -297,15 +326,10 @@ def start_cmd(self, action, restoration_time, ports, detection_time):
297326
"restoration time not defined; default to 2 times "
298327
"detection time: {} ms".format(2 * detection_time)
299328
)
329+
if pfc_stat_history:
330+
pfcwd_info["pfc_stat_history"] = "enable"
300331

301-
for port in ports:
302-
if port == "all":
303-
for p in all_ports:
304-
self.verify_pfc_enable_status_per_port(p, pfcwd_info)
305-
else:
306-
if port not in all_ports:
307-
continue
308-
self.verify_pfc_enable_status_per_port(port, pfcwd_info)
332+
self.configure_ports(ports, pfcwd_info, overwrite=True)
309333

310334
@multi_asic_util.run_on_multi_asic
311335
def interval(self, poll_interval):
@@ -391,11 +415,12 @@ def start_default(self):
391415
pfcwd_info = {
392416
'detection_time': DEFAULT_DETECTION_TIME * multiply,
393417
'restoration_time': DEFAULT_RESTORATION_TIME * multiply,
394-
'action': DEFAULT_ACTION
418+
'action': DEFAULT_ACTION,
419+
'pfc_stat_history': DEFAULT_PFC_HISTORY_STATUS
395420
}
396421

397422
for port in active_ports:
398-
self.verify_pfc_enable_status_per_port(port, pfcwd_info)
423+
self.verify_pfc_enable_status_per_port(port, pfcwd_info, overwrite=True)
399424

400425
pfcwd_info = {}
401426
pfcwd_info['POLL_INTERVAL'] = DEFAULT_POLL_INTERVAL * multiply
@@ -423,6 +448,15 @@ def big_red_switch(self, big_red_switch):
423448
pfcwd_info
424449
)
425450

451+
@multi_asic_util.run_on_multi_asic
452+
def pfc_stat_history_cmd(self, pfc_stat_history, ports):
453+
if os.geteuid() != 0:
454+
sys.exit("Root privileges are required for this operation")
455+
456+
pfcwd_info = {
457+
'pfc_stat_history': pfc_stat_history
458+
}
459+
self.configure_ports(ports, pfcwd_info, overwrite=False)
426460

427461
# Show stats
428462
class Show(object):
@@ -459,20 +493,21 @@ class Start(object):
459493
'--action', '-a', type=click.Choice(['drop', 'forward', 'alert'])
460494
)
461495
@click.option('--restoration-time', '-r', type=click.IntRange(100, 60000))
496+
@click.option('--pfc-stat-history', is_flag=True)
462497
@click.argument('ports', nargs=-1)
463498
@click.argument('detection-time', type=click.IntRange(100, 5000))
464499
@clicommon.pass_db
465-
def start(db, action, restoration_time, ports, detection_time):
500+
def start(db, action, restoration_time, ports, detection_time, pfc_stat_history):
466501
"""
467502
Start PFC watchdog on port(s). To config all ports, use all as input.
468503
469504
Example:
470505
471-
sudo pfcwd start --action drop all 400 --restoration-time 400
506+
sudo pfcwd start --action drop all 400 --restoration-time 400 --pfc-stat-history enable
472507
473508
"""
474509
PfcwdCli(db).start(
475-
action, restoration_time, ports, detection_time
510+
action, restoration_time, ports, detection_time, pfc_stat_history
476511
)
477512

478513

@@ -525,7 +560,19 @@ def big_red_switch(db, big_red_switch):
525560
PfcwdCli(db).big_red_switch(big_red_switch)
526561

527562

563+
# Enable/disable PFC WD PFC_STAT_HISTORY mode
564+
class PfcStatHistory(object):
565+
@cli.command('pfc_stat_history')
566+
@click.argument('pfc_stat_history', type=click.Choice(['enable', 'disable']))
567+
@click.argument('ports', nargs=-1)
568+
@clicommon.pass_db
569+
def pfc_stat_history(db, pfc_stat_history, ports):
570+
""" Enable/disable PFC Historical Statistics mode on ports"""
571+
PfcwdCli(db).pfc_stat_history(pfc_stat_history, ports)
572+
573+
528574
def get_pfcwd_clis():
575+
cli.add_command(PfcStatHistory().pfc_stat_history)
529576
cli.add_command(BigRedSwitch().big_red_switch)
530577
cli.add_command(CounterPoll().counter_poll)
531578
cli.add_command(StartDefault().start_default)

tests/mock_tables/asic0/config_db.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,22 +99,26 @@
9999
"PFC_WD|Ethernet0": {
100100
"action": "drop",
101101
"detection_time": "200",
102-
"restoration_time": "200"
102+
"restoration_time": "200",
103+
"pfc_stat_history": "disable"
103104
},
104105
"PFC_WD|Ethernet4": {
105106
"action": "drop",
106107
"detection_time": "200",
107-
"restoration_time": "200"
108+
"restoration_time": "200",
109+
"pfc_stat_history": "disable"
108110
},
109111
"PFC_WD|Ethernet-BP0": {
110112
"action": "drop",
111113
"detection_time": "200",
112-
"restoration_time": "200"
114+
"restoration_time": "200",
115+
"pfc_stat_history": "disable"
113116
},
114117
"PFC_WD|Ethernet-BP4": {
115118
"action": "drop",
116119
"detection_time": "200",
117-
"restoration_time": "200"
120+
"restoration_time": "200",
121+
"pfc_stat_history": "disable"
118122
},
119123
"PFC_WD|GLOBAL": {
120124
"BIG_RED_SWITCH": "enable",

tests/mock_tables/asic1/config_db.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,14 @@
6666
"PFC_WD|Ethernet-BP256": {
6767
"action": "drop",
6868
"detection_time": "200",
69-
"restoration_time": "200"
69+
"restoration_time": "200",
70+
"pfc_stat_history": "disable"
7071
},
7172
"PFC_WD|Ethernet-BP260": {
7273
"action": "drop",
7374
"detection_time": "200",
74-
"restoration_time": "200"
75+
"restoration_time": "200",
76+
"pfc_stat_history": "disable"
7577
},
7678
"PFC_WD|GLOBAL": {
7779
"BIG_RED_SWITCH": "enable",

tests/mock_tables/config_db.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,17 +1835,20 @@
18351835
"PFC_WD|Ethernet0": {
18361836
"action": "drop",
18371837
"detection_time": "600",
1838-
"restoration_time": "600"
1838+
"restoration_time": "600",
1839+
"pfc_stat_history": "disable"
18391840
},
18401841
"PFC_WD|Ethernet4": {
18411842
"action": "drop",
18421843
"detection_time": "600",
1843-
"restoration_time": "600"
1844+
"restoration_time": "600",
1845+
"pfc_stat_history": "disable"
18441846
},
18451847
"PFC_WD|Ethernet8": {
18461848
"action": "drop",
18471849
"detection_time": "600",
1848-
"restoration_time": "600"
1850+
"restoration_time": "600",
1851+
"pfc_stat_history": "disable"
18491852
},
18501853
"PFC_WD|GLOBAL": {
18511854
"POLL_INTERVAL": "600"

0 commit comments

Comments
 (0)