Skip to content

Commit

Permalink
Add buffer pool watermark support in watermarkstat and counterpoll (s…
Browse files Browse the repository at this point in the history
…onic-net#521)

* Add buffer pool watermark support to watermarkstat

Signed-off-by: Wenda Ni <wenni@microsoft.com>

* Add buffer pool watermark to counterpoll

Signed-off-by: Wenda Ni <wenni@microsoft.com>

* Print N/A if the buffer pool watermark value is not present

Signed-off-by: Wenda Ni <wenni@microsoft.com>

* Fix syntax error; Change signature of function get_print_all_stat

Signed-off-by: Wenda Ni <wenni@microsoft.com>

* Address review comments

Signed-off-by: Wenda Ni <wenni@microsoft.com>
  • Loading branch information
wendani authored Jun 4, 2019
1 parent 635dc88 commit b7fcb1f
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 47 deletions.
23 changes: 18 additions & 5 deletions counterpoll/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
import swsssdk
from tabulate import tabulate

BUFFER_POOL_WATERMARK = "BUFFER_POOL_WATERMARK"
DISABLE = "disable"
DEFLT_10_SEC= "default (10000)"
DEFLT_1_SEC = "default (1000)"

@click.group()
def cli():
""" SONiC Static Counter Poll configurations """
Expand Down Expand Up @@ -123,11 +128,14 @@ def interval(poll_interval):
configdb.connect()
queue_wm_info = {}
pg_wm_info = {}
buffer_pool_wm_info = {}
if poll_interval is not None:
queue_wm_info['POLL_INTERVAL'] = poll_interval
pg_wm_info['POLL_INTERVAL'] = poll_interval
buffer_pool_wm_info['POLL_INTERVAL'] = poll_interval
configdb.mod_entry("FLEX_COUNTER_TABLE", "QUEUE_WATERMARK", queue_wm_info)
configdb.mod_entry("FLEX_COUNTER_TABLE", "PG_WATERMARK", pg_wm_info)
configdb.mod_entry("FLEX_COUNTER_TABLE", BUFFER_POOL_WATERMARK, buffer_pool_wm_info)

@watermark.command()
def enable():
Expand All @@ -138,6 +146,7 @@ def enable():
fc_info['FLEX_COUNTER_STATUS'] = 'enable'
configdb.mod_entry("FLEX_COUNTER_TABLE", "QUEUE_WATERMARK", fc_info)
configdb.mod_entry("FLEX_COUNTER_TABLE", "PG_WATERMARK", fc_info)
configdb.mod_entry("FLEX_COUNTER_TABLE", BUFFER_POOL_WATERMARK, fc_info)

@watermark.command()
def disable():
Expand All @@ -148,6 +157,7 @@ def disable():
fc_info['FLEX_COUNTER_STATUS'] = 'disable'
configdb.mod_entry("FLEX_COUNTER_TABLE", "QUEUE_WATERMARK", fc_info)
configdb.mod_entry("FLEX_COUNTER_TABLE", "PG_WATERMARK", fc_info)
configdb.mod_entry("FLEX_COUNTER_TABLE", BUFFER_POOL_WATERMARK, fc_info)

@cli.command()
def show():
Expand All @@ -159,19 +169,22 @@ def show():
rif_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'RIF')
queue_wm_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'QUEUE_WATERMARK')
pg_wm_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'PG_WATERMARK')
buffer_pool_wm_info = configdb.get_entry('FLEX_COUNTER_TABLE', BUFFER_POOL_WATERMARK)

