Skip to content

Commit

Permalink
- Add '-d/--device' option for displaying AER stats of specified device
Browse files Browse the repository at this point in the history
- Include UT cases for device, no-zero options
  • Loading branch information
ArunSaravananBalachandran committed Dec 10, 2020
1 parent 35183f9 commit 586bc75
Show file tree
Hide file tree
Showing 3 changed files with 328 additions and 221 deletions.
211 changes: 106 additions & 105 deletions pcieutil/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

try:
import os
import re
import sys
from collections import OrderedDict

Expand Down Expand Up @@ -108,162 +109,162 @@ def pcie_show():
Id = item["id"]
click.echo("bus:dev.fn %s:%s.%s - dev_id=0x%s, %s" % (Bus, Dev, Fn, Id, Name))

# Show PCIe AER status

# PCIe AER stats helpers

@cli.group(cls=clicommon.AliasedGroup)
def pcie_aer():
'''Display PCIe AER status'''
pass
aer_fields = {
"correctable": ['RxErr', 'BadTLP', 'BadDLLP', 'Rollover', 'Timeout', 'NonFatalErr', 'CorrIntErr', 'HeaderOF', 'TOTAL_ERR_COR'],
"fatal": ['Undefined', 'DLP', 'SDES', 'TLP', 'FCP', 'CmpltTO', 'CmpltAbrt', 'UnxCmplt', 'RxOF', 'MalfTLP', 'ECRC', 'UnsupReq',
'ACSViol', 'UncorrIntErr', 'BlockedTLP', 'AtomicOpBlocked', 'TLPBlockedErr', 'TOTAL_ERR_FATAL'],
"non_fatal": ['Undefined', 'DLP', 'SDES', 'TLP', 'FCP', 'CmpltTO', 'CmpltAbrt', 'UnxCmplt', 'RxOF', 'MalfTLP', 'ECRC', 'UnsupReq',
'ACSViol', 'UncorrIntErr', 'BlockedTLP', 'AtomicOpBlocked', 'TLPBlockedErr', 'TOTAL_ERR_NONFATAL']
}


@pcie_aer.command()
@click.option('-nz', '--no-zero', is_flag=True)
def correctable(no_zero):
'''Show PCIe AER correctable attributes'''
class PcieDevice(click.ParamType):
name = "<Bus>:<Dev>.<Fn>"

statedb = SonicV2Connector()
statedb.connect(statedb.STATE_DB)
header = ['AER - CORRECTABLE']
def convert(self, value, param, ctx):
match = re.match(r'([0-9A-Fa-f]{1,2}):([0-9A-Fa-f]{1,2})\.([0-9A-Fa-f])', value)

# AER - Correctable fields (9)
fields = ['RxErr', 'BadTLP', 'BadDLLP', 'Rollover', 'Timeout', 'NonFatalErr', 'CorrIntErr', 'HeaderOF', 'TOTAL_ERR_COR']
table = OrderedDict()
for field in fields:
table[field] = [field]
if not match:
self.fail('{} is not in <Bus>:<Dev>.<Fn> format'.format(value), param, ctx)

resultInfo = platform_pcieutil.get_pcie_check()
for item in resultInfo:
if item["result"] == "Failed":
continue
Bus, Dev, Fn = [int(val, 16) for val in match.groups()]
if Bus > 255:
self.fail('Invalid Bus number', param, ctx)

Bus = item["bus"]
Dev = item["dev"]
Fn = item["fn"]
Id = item["id"]
if Dev > 31:
self.fail('Invalid Dev number', param, ctx)

pcie_dev_key = "PCIE_DEVICE|0x%s|%s:%s.%s" % (Id, Bus, Dev, Fn)
aer_attribute = statedb.get_all(statedb.STATE_DB, pcie_dev_key)
if not aer_attribute:
continue
if Fn > 7:
self.fail('Invalid Fn number', param, ctx)

if no_zero and all(val=='0' for key, val in aer_attribute.items() if key.startswith('correctable')):
continue
return "%02x:%02x.%d" % (Bus, Dev, Fn)

# Tabulate Header
device_name = "%s:%s.%s\n0x%s" % (Bus, Dev, Fn, Id)
header.append(device_name)

# Tabulate Row
for field in fields:
key = "correctable|" + field
table[field].append(aer_attribute.get(key, 'NA'))
_pcie_aer_click_options = [
click.option('-d', '--device', 'device_key',
type=PcieDevice(),
help="Display stats only for the specified device"),
click.option('-nz', '--no-zero',
is_flag=True,
help="Display non-zero AER stats")
]

click.echo(tabulate(list(table.values()), header, tablefmt="grid"))

def pcie_aer_click_options(func):
for option in reversed(_pcie_aer_click_options):
func = option(func)
return func


