Skip to content

Commit

Permalink
Fix multi-asic behaviour for pg-drop (#3058)
Browse files Browse the repository at this point in the history
* Fixes multi-asic behaviour for pg-drop script.

show priority-group drop is not behaving correctly on multi-asic devices,
as the namespace option '-n' is not available and correct namespaces were
not traversed to retrieve drop counters. This change fixes the multi-asic
behaviour of this command.

* add additional test and simplify branching


Co-authored-by: Kenneth Cheung <[email protected]>
  • Loading branch information
bktsim-arista and kenneth-arista authored Jul 10, 2024
1 parent 789ef63 commit 1f94444
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 28 deletions.
87 changes: 60 additions & 27 deletions scripts/pg-drop
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# pg-drop is a tool for show/clear ingress pg dropped packet stats.
#
#####################################################################
from importlib import reload
import json
import argparse
import os
Expand All @@ -13,6 +14,8 @@ from collections import OrderedDict

from natsort import natsorted
from tabulate import tabulate
from utilities_common.general import load_db_config
from sonic_py_common import multi_asic

# mock the redis for unit test purposes #
try:
Expand All @@ -22,7 +25,9 @@ try:
sys.path.insert(0, modules_path)
sys.path.insert(0, tests_path)
import mock_tables.dbconnector

if os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] == "multi_asic":
import mock_tables.mock_multi_asic
mock_tables.dbconnector.load_namespace_config()
except KeyError:
pass

Expand All @@ -43,28 +48,26 @@ def get_dropstat_dir():

class PgDropStat(object):

def __init__(self):
self.counters_db = SonicV2Connector(host='127.0.0.1')
self.counters_db.connect(self.counters_db.COUNTERS_DB)

self.configdb = ConfigDBConnector()
def __init__(self, namespace):
self.namespace = namespace
self.ns_list = multi_asic.get_namespace_list(namespace)
self.configdb = ConfigDBConnector(namespace=namespace)
self.configdb.connect()

dropstat_dir = get_dropstat_dir()
self.port_drop_stats_file = os.path.join(dropstat_dir, 'pg_drop_stats')

def get_port_id(oid):
"""
Get port ID using object ID
"""
port_id = self.counters_db.get(self.counters_db.COUNTERS_DB, COUNTERS_PG_PORT_MAP, oid)
port_id = self.get_counters_mapdata(COUNTERS_PG_PORT_MAP, oid)
if not port_id:
print("Port is not available for oid '{}'".format(oid))
sys.exit(1)
return port_id

# Get all ports
self.counter_port_name_map = self.counters_db.get_all(self.counters_db.COUNTERS_DB, COUNTERS_PORT_NAME_MAP)
self.counter_port_name_map = self.get_counters_mapall(COUNTERS_PORT_NAME_MAP)
if not self.counter_port_name_map:
print("COUNTERS_PORT_NAME_MAP is empty!")
sys.exit(1)
Expand All @@ -77,7 +80,7 @@ class PgDropStat(object):
self.port_name_map[self.counter_port_name_map[port]] = port

# Get PGs for each port
counter_pg_name_map = self.counters_db.get_all(self.counters_db.COUNTERS_DB, COUNTERS_PG_NAME_MAP)
counter_pg_name_map = self.get_counters_mapall(COUNTERS_PG_NAME_MAP)
if not counter_pg_name_map:
print("COUNTERS_PG_NAME_MAP is empty!")
sys.exit(1)
Expand All @@ -94,13 +97,32 @@ class PgDropStat(object):
"header_prefix": "PG"},
}

def get_counters_mapdata(self, tablemap, index):
for ns in self.ns_list:
counters_db = SonicV2Connector(namespace=ns)
counters_db.connect(counters_db.COUNTERS_DB)
data = counters_db.get(counters_db.COUNTERS_DB, tablemap, index)
if data:
return data
return None

def get_counters_mapall(self, tablemap):
mapdata = {}
for ns in self.ns_list:
counters_db = SonicV2Connector(namespace=ns)
counters_db.connect(counters_db.COUNTERS_DB)
map_result = counters_db.get_all(counters_db.COUNTERS_DB, tablemap)
if map_result:
mapdata.update(map_result)
return mapdata

def get_pg_index(self, oid):
"""
return PG index (0-7)
oid - object ID for entry in redis
"""
pg_index = self.counters_db.get(self.counters_db.COUNTERS_DB, COUNTERS_PG_INDEX_MAP, oid)
pg_index = self.get_counters_mapdata(COUNTERS_PG_INDEX_MAP, oid)
if not pg_index:
print("Priority group index is not available for oid '{}'".format(oid))
sys.exit(1)
Expand Down Expand Up @@ -154,7 +176,7 @@ class PgDropStat(object):
old_collected_data = port_drop_ckpt.get(name,{})[full_table_id] if len(port_drop_ckpt) > 0 else 0
idx = int(idx_func(obj_id))
pos = self.header_idx_to_pos[idx]
counter_data = self.counters_db.get(self.counters_db.COUNTERS_DB, full_table_id, counter_name)
counter_data = self.get_counters_mapdata(full_table_id, counter_name)
if counter_data is None:
fields[pos] = STATUS_NA
elif fields[pos] != STATUS_NA:
Expand All @@ -180,29 +202,29 @@ class PgDropStat(object):
print(tabulate(table, self.header_list, tablefmt='simple', stralign='right'))