header = ("Type", "Interval (in ms)", "Status")
data = []
if queue_info:
data.append(["QUEUE_STAT", queue_info["POLL_INTERVAL"] if 'POLL_INTERVAL' in queue_info else 'default (10000)', queue_info["FLEX_COUNTER_STATUS"] if 'FLEX_COUNTER_STATUS' in queue_info else 'disable' ])
data.append(["QUEUE_STAT", queue_info.get("POLL_INTERVAL", DEFLT_10_SEC), queue_info.get("FLEX_COUNTER_STATUS", DISABLE)])
if port_info:
data.append(["PORT_STAT", port_info["POLL_INTERVAL"] if 'POLL_INTERVAL' in port_info else 'default (1000)', port_info["FLEX_COUNTER_STATUS"] if 'FLEX_COUNTER_STATUS' in port_info else 'disable'])
data.append(["PORT_STAT", port_info.get("POLL_INTERVAL", DEFLT_1_SEC), port_info.get("FLEX_COUNTER_STATUS", DISABLE)])
if rif_info:
data.append(["RIF_STAT", rif_info["POLL_INTERVAL"] if 'POLL_INTERVAL' in rif_info else 'default (1000)', rif_info["FLEX_COUNTER_STATUS"] if 'FLEX_COUNTER_STATUS' in rif_info else 'disable'])
data.append(["RIF_STAT", rif_info.get("POLL_INTERVAL", DEFLT_1_SEC), rif_info.get("FLEX_COUNTER_STATUS", DISABLE)])
if queue_wm_info:
data.append(["QUEUE_WATERMARK_STAT", queue_wm_info["POLL_INTERVAL"] if 'POLL_INTERVAL' in queue_wm_info else 'default (10000)', queue_wm_info["FLEX_COUNTER_STATUS"] if 'FLEX_COUNTER_STATUS' in queue_wm_info else 'disable' ])
data.append(["QUEUE_WATERMARK_STAT", queue_wm_info.get("POLL_INTERVAL", DEFLT_10_SEC), queue_wm_info.get("FLEX_COUNTER_STATUS", DISABLE)])
if pg_wm_info:
data.append(["PG_WATERMARK_STAT", pg_wm_info["POLL_INTERVAL"] if 'POLL_INTERVAL' in pg_wm_info else 'default (10000)', pg_wm_info["FLEX_COUNTER_STATUS"] if 'FLEX_COUNTER_STATUS' in pg_wm_info else 'disable'])
data.append(["PG_WATERMARK_STAT", pg_wm_info.get("POLL_INTERVAL", DEFLT_10_SEC), pg_wm_info.get("FLEX_COUNTER_STATUS", DISABLE)])
if buffer_pool_wm_info:
data.append(["BUFFER_POOL_WATERMARK_STAT", buffer_pool_wm_info.get("POLL_INTERVAL", DEFLT_10_SEC), buffer_pool_wm_info.get("FLEX_COUNTER_STATUS", DISABLE)])

print tabulate(data, headers=header, tablefmt="simple", missingval="")

103 changes: 64 additions & 39 deletions scripts/watermarkstat
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ from tabulate import tabulate
headerPg = ['Port', 'PG0', 'PG1', 'PG2', 'PG3', 'PG4', 'PG5', 'PG6', 'PG7']
headerUc = ['Port', 'UC0', 'UC1', 'UC2', 'UC3', 'UC4', 'UC5', 'UC6', 'UC7']
headerMc = ['Port', 'MC8', 'MC9', 'MC10', 'MC11', 'MC12', 'MC13', 'MC14', 'MC15']
headerBufferPool = ['Pool', 'Bytes']


STATUS_NA = 'N/A'
Expand All @@ -43,6 +44,7 @@ COUNTERS_QUEUE_PORT_MAP = "COUNTERS_QUEUE_PORT_MAP"
COUNTERS_PG_NAME_MAP = "COUNTERS_PG_NAME_MAP"
COUNTERS_PG_PORT_MAP = "COUNTERS_PG_PORT_MAP"
COUNTERS_PG_INDEX_MAP = "COUNTERS_PG_INDEX_MAP"
COUNTERS_BUFFER_POOL_NAME_MAP = "COUNTERS_BUFFER_POOL_NAME_MAP"


class Watermarkstat(object):
Expand All @@ -58,7 +60,7 @@ class Watermarkstat(object):
def get_queue_type(table_id):
queue_type = self.counters_db.get(self.counters_db.COUNTERS_DB, COUNTERS_QUEUE_TYPE_MAP, table_id)
if queue_type is None:
print "Queue Type is not available!", table_id
print >> sys.stderr, "Queue Type is not available!", table_id
sys.exit(1)
elif queue_type == SAI_QUEUE_TYPE_MULTICAST:
return QUEUE_TYPE_MC
Expand All @@ -67,29 +69,29 @@ class Watermarkstat(object):
elif queue_type == SAI_QUEUE_TYPE_ALL:
return QUEUE_TYPE_ALL
else:
print "Queue Type is invalid:", table_id, queue_type
print >> sys.stderr, "Queue Type is invalid:", table_id, queue_type
sys.exit(1)

def get_queue_port(table_id):
port_table_id = self.counters_db.get(self.counters_db.COUNTERS_DB, COUNTERS_QUEUE_PORT_MAP, table_id)
if port_table_id is None:
print "Port is not available!", table_id
print >> sys.stderr, "Port is not available!", table_id
sys.exit(1)

return port_table_id

def get_pg_port(table_id):
port_table_id = self.counters_db.get(self.counters_db.COUNTERS_DB, COUNTERS_PG_PORT_MAP, table_id)
if port_table_id is None:
print "Port is not available!", table_id
print >> sys.stderr, "Port is not available!", table_id
sys.exit(1)