def pcie_aer_display(ctx, severity):
device_key = ctx.params['device_key']
no_zero = ctx.params['no_zero']
header = ["AER - " + severity.upper().replace("_", "")]
fields = aer_fields[severity]
pcie_dev_list = list()
dev_found = False

@pcie_aer.command()
@click.option('-nz', '--no-zero', is_flag=True)
def fatal(no_zero):
'''Show PCIe AER fatal attributes'''
statedb = SonicV2Connector()
statedb.connect(statedb.STATE_DB)
header = ['AER - FATAL']

# AER - Fatal fields (18)
fields = ['Undefined', 'DLP', 'SDES', 'TLP', 'FCP', 'CmpltTO', 'CmpltAbrt', 'UnxCmplt', 'RxOF', 'MalfTLP', 'ECRC', 'UnsupReq', 'ACSViol', 'UncorrIntErr', 'BlockedTLP', 'AtomicOpBlocked', 'TLPBlockedErr', 'TOTAL_ERR_FATAL']
table = OrderedDict()
for field in fields:
table[field] = [field]

resultInfo = platform_pcieutil.get_pcie_check()
for item in resultInfo:
if item["result"] == "Failed":
continue

Bus = item["bus"]
Dev = item["dev"]
Fn = item["fn"]
Id = item["id"]
if device_key:
pcie_dev_list = ["PCIE_DEVICE|%s" % device_key]
else:
keys = statedb.keys(statedb.STATE_DB, "PCIE_DEVICE|*")
if keys:
pcie_dev_list = sorted(keys)

pcie_dev_key = "PCIE_DEVICE|0x%s|%s:%s.%s" % (Id, Bus, Dev, Fn)
for pcie_dev_key in pcie_dev_list:
aer_attribute = statedb.get_all(statedb.STATE_DB, pcie_dev_key)
if not aer_attribute:
continue

if no_zero and all(val=='0' for key, val in aer_attribute.items() if key.startswith('fatal')):
if device_key:
dev_found = True

if no_zero and all(val == '0' for key, val in aer_attribute.items() if key.startswith(severity)):
continue

pcie_dev = pcie_dev_key.split("|")[1]
Id = aer_attribute['id']

# Tabulate Header
device_name = "%s:%s.%s\n0x%s" % (Bus, Dev, Fn, Id)
device_name = "%s\n%s" % (pcie_dev, Id)
header.append(device_name)

# Tabulate Row
for field in fields:
key = "fatal|" + field
key = severity + "|" + field
table[field].append(aer_attribute.get(key, 'NA'))

click.echo(tabulate(list(table.values()), header, tablefmt="grid"))
if device_key and not dev_found:
ctx.exit("Device not found in DB")

# Strip fields with no non-zero value
if no_zero:
for field in fields:
if all(val == '0' for val in table[field][1:]):
del table[field]

@pcie_aer.command()
@click.option('-nz', '--no-zero', is_flag=True)
def non_fatal(no_zero):
'''Show PCIe AER non-fatal attributes '''
statedb = SonicV2Connector()
statedb.connect(statedb.STATE_DB)
aer_attribute = {}
header = ['AER - NONFATAL']
if not (no_zero and (len(header) == 1)):
if ctx.obj:
click.echo("")

# AER - Non-Fatal fields (18)
fields = ['Undefined', 'DLP', 'SDES', 'TLP', 'FCP', 'CmpltTO', 'CmpltAbrt', 'UnxCmplt', 'RxOF', 'MalfTLP', 'ECRC', 'UnsupReq', 'ACSViol', 'UncorrIntErr', 'BlockedTLP', 'AtomicOpBlocked', 'TLPBlockedErr', 'TOTAL_ERR_NONFATAL']
table = OrderedDict()
for field in fields:
table[field] = [field]
click.echo(tabulate(list(table.values()), header, tablefmt="grid"))
ctx.obj = True
else:
ctx.obj = False

resultInfo = platform_pcieutil.get_pcie_check()
for item in resultInfo:
if item["result"] == "Failed":
continue

Bus = item["bus"]
Dev = item["dev"]
Fn = item["fn"]
Id = item["id"]
# Show PCIe AER status
@cli.group(cls=clicommon.AliasedGroup)
@click.pass_context
def pcie_aer(ctx):
'''Display PCIe AER status'''
# Set True to insert a line between severities in 'all' context
ctx.obj = False
pass

pcie_dev_key = "PCIE_DEVICE|0x%s|%s:%s.%s" % (Id, Bus, Dev, Fn)
aer_attribute = statedb.get_all(statedb.STATE_DB, pcie_dev_key)
if not aer_attribute:
continue

if no_zero and all(val=='0' for key, val in aer_attribute.items() if key.startswith('non_fatal')):
continue
@pcie_aer.command()
@pcie_aer_click_options
@click.pass_context
def correctable(ctx, no_zero, device_key):
'''Show PCIe AER correctable attributes'''
pcie_aer_display(ctx, "correctable")

