Skip to content
Closed
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
161 changes: 59 additions & 102 deletions scripts/portstat
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ from collections import namedtuple, OrderedDict
from natsort import natsorted
from tabulate import tabulate


PORT_RATE = 40

NStats = namedtuple("NStats", "rx_ok, rx_err, rx_drop, rx_ovr, tx_ok,\
Expand All @@ -33,6 +32,7 @@ header_all = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'RX_ERR'
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']

BUCKET_NUM = 10
counter_bucket_dict = {
'SAI_PORT_STAT_IF_IN_UCAST_PKTS': 0,
'SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS': 0,
Expand All @@ -58,6 +58,7 @@ PORT_OPER_STATUS_FIELD = "oper_status"
PORT_ADMIN_STATUS_FIELD = "admin_status"
PORT_STATUS_VALUE_UP = 'UP'
PORT_STATUS_VALUE_DOWN = 'DOWN'
PORT_SPEED_FIELD = "speed"

PORT_STATE_UP = 'U'
PORT_STATE_DOWN = 'D'
Expand All @@ -69,6 +70,10 @@ class Portstat(object):
self.db.connect(self.db.COUNTERS_DB)
self.db.connect(self.db.APPL_DB)

def get_uptime(self):
with open('/proc/uptime') as fp:
return float(fp.read().split(' ')[0])

def get_cnstat(self):
"""
Get the counters info from database.
Expand Down Expand Up @@ -99,6 +104,19 @@ class Portstat(object):
cnstat_dict[port] = get_counters(counter_port_name_map[port])
return cnstat_dict

def get_port_speed(self, port_name):
"""
Get the port speed
"""
# Get speed from APPL_DB
full_table_id = PORT_STATUS_TABLE_PREFIX + port_name
speed = self.db.get(self.db.APPL_DB, full_table_id, PORT_SPEED_FIELD)
if speed is None:
speed = PORT_RATE
else:
speed = int(speed)/1000
return speed

def get_port_state(self, port_name):
"""
Get the port state
Expand Down Expand Up @@ -136,40 +154,7 @@ class Portstat(object):

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

def cnstat_print(self, cnstat_dict, use_json, print_all):
"""
Print the cnstat.
"""
table = []

for key, data in cnstat_dict.iteritems():
if key == 'time':
continue

if print_all:
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, STATUS_NA, STATUS_NA, STATUS_NA, data.tx_err,
data.tx_drop, data.tx_ovr))
else:
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, STATUS_NA, STATUS_NA, data.tx_err,
data.tx_drop, data.tx_ovr))


if use_json:
print self.table_as_json(table, print_all)

else:
if print_all:
print tabulate(table, header_all, tablefmt='simple', stralign='right')
else:
print tabulate(table, header, tablefmt='simple', stralign='right')

def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict, use_json, print_all):
def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict, use_json=False, print_all=False):
"""
Print the difference between two cnstat results.
"""
Expand Down Expand Up @@ -209,90 +194,62 @@ class Portstat(object):
rate = int(ns_diff(newstr, oldstr).replace(',',''))/delta
return "{:.2f}".format(rate)+'/s'

def ns_util(newstr, oldstr, delta):
def ns_util(newstr, oldstr, delta, port_rate=PORT_RATE):
"""
Calculate the util.
"""
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
util = rate/(port_rate*1024*1024*1024/8.0)*100
return "{:.2f}%".format(util)

table = []

for key, cntr in cnstat_new_dict.iteritems():
if key == 'time':
time_gap = cnstat_new_dict.get('time') - cnstat_old_dict.get('time')
time_gap = time_gap.total_seconds()
if 'time' in cnstat_old_dict:
time_gap = cnstat_new_dict.get('time') - cnstat_old_dict.get('time')
time_gap = time_gap.total_seconds()
else:
time_gap = self.get_uptime()
continue
old_cntr = None
if key in cnstat_old_dict:
old_cntr = cnstat_old_dict.get(key)