return port_table_id

# Get all ports
self.counter_port_name_map = self.counters_db.get_all(self.counters_db.COUNTERS_DB, COUNTERS_PORT_NAME_MAP)
if self.counter_port_name_map is None:
print "COUNTERS_PORT_NAME_MAP is empty!"
print >> sys.stderr, "COUNTERS_PORT_NAME_MAP is empty!"
sys.exit(1)

self.port_uc_queues_map = {}
Expand All @@ -106,7 +108,7 @@ class Watermarkstat(object):
# Get Queues for each port
counter_queue_name_map = self.counters_db.get_all(self.counters_db.COUNTERS_DB, COUNTERS_QUEUE_NAME_MAP)
if counter_queue_name_map is None:
print "COUNTERS_QUEUE_NAME_MAP is empty!"
print >> sys.stderr, "COUNTERS_QUEUE_NAME_MAP is empty!"
sys.exit(1)

for queue in counter_queue_name_map:
Expand All @@ -120,48 +122,57 @@ class Watermarkstat(object):
# Get PGs for each port
counter_pg_name_map = self.counters_db.get_all(self.counters_db.COUNTERS_DB, COUNTERS_PG_NAME_MAP)
if counter_pg_name_map is None:
print "COUNTERS_PG_NAME_MAP is empty!"
print >> sys.stderr, "COUNTERS_PG_NAME_MAP is empty!"
sys.exit(1)

for pg in counter_pg_name_map:
port = self.port_name_map[get_pg_port(counter_pg_name_map[pg])]
self.port_pg_map[port][pg] = counter_pg_name_map[pg]

# Get all buffer pools
self.buffer_pool_name_to_oid_map = self.counters_db.get_all(self.counters_db.COUNTERS_DB, COUNTERS_BUFFER_POOL_NAME_MAP)
if self.buffer_pool_name_to_oid_map is None:
print >> sys.stderr, "COUNTERS_BUFFER_POOL_NAME_MAP is empty!"
sys.exit(1)

self.watermark_types = {
"pg_headroom": {"message": "Ingress headroom per PG:",
"obj_map": self.port_pg_map,
"idx_func": self.get_pg_index,
"wm_name": "SAI_INGRESS_PRIORITY_GROUP_STAT_XOFF_ROOM_WATERMARK_BYTES",
"header": headerPg},
"pg_shared": {"message": "Ingress shared pool occupancy per PG:",
"obj_map": self.port_pg_map,
"idx_func": self.get_pg_index,
"wm_name": "SAI_INGRESS_PRIORITY_GROUP_STAT_SHARED_WATERMARK_BYTES",
"header": headerPg},
"q_shared_uni": {"message": "Egress shared pool occupancy per unicast queue:",
"obj_map": self.port_uc_queues_map,
"idx_func": self.get_queue_index,
"wm_name": "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES",
"header": headerUc},
"q_shared_multi": {"message": "Egress shared pool occupancy per multicast queue:",
"obj_map": self.port_mc_queues_map,
"idx_func": self.get_queue_index,
"wm_name": "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES",
"header": headerMc}
"pg_headroom" : {"message" : "Ingress headroom per PG:",
"obj_map" : self.port_pg_map,
"idx_func": self.get_pg_index,
"wm_name" : "SAI_INGRESS_PRIORITY_GROUP_STAT_XOFF_ROOM_WATERMARK_BYTES",
"header" : headerPg},
"pg_shared" : {"message" : "Ingress shared pool occupancy per PG:",
"obj_map" : self.port_pg_map,
"idx_func": self.get_pg_index,
"wm_name" : "SAI_INGRESS_PRIORITY_GROUP_STAT_SHARED_WATERMARK_BYTES",
"header" : headerPg},
"q_shared_uni" : {"message" : "Egress shared pool occupancy per unicast queue:",
"obj_map" : self.port_uc_queues_map,
"idx_func": self.get_queue_index,
"wm_name" : "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES",
"header" : headerUc},
"q_shared_multi": {"message" : "Egress shared pool occupancy per multicast queue:",
"obj_map" : self.port_mc_queues_map,
"idx_func": self.get_queue_index,
"wm_name" : "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES",
"header" : headerMc},
"buffer_pool" : {"message": "Shared pool maximum occupancy:",
"wm_name": "SAI_BUFFER_POOL_STAT_WATERMARK_BYTES",
"header" : headerBufferPool}
}

def get_queue_index(self, table_id):
queue_index = self.counters_db.get(self.counters_db.COUNTERS_DB, COUNTERS_QUEUE_INDEX_MAP, table_id)
if queue_index is None:
print "Queue index is not available!", table_id
print >> sys.stderr, "Queue index is not available!", table_id
sys.exit(1)