# Tabulate Header
device_name = "%s:%s.%s\n0x%s" % (Bus, Dev, Fn, Id)
header.append(device_name)

# Tabulate Row
for field in fields:
key = "non_fatal|" + field
table[field].append(aer_attribute.get(key, 'NA'))
@pcie_aer.command()
@pcie_aer_click_options
@click.pass_context
def fatal(ctx, no_zero, device_key):
'''Show PCIe AER fatal attributes'''
pcie_aer_display(ctx, "fatal")


click.echo(tabulate(list(table.values()), header, tablefmt="grid"))
@pcie_aer.command()
@pcie_aer_click_options
@click.pass_context
def non_fatal(ctx, no_zero, device_key):
'''Show PCIe AER non-fatal attributes '''
pcie_aer_display(ctx, "non_fatal")


@pcie_aer.command(name='all')
@click.option('-nz', '--no-zero', is_flag=True)
@pcie_aer_click_options
@click.pass_context
def all_errors(ctx, no_zero):
def all_errors(ctx, no_zero, device_key):
'''Show all PCIe AER attributes '''
ctx.forward(correctable)
click.echo("")

ctx.forward(fatal)
click.echo("")

ctx.forward(non_fatal)
click.echo("")
pcie_aer_display(ctx, "correctable")
pcie_aer_display(ctx, "fatal")
pcie_aer_display(ctx, "non_fatal")


# Show PCIE Vender ID and Device ID
Expand Down
53 changes: 52 additions & 1 deletion tests/mock_tables/state_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -328,15 +328,17 @@
"MUX_CABLE_TABLE|Ethernet12": {
"state": "unknown"
},
"PCIE_DEVICE|0x0001|00:01.0": {
"PCIE_DEVICE|00:01.0": {
"correctable|BadDLLP": "0",
"correctable|BadTLP": "0",
"correctable|BadTLP": "1",
"correctable|CorrIntErr": "0",
"correctable|HeaderOF": "0",
"correctable|NonFatalErr": "0",
"correctable|Rollover": "0",
"correctable|RxErr": "0",
"correctable|TOTAL_ERR_COR": "0",
"correctable|TOTAL_ERR_COR": "1",
"correctable|Timeout": "0",
"fatal|ACSViol": "0",
"fatal|AtomicOpBlocked": "0",
Expand All @@ -356,6 +358,55 @@
"fatal|Undefined": "0",
"fatal|UnsupReq": "0",
"fatal|UnxCmplt": "0",
"id": "0x0001",
"non_fatal|ACSViol": "0",
"non_fatal|AtomicOpBlocked": "0",
"non_fatal|BlockedTLP": "0",
"non_fatal|CmpltAbrt": "0",
"non_fatal|CmpltTO": "0",
"non_fatal|DLP": "0",
"non_fatal|ECRC": "0",
"non_fatal|FCP": "0",
"non_fatal|MalfTLP": "1",
"non_fatal|RxOF": "0",
"non_fatal|SDES": "0",
"non_fatal|TLP": "0",
"non_fatal|TLPBlockedErr": "0",
"non_fatal|TOTAL_ERR_NONFATAL": "1",
"non_fatal|UncorrIntErr": "0",
"non_fatal|Undefined": "0",
"non_fatal|UnsupReq": "0",
"non_fatal|UnxCmplt": "0"
},
"PCIE_DEVICE|01:00.0": {
"correctable|BadDLLP": "0",
"correctable|BadTLP": "0",
"correctable|CorrIntErr": "0",
"correctable|HeaderOF": "0",
"correctable|NonFatalErr": "0",
"correctable|Rollover": "0",
"correctable|RxErr": "1",
"correctable|TOTAL_ERR_COR": "1",
"correctable|Timeout": "0",
"fatal|ACSViol": "0",
"fatal|AtomicOpBlocked": "0",
"fatal|BlockedTLP": "0",
"fatal|CmpltAbrt": "0",
"fatal|CmpltTO": "0",
"fatal|DLP": "0",
"fatal|ECRC": "0",
"fatal|FCP": "0",
"fatal|MalfTLP": "0",
"fatal|RxOF": "0",
"fatal|SDES": "0",
"fatal|TLP": "0",
"fatal|TLPBlockedErr": "0",
"fatal|TOTAL_ERR_FATAL": "0",
"fatal|UncorrIntErr": "0",
"fatal|Undefined": "0",
"fatal|UnsupReq": "0",
"fatal|UnxCmplt": "0",
"id": "0x0002",
"non_fatal|ACSViol": "0",
"non_fatal|AtomicOpBlocked": "0",
"non_fatal|BlockedTLP": "0",
Expand Down
Loading

0 comments on commit 586bc75

Please sign in to comment.