else:
old_cntr = NStats._make([0] * BUCKET_NUM)
port_speed = self.get_port_speed(key)
if print_all:
if old_cntr is not None:
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),
ns_util(cntr.rx_byt, old_cntr.rx_byt, time_gap),
ns_diff(cntr.rx_err, old_cntr.rx_err),
ns_diff(cntr.rx_drop, old_cntr.rx_drop),
ns_diff(cntr.rx_ovr, old_cntr.rx_ovr),
ns_diff(cntr.tx_ok, old_cntr.tx_ok),
ns_brate(cntr.tx_byt, old_cntr.tx_byt, time_gap),
ns_prate(cntr.tx_ok, old_cntr.tx_ok, time_gap),
ns_util(cntr.tx_byt, old_cntr.tx_byt, time_gap),
ns_diff(cntr.tx_err, old_cntr.tx_err),
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_state(key),
cntr.rx_ok,
STATUS_NA,
STATUS_NA,
STATUS_NA,
cntr.rx_err,
cntr.rx_drop,
cntr.rx_ovr,
cntr.tx_ok,
STATUS_NA,
STATUS_NA,
STATUS_NA,
cntr.tx_err,
cntr.tx_drop,
cntr.tx_err))
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),
ns_util(cntr.rx_byt, old_cntr.rx_byt, time_gap, port_speed),
ns_diff(cntr.rx_err, old_cntr.rx_err),
ns_diff(cntr.rx_drop, old_cntr.rx_drop),
ns_diff(cntr.rx_ovr, old_cntr.rx_ovr),
ns_diff(cntr.tx_ok, old_cntr.tx_ok),
ns_brate(cntr.tx_byt, old_cntr.tx_byt, time_gap),
ns_prate(cntr.tx_ok, old_cntr.tx_ok, time_gap),
ns_util(cntr.tx_byt, old_cntr.tx_byt, time_gap, port_speed),
ns_diff(cntr.tx_err, old_cntr.tx_err),
ns_diff(cntr.tx_drop, old_cntr.tx_drop),
ns_diff(cntr.tx_ovr, old_cntr.tx_ovr)))
else:
if old_cntr is not None:
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),
ns_diff(cntr.rx_err, old_cntr.rx_err),
ns_diff(cntr.rx_drop, old_cntr.rx_drop),
ns_diff(cntr.rx_ovr, old_cntr.rx_ovr),
ns_diff(cntr.tx_ok, old_cntr.tx_ok),
ns_brate(cntr.tx_byt, old_cntr.tx_byt, time_gap),
ns_util(cntr.tx_byt, old_cntr.tx_byt, time_gap),
ns_diff(cntr.tx_err, old_cntr.tx_err),
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_state(key),
cntr.rx_ok,
STATUS_NA,
STATUS_NA,
cntr.rx_err,
cntr.rx_drop,
cntr.rx_ovr,
cntr.tx_ok,
STATUS_NA,
STATUS_NA,
cntr.tx_err,
cntr.tx_drop,
cntr.tx_err))
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, port_speed),
ns_diff(cntr.rx_err, old_cntr.rx_err),
ns_diff(cntr.rx_drop, old_cntr.rx_drop),
ns_diff(cntr.rx_ovr, old_cntr.rx_ovr),
ns_diff(cntr.tx_ok, old_cntr.tx_ok),
ns_brate(cntr.tx_byt, old_cntr.tx_byt, time_gap),
ns_util(cntr.tx_byt, old_cntr.tx_byt, time_gap, port_speed),
ns_diff(cntr.tx_err, old_cntr.tx_err),
ns_diff(cntr.tx_drop, old_cntr.tx_drop),
ns_diff(cntr.tx_ovr, old_cntr.tx_ovr)))

if use_json:
print self.table_as_json(table, print_all)
Expand Down Expand Up @@ -410,7 +367,7 @@ Examples:
print "\nFile '%s' does not exist" % cnstat_fqn_file
print "Did you run 'portstat -c -t %s' to record the counters via tag %s?\n" % (tag_name, tag_name)
else:
portstat.cnstat_print(cnstat_dict, use_json, print_all)
portstat.cnstat_diff_print(cnstat_dict, {}, use_json, print_all)
else:
#wait for the specified time and then gather the new stats and output the difference.
time.sleep(wait_time_in_seconds)
Expand Down