Skip to content

Commit

Permalink
sonic-utilities: WRED stats feature changes on sonic-utilities
Browse files Browse the repository at this point in the history
* New script for wredstat CLI commands
* portstat script updated to accomodate WRED port stats
* counterpoll script updated to support wredport and wredqueue counters
* CLi to script mapping changes
* UT for the new script changes

Signed-off-by: rpmarvell <rperumal@marvell.com>
  • Loading branch information
rpmarvell committed May 12, 2023
1 parent 3a9995b commit 6084f23
Show file tree
Hide file tree
Showing 14 changed files with 2,382 additions and 5 deletions.
6 changes: 6 additions & 0 deletions clear/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ def clear_wm_q_all():
command = ['watermarkstat', '-c', '-t', 'q_shared_all']
run_command(command)

@queue.group(name='wredcounters')
def wredcounters():
"""Clear queue wredcounters"""
command = "wredstat -c"
run_command(command)

@queue.group(name='persistent-watermark')
def persistent_watermark():
"""Clear queue persistent WM. One does not simply clear WM, root is required"""
Expand Down
72 changes: 72 additions & 0 deletions counterpoll/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,72 @@ def disable(ctx):
fc_info['FLEX_COUNTER_STATUS'] = 'disable'
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", "FLOW_CNT_ROUTE", fc_info)

# WRED queue counter commands
@cli.group()
@click.pass_context
def wredqueue(ctx):
""" WRED queue counter commands """
ctx.obj = ConfigDBConnector()
ctx.obj.connect()

@wredqueue.command()
@click.argument('poll_interval', type=click.IntRange(100, 30000))
@click.pass_context
def interval(ctx, poll_interval):
""" Set wred queue counter query interval """
wred_queue_info = {}
wred_queue_info['POLL_INTERVAL'] = poll_interval
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", "WRED_ECN_QUEUE", wred_queue_info)

@wredqueue.command()
@click.pass_context
def enable(ctx):
""" Enable wred queue counter query """
wred_queue_info = {}
wred_queue_info['FLEX_COUNTER_STATUS'] = 'enable'
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", "WRED_ECN_QUEUE", wred_queue_info)

@wredqueue.command()
@click.pass_context
def disable(ctx):
""" Disable wred queue counter query """
wred_queue_info = {}
wred_queue_info['FLEX_COUNTER_STATUS'] = 'disable'
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", "WRED_ECN_QUEUE", wred_queue_info)

# WRED port counter commands
@cli.group()
@click.pass_context
def wredport(ctx):
""" WRED port counter commands """
ctx.obj = ConfigDBConnector()
ctx.obj.connect()

@wredport.command()
@click.argument('poll_interval', type=click.IntRange(100, 30000))
@click.pass_context
def interval(ctx, poll_interval):
""" Set wred port counter query interval """
wred_port_info = {}
wred_port_info['POLL_INTERVAL'] = poll_interval
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", "WRED_ECN_PORT", wred_port_info)

@wredport.command()
@click.pass_context
def enable(ctx):
""" Enable wred port counter query """
wred_port_info = {}
wred_port_info['FLEX_COUNTER_STATUS'] = 'enable'
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", "WRED_ECN_PORT", wred_port_info)

@wredport.command()
@click.pass_context
def disable(ctx):
""" Disable wred port counter query """
wred_port_info = {}
wred_port_info['FLEX_COUNTER_STATUS'] = 'disable'
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", "WRED_ECN_PORT", wred_port_info)

@cli.command()
def show():
""" Show the counter configuration """
Expand All @@ -399,6 +465,8 @@ def show():
tunnel_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'TUNNEL')
trap_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'FLOW_CNT_TRAP')
route_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'FLOW_CNT_ROUTE')
wred_queue_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'WRED_ECN_QUEUE')
wred_port_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'WRED_ECN_PORT')