return queue_index

def get_pg_index(self, table_id):
pg_index = self.counters_db.get(self.counters_db.COUNTERS_DB, COUNTERS_PG_INDEX_MAP, table_id)
if pg_index is None:
print "Priority group index is not available!", table_id
print >> sys.stderr, "Priority group index is not available!", table_id
sys.exit(1)

return pg_index
Expand All @@ -171,7 +182,7 @@ class Watermarkstat(object):
Get the counters from specific table.
"""

fields = ["0"]*8
fields = ["0"] * 8

for name, obj_id in port_obj.items():
full_table_id = table_prefix + obj_id
Expand All @@ -184,14 +195,25 @@ class Watermarkstat(object):
cntr = tuple(fields)
return cntr

def get_print_all_stat(self, table_prefix, type):
# Get stat for each port
def print_all_stat(self, table_prefix, key):
table = []
for port in natsorted(self.counter_port_name_map):
data = self.get_counters(table_prefix,
type["obj_map"][port], type["idx_func"], type["wm_name"])
table.append((port, data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7]))
type = self.watermark_types[key]
if key == 'buffer_pool':
# Get stats for each buffer pool
for buf_pool, bp_oid in natsorted(self.buffer_pool_name_to_oid_map.items()):
key = table_prefix + bp_oid
data = self.counters_db.get(self.counters_db.COUNTERS_DB, key, type["wm_name"])
if data is None:
data = STATUS_NA
table.append((buf_pool, data))
else:
# Get stat for each port
for port in natsorted(self.counter_port_name_map):
data = self.get_counters(table_prefix,
type["obj_map"][port], type["idx_func"], type["wm_name"])
table.append((port, data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7]))

print(type["message"])
print tabulate(table, type["header"], tablefmt='simple', stralign='right')

Expand All @@ -214,12 +236,15 @@ Examples:
watermarkstat -t q_shared_multi -c
watermarkstat -p -t pg_shared
watermarkstat -p -t q_shared_multi -c
watermarkstat -t buffer_pool
watermarkstat -t buffer_pool -c
watermarkstat -p -t buffer_pool -c
""")

parser.add_argument('-c', '--clear', action='store_true', help='Clear watermarks request')
parser.add_argument('-p', '--persistent', action='store_true', help='Do the operations on the persistent watermark')
parser.add_argument('-t', '--type', required=True, action='store',
choices=['pg_headroom', 'pg_shared', 'q_shared_uni', 'q_shared_multi'],
choices=['pg_headroom', 'pg_shared', 'q_shared_uni', 'q_shared_multi', 'buffer_pool'],
help='The type of watermark')
args = parser.parse_args()
watermarkstat = Watermarkstat()
Expand All @@ -229,7 +254,7 @@ Examples:
sys.exit(0)

table_prefix = PERSISTENT_TABLE_PREFIX if args.persistent else USER_TABLE_PREFIX
watermarkstat.get_print_all_stat(table_prefix, watermarkstat.watermark_types[args.type])
watermarkstat.print_all_stat(table_prefix, args.type)
sys.exit(0)


Expand Down
26 changes: 23 additions & 3 deletions show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,10 +747,9 @@ def pwm_q_multi():
def priority_group():
"""Show details of the PGs """


@priority_group.group()
def watermark():
"""Show priority_group user WM"""
"""Show priority-group user WM"""
pass

@watermark.command('headroom')
Expand All @@ -767,7 +766,7 @@ def wm_pg_shared():

@priority_group.group(name='persistent-watermark')
def persistent_watermark():
"""Show queue persistent WM"""
"""Show priority-group persistent WM"""
pass

@persistent_watermark.command('headroom')
Expand All @@ -783,6 +782,27 @@ def pwm_pg_shared():
run_command(command)


#
# 'buffer_pool' group ("show buffer_pool ...")
#

@cli.group(name='buffer_pool', cls=AliasedGroup, default_if_no_args=False)
def buffer_pool():
"""Show details of the buffer pools"""

@buffer_pool.command('watermark')
def wm_buffer_pool():
"""Show user WM for buffer pools"""
command = 'watermarkstat -t buffer_pool'
run_command(command)

@buffer_pool.command('persistent-watermark')
def pwm_buffer_pool():
"""Show persistent WM for buffer pools"""
command = 'watermarkstat -p -t buffer_pool'
run_command(command)


#
# 'mac' command ("show mac ...")
#
Expand Down

0 comments on commit b7fcb1f

Please sign in to comment.