def get_counts(self, counters, oid):
"""
Get the PG drop counts for an individual counter.
"""
counts = {}
table_id = COUNTER_TABLE_PREFIX + oid
for counter in counters:
counter_data = self.counters_db.get(self.counters_db.COUNTERS_DB, table_id, counter)
if counter_data is None:
counts[table_id] = 0
else:
counts[table_id] = int(counter_data)
return counts
"""
Get the PG drop counts for an individual counter.
"""
counts = {}
table_id = COUNTER_TABLE_PREFIX + oid
for counter in counters:
counter_data = self.get_counters_mapdata(table_id, counter)
if counter_data is None:
counts[table_id] = 0
else:
counts[table_id] = int(counter_data)
return counts

def get_counts_table(self, counters, object_table):
"""
Returns a dictionary containing a mapping from an object (like a port)
to its PG drop counts. Counts are contained in a dictionary that maps
counter oid to its counts.
"""
counter_object_name_map = self.counters_db.get_all(self.counters_db.COUNTERS_DB, object_table)
counter_object_name_map = self.get_counters_mapall(object_table)
current_stat_dict = OrderedDict()

if counter_object_name_map is None:
if not counter_object_name_map:
return current_stat_dict

for obj in natsorted(counter_object_name_map):
Expand Down Expand Up @@ -239,10 +261,12 @@ def main():
epilog="""
Examples:
pg-drop -c show
pg-drop -c show --namespace asic0
pg-drop -c clear
""")

parser.add_argument('-c', '--command', type=str, help='Desired action to perform')
parser.add_argument('-n', '--namespace', type=str, help='Namespace name or skip for all', default=None)

args = parser.parse_args()
command = args.command
Expand All @@ -256,7 +280,16 @@ pg-drop -c clear
print(e)
sys.exit(e.errno)

pgdropstat = PgDropStat()
# Load database config files
load_db_config()
namespaces = multi_asic.get_namespace_list()
if args.namespace and args.namespace not in namespaces:
namespacelist = ', '.join(namespaces)
print(f"Input value for '--namespace' / '-n'. Choose from one of ({namespacelist})")
sys.exit(1)

# For 'clear' command force applying to all namespaces
pgdropstat = PgDropStat(args.namespace if command != 'clear' else None)

if command == 'clear':
pgdropstat.clear_drop_counts()
Expand Down
5 changes: 4 additions & 1 deletion show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -857,9 +857,12 @@ def drop():
pass

@drop.command('counters')
def pg_drop_counters():
@multi_asic_util.multi_asic_click_option_namespace
def pg_drop_counters(namespace):
"""Show dropped packets for priority-group"""
command = ['pg-drop', '-c', 'show']
if namespace is not None:
command += ['-n', str(namespace)]
run_command(command)