header = ("Type", "Interval (in ms)", "Status")
data = []
Expand Down Expand Up @@ -427,6 +495,10 @@ def show():
if route_info:
data.append(["FLOW_CNT_ROUTE_STAT", route_info.get("POLL_INTERVAL", DEFLT_10_SEC),
route_info.get("FLEX_COUNTER_STATUS", DISABLE)])
if wred_queue_info:
data.append(["WRED_ECN_QUEUE_STAT", wred_queue_info.get("POLL_INTERVAL", DEFLT_10_SEC), wred_queue_info.get("FLEX_COUNTER_STATUS", DISABLE)])
if wred_port_info:
data.append(["WRED_ECN_PORT_STAT", wred_port_info.get("POLL_INTERVAL", DEFLT_1_SEC), wred_port_info.get("FLEX_COUNTER_STATUS", DISABLE)])

click.echo(tabulate(data, headers=header, tablefmt="simple", missingval=""))

Expand Down
78 changes: 78 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -7984,6 +7984,7 @@ This sub-section explains the following queue parameters that can be displayed u
2) queue watermark
3) priority-group watermark
4) queue persistent-watermark
5) queue wredcounters
**show queue counters**
Expand Down Expand Up @@ -8177,6 +8178,83 @@ This command displays the user persistet-watermark for the queues (Egress shared
admin@sonic:~$ sonic-clear priority-group drop counters
```
**show queue wredcounters**
This command displays wred-drop packet/byte and ecn-marked packet/byte counters for all queues of all ports or one specific-port given as arguement.
This command can be used to clear the counters for all queues of all ports. Note that port specific clear is not supported.
- Usage:
```
show queue wredcounters [<interface_name>]
```
- Example:
```
admin@sonic:~$ show queue wredcounters
Port TxQ WredDrp/pkts WredDrp/bytes EcnMarked/pkts EcnMarked/bytes
--------- ----- -------------- --------------- --------------- ----------------
Ethernet0 UC0 0 0 0 0
Ethernet0 UC1 0 0 0 0
Ethernet0 UC2 0 0 0 0
Ethernet0 UC3 0 0 0 0
Ethernet0 UC4 0 0 0 0
Ethernet0 UC5 0 0 0 0
Ethernet0 UC6 0 0 0 0
Ethernet0 UC7 0 0 0 0
Ethernet0 UC8 0 0 0 0
Ethernet0 UC9 0 0 0 0
Ethernet0 MC0 0 0 0 0
Ethernet0 MC1 0 0 0 0
Ethernet0 MC2 0 0 0 0
Ethernet0 MC3 0 0 0 0
Ethernet0 MC4 0 0 0 0
Ethernet0 MC5 0 0 0 0
Ethernet0 MC6 0 0 0 0
Ethernet0 MC7 0 0 0 0
Ethernet0 MC8 0 0 0 0
Ethernet0 MC9 0 0 0 0
Port TxQ WredDrp/pkts WredDrp/bytes EcnMarked/pkts EcnMarked/bytes
--------- ----- -------------- --------------- --------------- ----------------
Ethernet4 UC0 0 0 0 0
Ethernet4 UC1 0 0 0 0
Ethernet4 UC2 0 0 0 0
Ethernet4 UC3 0 0 0 0
Ethernet4 UC4 0 0 0 0
Ethernet4 UC5 0 0 0 0
Ethernet4 UC6 0 0 0 0
Ethernet4 UC7 0 0 0 0
Ethernet4 UC8 0 0 0 0
Ethernet4 UC9 0 0 0 0
Ethernet4 MC0 0 0 0 0
Ethernet4 MC1 0 0 0 0
Ethernet4 MC2 0 0 0 0
Ethernet4 MC3 0 0 0 0
Ethernet4 MC4 0 0 0 0
Ethernet4 MC5 0 0 0 0
Ethernet4 MC6 0 0 0 0
Ethernet4 MC7 0 0 0 0
Ethernet4 MC8 0 0 0 0
Ethernet4 MC9 0 0 0 0
...
```
Optionally, you can specify an interface name in order to display only that particular interface
- Example:
```
admin@sonic:~$ show queue wredcounters Ethernet72
```
- NOTE: Queue counters can be cleared by the user with the following command:
```
admin@sonic:~$ sonic-clear queue wredcounters
```
#### Buffer Pool
This sub-section explains the following buffer pool parameters that can be displayed using "show buffer_pool" command.
Expand Down
65 changes: 62 additions & 3 deletions scripts/portstat
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ NStats = namedtuple("NStats", "rx_ok, rx_err, rx_drop, rx_ovr, tx_ok,\
tx_64, tx_65_127, tx_128_255, tx_256_511, tx_512_1023, tx_1024_1518, tx_1519_2047, tx_2048_4095, tx_4096_9216, tx_9217_16383,\
tx_uca, tx_mca, tx_bca, tx_all,\
rx_jbr, rx_frag, rx_usize, rx_ovrrun,\
fec_corr, fec_uncorr, fec_symbol_err")
fec_corr, fec_uncorr, fec_symbol_err,\
wred_grn_drp_pkt, wred_ylw_drp_pkt, wred_red_drp_pkt, wred_tot_drp_pkt")
header_all = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR',
'TX_OK', 'TX_BPS', 'TX_PPS', 'TX_UTIL', 'TX_ERR', 'TX_DRP', 'TX_OVR']
header_std = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR',
Expand All @@ -70,7 +71,14 @@ RateStats = namedtuple("RateStats", ratestat_fields)
The order and count of statistics mentioned below needs to be in sync with the values in portstat script
So, any fields added/deleted in here should be reflected in portstat script also
"""
BUCKET_NUM = 45
BUCKET_NUM = 49

wred_green_pkt_stat_capable = False
wred_yellow_pkt_stat_capable = False
wred_red_pkt_stat_capable = False
wred_total_pkt_stat_capable = False
is_wred_stats_reqd = True

counter_bucket_dict = {
0:['SAI_PORT_STAT_IF_IN_UCAST_PKTS', 'SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS'],
1:['SAI_PORT_STAT_IF_IN_ERRORS'],
Expand Down Expand Up @@ -116,7 +124,11 @@ counter_bucket_dict = {
41:['SAI_PORT_STAT_IP_IN_RECEIVES'],
42:['SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES'],
43:['SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES'],
44:['SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS']
44:['SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS'],
45:['SAI_PORT_STAT_GREEN_WRED_DROPPED_PACKETS'],
46:['SAI_PORT_STAT_YELLOW_WRED_DROPPED_PACKETS'],
47:['SAI_PORT_STAT_RED_WRED_DROPPED_PACKETS'],
48:['SAI_PORT_STAT_WRED_DROPPED_PACKETS']
}

STATUS_NA = 'N/A'
Expand Down Expand Up @@ -157,6 +169,32 @@ class Portstat(object):
Collect the statisitics from all the asics present on the
device and store in a dict
"""
global BUCKET_NUM

global wred_green_pkt_stat_capable
global wred_yellow_pkt_stat_capable
global wred_red_pkt_stat_capable
global wred_total_pkt_stat_capable
global is_wred_stats_reqd

wred_green_pkt_stat_capable = self.db.get(self.db.STATE_DB, "PORT_COUNTER_CAPABILITIES|WRED_ECN_PORT_WRED_GREEN_DROP_COUNTER","isSupported")
wred_yellow_pkt_stat_capable = self.db.get(self.db.STATE_DB, "PORT_COUNTER_CAPABILITIES|WRED_ECN_PORT_WRED_YELLOW_DROP_COUNTER","isSupported")
wred_red_pkt_stat_capable = self.db.get(self.db.STATE_DB, "PORT_COUNTER_CAPABILITIES|WRED_ECN_PORT_WRED_RED_DROP_COUNTER","isSupported")
wred_total_pkt_stat_capable = self.db.get(self.db.STATE_DB, "PORT_COUNTER_CAPABILITIES|WRED_ECN_PORT_WRED_TOTAL_DROP_COUNTER","isSupported")

# Remove the unsupported stats from the counter dict
if ((is_wred_stats_reqd == False) or (wred_green_pkt_stat_capable != "true")) and ('SAI_PORT_STAT_GREEN_WRED_DROPPED_PACKETS' in counter_bucket_dict.keys()):
del counter_bucket_dict['SAI_PORT_STAT_GREEN_WRED_DROPPED_PACKETS']
BUCKET_NUM = (BUCKET_NUM - 1)
if ((is_wred_stats_reqd == False) or (wred_yellow_pkt_stat_capable != "true")) and ('SAI_PORT_STAT_YELLOW_WRED_DROPPED_PACKETS' in counter_bucket_dict.keys()):
del counter_bucket_dict['SAI_PORT_STAT_YELLOW_WRED_DROPPED_PACKETS']
BUCKET_NUM = (BUCKET_NUM - 1)
if ((is_wred_stats_reqd == False) or (wred_red_pkt_stat_capable != "true")) and ('SAI_PORT_STAT_RED_WRED_DROPPED_PACKETS' in counter_bucket_dict.keys()):
del counter_bucket_dict['SAI_PORT_STAT_RED_WRED_DROPPED_PACKETS']
BUCKET_NUM = (BUCKET_NUM - 1)
if ((is_wred_stats_reqd == False) or (wred_total_pkt_stat_capable != "true")) and ('SAI_PORT_STAT_WRED_DROPPED_PACKETS' in counter_bucket_dict.keys()):
del counter_bucket_dict['SAI_PORT_STAT_WRED_DROPPED_PACKETS']
BUCKET_NUM = (BUCKET_NUM - 1)

cnstat_dict, ratestat_dict = self.get_cnstat()
self.cnstat_dict.update(cnstat_dict)
Expand All @@ -170,6 +208,8 @@ class Portstat(object):
"""
Get the counters from specific table.
"""


fields = ["0"]*BUCKET_NUM

_, fvs = counter_table.get(PortCounter(), port)
Expand Down Expand Up @@ -400,9 +440,22 @@ class Portstat(object):
print("Multicast Packets Transmitted.................. {}".format(ns_diff(cntr.tx_mca, old_cntr.tx_mca)))
print("Broadcast Packets Transmitted.................. {}".format(ns_diff(cntr.tx_bca, old_cntr.tx_bca)))

if wred_green_pkt_stat_capable == "true" or wred_yellow_pkt_stat_capable == "true" or wred_red_pkt_stat_capable == "true" or wred_total_pkt_stat_capable == "true":
print("")
if wred_green_pkt_stat_capable == "true":
print("WRED Green Dropped Packets..................... {}".format(ns_diff(cntr.wred_grn_drp_pkt, old_cntr.wred_grn_drp_pkt)))
if wred_yellow_pkt_stat_capable == "true":
print("WRED Yellow Dropped Packets.................... {}".format(ns_diff(cntr.wred_ylw_drp_pkt, old_cntr.wred_ylw_drp_pkt)))
if wred_red_pkt_stat_capable == "true":
print("WRED Red Dropped Packets....................... {}".format(ns_diff(cntr.wred_red_drp_pkt, old_cntr.wred_red_drp_pkt)))
if wred_total_pkt_stat_capable == "true":
print("WRED Total Dropped Packets..................... {}".format(ns_diff(cntr.wred_tot_drp_pkt, old_cntr.wred_tot_drp_pkt)))
if wred_green_pkt_stat_capable == "true" or wred_yellow_pkt_stat_capable == "true" or wred_red_pkt_stat_capable == "true" or wred_total_pkt_stat_capable == "true":
print("")
print("Time Since Counters Last Cleared............... " + str(cnstat_old_dict.get('time')))



def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict,
ratestat_dict, intf_list, use_json,
print_all, errors_only, fec_stats_only,
Expand Down Expand Up @@ -632,6 +685,12 @@ Examples:
namespace = None
display_option = constants.DISPLAY_ALL

global is_wred_stats_reqd

if errors_only or rates_only or fec_stats_only:
is_wred_stats_reqd = False


portstat = Portstat(namespace, display_option)
cnstat_dict, ratestat_dict = portstat.get_cnstat_dict()

Expand Down
Loading

0 comments on commit 6084f23

Please sign in to comment.