Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 60 additions & 77 deletions scripts/portstat
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ PORT_RATE = 40

NStats = namedtuple("NStats", "rx_ok, rx_err, rx_drop, rx_ovr, tx_ok,\
tx_err, tx_drop, tx_ovr, rx_byt, tx_byt")
header_all = ['Iface', 'ADMIN', 'OPER', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR',
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 = ['Iface', 'ADMIN', 'OPER', 'RX_OK', 'RX_BPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR',
header = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR',
'TX_OK', 'TX_BPS', 'TX_UTIL', 'TX_ERR', 'TX_DRP', 'TX_OVR']

counter_bucket_dict = {
Expand All @@ -48,11 +48,20 @@ counter_bucket_dict = {
'SAI_PORT_STAT_IF_OUT_OCTETS': 9
}

STATUS_NA = 'N/A'

COUNTER_TABLE_PREFIX = "COUNTERS:"
COUNTERS_PORT_NAME_MAP = "COUNTERS_PORT_NAME_MAP"

PORT_STATUS_TABLE_PREFIX = "PORT_TABLE:"
PORT_OPER_STATUS_FIELD = "oper_status"
PORT_ADMIN_STATUS_FIELD = "admin_status"
PORT_STATUS_VALUE_UP = 'UP'
PORT_STATUS_VALUE_DOWN = 'DOWN'

PORT_STATE_UP = 'U'
PROT_STATE_DOWN = 'D'
PORT_STATE_DISABLED = 'X'

class Portstat(object):
def __init__(self):
Expand All @@ -73,8 +82,8 @@ class Portstat(object):
full_table_id = COUNTER_TABLE_PREFIX + table_id
counter_data = self.db.get(self.db.COUNTERS_DB, full_table_id, counter_name)
if counter_data is None:
fields[pos] = "N/A"
elif fields[pos] != "N/A":
fields[pos] = STATUS_NA
elif fields[pos] != STATUS_NA:
fields[pos] = str(int(fields[pos]) + int(counter_data))
cntr = NStats._make(fields)
return cntr
Expand All @@ -90,67 +99,40 @@ class Portstat(object):
cnstat_dict[port] = get_counters(counter_port_name_map[port])
return cnstat_dict

def get_port_status(self, port_name, status_type):
def get_port_state(self, port_name):
"""
Get the port status
Get the port state
"""
full_table_id = PORT_STATUS_TABLE_PREFIX + port_name
status = self.db.get(self.db.APPL_DB, full_table_id, status_type)
if status is None:
return "N/A"
admin_state = self.db.get(self.db.APPL_DB, full_table_id, PORT_ADMIN_STATUS_FIELD)
oper_state = self.db.get(self.db.APPL_DB, full_table_id, PORT_OPER_STATUS_FIELD)
if admin_state is None or oper_state is None:
return STATUS_NA
elif admin_state.upper() == PORT_STATUS_VALUE_DOWN:
return PORT_STATE_DISABLED
elif admin_state.upper() == PORT_STATUS_VALUE_UP and oper_state.upper() == PORT_STATUS_VALUE_UP:
return PORT_STATE_UP
elif admin_state.upper() == PORT_STATUS_VALUE_UP and oper_state.upper() == PORT_STATUS_VALUE_DOWN:
return PORT_STATE_DOWN
else:
return status
return STATUS_NA

def table_as_json(self, table, print_all):
"""
Print table as json format.
"""
output = {}

# Build a dictionary where the if_name is the key and the value is
# a dictionary that holds MTU, TX_DRP, etc
if print_all:
for line in table:
if_name = line[0]

# Build a dictionary where the if_name is the key and the value is
# a dictionary that holds MTU, TX_DRP, etc
output[if_name] = {
header_all[1] : line[1],
header_all[2] : line[2],
header_all[3] : line[3],
header_all[4] : line[4],
header_all[5] : line[5],
header_all[6] : line[6],
header_all[7] : line[7],
header_all[8] : line[8],
header_all[9] : line[9],
header_all[10] : line[10],
header_all[11] : line[11],
header_all[12] : line[12],
header_all[13] : line[13],
header_all[14] : line[14],
header_all[15] : line[15]
}
output[if_name] = {header_all[i]: line[i] for i in range(1, len(header_all))}
else:
for line in table:
if_name = line[0]

# Build a dictionary where the if_name is the key and the value is
# a dictionary that holds MTU, TX_DRP, etc
output[if_name] = {
header[1] : line[1],
header[2] : line[2],
header[3] : line[3],
header[4] : line[4],
header[5] : line[5],
header[6] : line[6],
header[7] : line[7],
header[8] : line[8],
header[9] : line[9],
header[10] : line[10],
header[11] : line[11],
header[12] : line[12],
header[13] : line[13]
}
output[if_name] = {header[i]: line[i] for i in range(1, len(header))}

return json.dumps(output, indent=4, sort_keys=True)

Expand All @@ -165,16 +147,16 @@ class Portstat(object):
continue

if print_all:
table.append((key, self.get_port_status(key, PORT_ADMIN_STATUS_FIELD), self.get_port_status(key, PORT_OPER_STATUS_FIELD),
data.rx_ok, "N/A", "N/A", "N/A", data.rx_err,
table.append((key, self.get_port_state(key),
data.rx_ok, STATUS_NA, STATUS_NA, STATUS_NA, data.rx_err,
data.rx_drop, data.rx_ovr,
data.tx_ok, "N/A", "N/A", "N/A", data.tx_err,
data.tx_ok, STATUS_NA, STATUS_NA, STATUS_NA, data.tx_err,
data.tx_drop, data.tx_ovr))
else:
table.append((key, self.get_port_status(key, PORT_ADMIN_STATUS_FIELD), self.get_port_status(key, PORT_OPER_STATUS_FIELD),
data.rx_ok, "N/A", "N/A", data.rx_err,
table.append((key, self.get_port_state(key),
data.rx_ok, STATUS_NA, STATUS_NA, data.rx_err,
data.rx_drop, data.rx_ovr,
data.tx_ok, "N/A", "N/A", data.tx_err,
data.tx_ok, STATUS_NA, STATUS_NA, data.tx_err,
data.tx_drop, data.tx_ovr))


Expand All @@ -195,8 +177,8 @@ class Portstat(object):
"""
Calculate the diff.
"""
if newstr == "N/A" or oldstr == "N/A":
return "N/A"
if newstr == STATUS_NA or oldstr == STATUS_NA:
return STATUS_NA
else:
new, old = int(newstr), int(oldstr)
return '{:,}'.format(new - old)
Expand All @@ -205,8 +187,8 @@ class Portstat(object):
"""
Calculate the byte rate.
"""
if newstr == "N/A" or oldstr == "N/A":
return "N/A"
if newstr == STATUS_NA or oldstr == STATUS_NA:
return STATUS_NA
else:
rate = int(ns_diff(newstr, oldstr).replace(',',''))/delta
if rate > 1024*1024*10:
Expand All @@ -221,8 +203,8 @@ class Portstat(object):
"""
Calculate the packet rate.
"""
if newstr == "N/A" or oldstr == "N/A":
return "N/A"
if newstr == STATUS_NA or oldstr == STATUS_NA:
return STATUS_NA
else:
rate = int(ns_diff(newstr, oldstr).replace(',',''))/delta
return "{:.2f}".format(rate)+'/s'
Expand All @@ -231,8 +213,8 @@ class Portstat(object):
"""
Calculate the util.
"""
if newstr == "N/A" or oldstr == "N/A":
return "N/A"
if newstr == STATUS_NA or oldstr == STATUS_NA:
return STATUS_NA
else:
rate = int(ns_diff(newstr, oldstr).replace(',',''))/delta
util = rate/(PORT_RATE*1024*1024*1024/8.0)*100
Expand All @@ -251,7 +233,7 @@ class Portstat(object):

if print_all:
if old_cntr is not None:
table.append((key, self.get_port_status(key, PORT_ADMIN_STATUS_FIELD), self.get_port_status(key, PORT_OPER_STATUS_FIELD),
table.append((key, self.get_port_state(key),
ns_diff(cntr.rx_ok, old_cntr.rx_ok),
ns_brate(cntr.rx_byt, old_cntr.rx_byt, time_gap),
ns_prate(cntr.rx_ok, old_cntr.rx_ok, time_gap),
Expand All @@ -267,24 +249,24 @@ class Portstat(object):
ns_diff(cntr.tx_drop, old_cntr.tx_drop),
ns_diff(cntr.tx_ovr, old_cntr.tx_ovr)))
else:
table.append((key, self.get_port_status(key, PORT_ADMIN_STATUS_FIELD), self.get_port_status(key, PORT_OPER_STATUS_FIELD),
table.append((key, self.get_port_state(key),
cntr.rx_ok,
"N/A",
"N/A",
"N/A",
STATUS_NA,
STATUS_NA,
STATUS_NA,
cntr.rx_err,
cntr.rx_drop,
cntr.rx_ovr,
cntr.tx_ok,
"N/A",
"N/A",
"N/A",
STATUS_NA,
STATUS_NA,
STATUS_NA,
cntr.tx_err,
cntr.tx_drop,
cntr.tx_err))
else:
if old_cntr is not None:
table.append((key, self.get_port_status(key, PORT_ADMIN_STATUS_FIELD), self.get_port_status(key, PORT_OPER_STATUS_FIELD),
table.append((key, self.get_port_state(key),
ns_diff(cntr.rx_ok, old_cntr.rx_ok),
ns_brate(cntr.rx_byt, old_cntr.rx_byt, time_gap),
ns_util(cntr.rx_byt, old_cntr.rx_byt, time_gap),
Expand All @@ -298,16 +280,16 @@ class Portstat(object):
ns_diff(cntr.tx_drop, old_cntr.tx_drop),
ns_diff(cntr.tx_ovr, old_cntr.tx_ovr)))
else:
table.append((key, self.get_port_status(key, PORT_ADMIN_STATUS_FIELD), self.get_port_status(key, PORT_OPER_STATUS_FIELD),
table.append((key, self.get_port_state(key),
cntr.rx_ok,
"N/A",
"N/A",
STATUS_NA,
STATUS_NA,
cntr.rx_err,
cntr.rx_drop,
cntr.rx_ovr,
cntr.tx_ok,
"N/A",
"N/A",
STATUS_NA,
STATUS_NA,
cntr.tx_err,
cntr.tx_drop,
cntr.tx_err))
Expand All @@ -322,10 +304,11 @@ class Portstat(object):


def main():
parser = argparse.ArgumentParser(description='Wrapper for netstat',
parser = argparse.ArgumentParser(description='Display the ports state and counters',
version='1.0.0',
formatter_class=argparse.RawTextHelpFormatter,
epilog="""
Port state: (U)-Up (D)-Down (X)-Disabled
Examples:
portstat -c -t test
portstat -t test
Expand Down