@priority_group.group(name='persistent-watermark')
Expand Down
102 changes: 102 additions & 0 deletions tests/mock_tables/asic1/counters_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,108 @@
"Ethernet-BP256": "oid:0x1000000000b06",
"Ethernet-BP260": "oid:0x1000000000b08"
},
"COUNTERS_PG_NAME_MAP": {
"Ethernet-BP256:0": "oid:100000000b0f0",
"Ethernet-BP256:1": "oid:100000000b0f1",
"Ethernet-BP256:2": "oid:100000000b0f2",
"Ethernet-BP256:3": "oid:100000000b0f3",
"Ethernet-BP256:4": "oid:100000000b0f4",
"Ethernet-BP256:5": "oid:100000000b0f5",
"Ethernet-BP256:6": "oid:100000000b0f6",
"Ethernet-BP256:7": "oid:100000000b0f7",
"Ethernet-BP256:8": "oid:100000000b0f8",
"Ethernet-BP256:9": "oid:100000000b0f9",
"Ethernet-BP256:10": "oid:100000000b0fa",
"Ethernet-BP256:11": "oid:100000000b0fb",
"Ethernet-BP256:12": "oid:100000000b0fc",
"Ethernet-BP256:13": "oid:100000000b0fd",
"Ethernet-BP256:14": "oid:100000000b0fe",
"Ethernet-BP256:15": "oid:100000000b0ff",
"Ethernet-BP260:0": "oid:0x100000000b1f0",
"Ethernet-BP260:1": "oid:0x100000000b1f1",
"Ethernet-BP260:2": "oid:0x100000000b1f2",
"Ethernet-BP260:3": "oid:0x100000000b1f3",
"Ethernet-BP260:4": "oid:0x100000000b1f4",
"Ethernet-BP260:5": "oid:0x100000000b1f5",
"Ethernet-BP260:6": "oid:0x100000000b1f6",
"Ethernet-BP260:7": "oid:0x100000000b1f7",
"Ethernet-BP260:8": "oid:0x100000000b1f8",
"Ethernet-BP260:9": "oid:0x100000000b1f9",
"Ethernet-BP260:10": "oid:0x100000000b1fa",
"Ethernet-BP260:11": "oid:0x100000000b1fb",
"Ethernet-BP260:12": "oid:0x100000000b1fc",
"Ethernet-BP260:13": "oid:0x100000000b1fd",
"Ethernet-BP260:14": "oid:0x100000000b1fe",
"Ethernet-BP260:15": "oid:0x100000000b1ff"
},
"COUNTERS_PG_PORT_MAP": {
"oid:100000000b0f0": "oid:0x1000000000b06",
"oid:100000000b0f1": "oid:0x1000000000b06",
"oid:100000000b0f2": "oid:0x1000000000b06",
"oid:100000000b0f3": "oid:0x1000000000b06",
"oid:100000000b0f4": "oid:0x1000000000b06",
"oid:100000000b0f5": "oid:0x1000000000b06",
"oid:100000000b0f6": "oid:0x1000000000b06",
"oid:100000000b0f7": "oid:0x1000000000b06",
"oid:100000000b0f8": "oid:0x1000000000b06",
"oid:100000000b0f9": "oid:0x1000000000b06",
"oid:100000000b0fa": "oid:0x1000000000b06",
"oid:100000000b0fb": "oid:0x1000000000b06",
"oid:100000000b0fc": "oid:0x1000000000b06",
"oid:100000000b0fd": "oid:0x1000000000b06",
"oid:100000000b0fe": "oid:0x1000000000b06",
"oid:100000000b0ff": "oid:0x1000000000b06",
"oid:0x100000000b1f0": "oid:0x1000000000b08",
"oid:0x100000000b1f1": "oid:0x1000000000b08",
"oid:0x100000000b1f2": "oid:0x1000000000b08",
"oid:0x100000000b1f3": "oid:0x1000000000b08",
"oid:0x100000000b1f4": "oid:0x1000000000b08",
"oid:0x100000000b1f5": "oid:0x1000000000b08",
"oid:0x100000000b1f6": "oid:0x1000000000b08",
"oid:0x100000000b1f7": "oid:0x1000000000b08",
"oid:0x100000000b1f8": "oid:0x1000000000b08",
"oid:0x100000000b1f9": "oid:0x1000000000b08",
"oid:0x100000000b1fa": "oid:0x1000000000b08",
"oid:0x100000000b1fb": "oid:0x1000000000b08",
"oid:0x100000000b1fc": "oid:0x1000000000b08",
"oid:0x100000000b1fd": "oid:0x1000000000b08",
"oid:0x100000000b1fe": "oid:0x1000000000b08",
"oid:0x100000000b1ff" : "oid:0x1000000000b08"
},
"COUNTERS_PG_INDEX_MAP": {
"oid:100000000b0f0": "0",
"oid:100000000b0f1": "1",
"oid:100000000b0f2": "2",
"oid:100000000b0f3": "3",
"oid:100000000b0f4": "4",
"oid:100000000b0f5": "5",
"oid:100000000b0f6": "6",
"oid:100000000b0f7": "7",
"oid:100000000b0f8": "8",
"oid:100000000b0f9": "9",
"oid:100000000b0fa": "10",
"oid:100000000b0fb": "11",
"oid:100000000b0fc": "12",
"oid:100000000b0fd": "13",
"oid:100000000b0fe": "14",
"oid:100000000b0ff": "15",
"oid:0x100000000b1f0": "0",
"oid:0x100000000b1f1": "1",
"oid:0x100000000b1f2": "2",
"oid:0x100000000b1f3": "3",
"oid:0x100000000b1f4": "4",
"oid:0x100000000b1f5": "5",
"oid:0x100000000b1f6": "6",
"oid:0x100000000b1f7": "7",
"oid:0x100000000b1f8": "8",
"oid:0x100000000b1f9": "9",
"oid:0x100000000b1fa": "10",
"oid:0x100000000b1fb": "11",
"oid:0x100000000b1fc": "12",
"oid:0x100000000b1fd": "13",
"oid:0x100000000b1fe": "14",
"oid:0x100000000b1ff" : "15"
},
"COUNTERS_LAG_NAME_MAP": {
"PortChannel0001": "oid:0x60000000005a1",
"PortChannel0002": "oid:0x60000000005a2",
Expand Down
Loading

0 comments on commit 1f94444

Please sign in to comment.