Skip to content

Commit 586bc75

Browse files
- Add '-d/--device' option for displaying AER stats of specified device
- Include UT cases for device, no-zero options
1 parent 35183f9 commit 586bc75

File tree

3 files changed

+328
-221
lines changed

3 files changed

+328
-221
lines changed

pcieutil/main.py

+106-105
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
try:
99
import os
10+
import re
1011
import sys
1112
from collections import OrderedDict
1213

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

111-
# Show PCIe AER status
112112

113+
# PCIe AER stats helpers
113114

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

119123

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

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

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

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

140-
Bus = item["bus"]
141-
Dev = item["dev"]
142-
Fn = item["fn"]
143-
Id = item["id"]
137+
if Dev > 31:
138+
self.fail('Invalid Dev number', param, ctx)
144139

145-
pcie_dev_key = "PCIE_DEVICE|0x%s|%s:%s.%s" % (Id, Bus, Dev, Fn)
146-
aer_attribute = statedb.get_all(statedb.STATE_DB, pcie_dev_key)
147-
if not aer_attribute:
148-
continue
140+
if Fn > 7:
141+
self.fail('Invalid Fn number', param, ctx)
149142

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

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

157-
# Tabulate Row
158-
for field in fields:
159-
key = "correctable|" + field
160-
table[field].append(aer_attribute.get(key, 'NA'))
146+
_pcie_aer_click_options = [
147+
click.option('-d', '--device', 'device_key',
148+
type=PcieDevice(),
149+
help="Display stats only for the specified device"),
150+
click.option('-nz', '--no-zero',
151+
is_flag=True,
152+
help="Display non-zero AER stats")
153+
]
161154

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

156+
def pcie_aer_click_options(func):
157+
for option in reversed(_pcie_aer_click_options):
158+
func = option(func)
159+
return func
160+
161+
162+
def pcie_aer_display(ctx, severity):
163+
device_key = ctx.params['device_key']
164+
no_zero = ctx.params['no_zero']
165+
header = ["AER - " + severity.upper().replace("_", "")]
166+
fields = aer_fields[severity]
167+
pcie_dev_list = list()
168+
dev_found = False
164169

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

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

179-
resultInfo = platform_pcieutil.get_pcie_check()
180-
for item in resultInfo:
181-
if item["result"] == "Failed":
182-
continue
183-
184-
Bus = item["bus"]
185-
Dev = item["dev"]
186-
Fn = item["fn"]
187-
Id = item["id"]
177+
if device_key:
178+
pcie_dev_list = ["PCIE_DEVICE|%s" % device_key]
179+
else:
180+
keys = statedb.keys(statedb.STATE_DB, "PCIE_DEVICE|*")
181+
if keys:
182+
pcie_dev_list = sorted(keys)
188183

189-
pcie_dev_key = "PCIE_DEVICE|0x%s|%s:%s.%s" % (Id, Bus, Dev, Fn)
184+
for pcie_dev_key in pcie_dev_list:
190185
aer_attribute = statedb.get_all(statedb.STATE_DB, pcie_dev_key)
191186
if not aer_attribute:
192187
continue
193188

194-
if no_zero and all(val=='0' for key, val in aer_attribute.items() if key.startswith('fatal')):
189+
if device_key:
190+
dev_found = True
191+
192+
if no_zero and all(val == '0' for key, val in aer_attribute.items() if key.startswith(severity)):
195193
continue
196194

195+
pcie_dev = pcie_dev_key.split("|")[1]
196+
Id = aer_attribute['id']
197+
197198
# Tabulate Header
198-
device_name = "%s:%s.%s\n0x%s" % (Bus, Dev, Fn, Id)
199+
device_name = "%s\n%s" % (pcie_dev, Id)
199200
header.append(device_name)
200201

201202
# Tabulate Row
202203
for field in fields:
203-
key = "fatal|" + field
204+
key = severity + "|" + field
204205
table[field].append(aer_attribute.get(key, 'NA'))
205206

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

210+
# Strip fields with no non-zero value
211+
if no_zero:
212+
for field in fields:
213+
if all(val == '0' for val in table[field][1:]):
214+
del table[field]
208215

209-
@pcie_aer.command()
210-
@click.option('-nz', '--no-zero', is_flag=True)
211-
def non_fatal(no_zero):
212-
'''Show PCIe AER non-fatal attributes '''
213-
statedb = SonicV2Connector()
214-
statedb.connect(statedb.STATE_DB)
215-
aer_attribute = {}
216-
header = ['AER - NONFATAL']
216+
if not (no_zero and (len(header) == 1)):
217+
if ctx.obj:
218+
click.echo("")
217219

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

224-
resultInfo = platform_pcieutil.get_pcie_check()
225-
for item in resultInfo:
226-
if item["result"] == "Failed":
227-
continue
228225

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

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

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

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

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

251-
click.echo(tabulate(list(table.values()), header, tablefmt="grid"))
252+
@pcie_aer.command()
253+
@pcie_aer_click_options
254+
@click.pass_context
255+
def non_fatal(ctx, no_zero, device_key):
256+
'''Show PCIe AER non-fatal attributes '''
257+
pcie_aer_display(ctx, "non_fatal")
252258

253259

254260
@pcie_aer.command(name='all')
255-
@click.option('-nz', '--no-zero', is_flag=True)
261+
@pcie_aer_click_options
256262
@click.pass_context
257-
def all_errors(ctx, no_zero):
263+
def all_errors(ctx, no_zero, device_key):
258264
'''Show all PCIe AER attributes '''
259-
ctx.forward(correctable)
260-
click.echo("")
261-
262-
ctx.forward(fatal)
263-
click.echo("")
264-
265-
ctx.forward(non_fatal)
266-
click.echo("")
265+
pcie_aer_display(ctx, "correctable")
266+
pcie_aer_display(ctx, "fatal")
267+
pcie_aer_display(ctx, "non_fatal")
267268

268269

269270
# Show PCIE Vender ID and Device ID

tests/mock_tables/state_db.json

+52-1
Original file line numberDiff line numberDiff line change
@@ -328,15 +328,17 @@
328328
"MUX_CABLE_TABLE|Ethernet12": {
329329
"state": "unknown"
330330
},
331-
"PCIE_DEVICE|0x0001|00:01.0": {
331+
"PCIE_DEVICE|00:01.0": {
332332
"correctable|BadDLLP": "0",
333333
"correctable|BadTLP": "0",
334+
"correctable|BadTLP": "1",
334335
"correctable|CorrIntErr": "0",
335336
"correctable|HeaderOF": "0",
336337
"correctable|NonFatalErr": "0",
337338
"correctable|Rollover": "0",
338339
"correctable|RxErr": "0",
339340
"correctable|TOTAL_ERR_COR": "0",
341+
"correctable|TOTAL_ERR_COR": "1",
340342
"correctable|Timeout": "0",
341343
"fatal|ACSViol": "0",
342344
"fatal|AtomicOpBlocked": "0",
@@ -356,6 +358,55 @@
356358
"fatal|Undefined": "0",
357359
"fatal|UnsupReq": "0",
358360
"fatal|UnxCmplt": "0",
361+
"id": "0x0001",
362+
"non_fatal|ACSViol": "0",
363+
"non_fatal|AtomicOpBlocked": "0",
364+
"non_fatal|BlockedTLP": "0",
365+
"non_fatal|CmpltAbrt": "0",
366+
"non_fatal|CmpltTO": "0",
367+
"non_fatal|DLP": "0",
368+
"non_fatal|ECRC": "0",
369+
"non_fatal|FCP": "0",
370+
"non_fatal|MalfTLP": "1",
371+
"non_fatal|RxOF": "0",
372+
"non_fatal|SDES": "0",
373+
"non_fatal|TLP": "0",
374+
"non_fatal|TLPBlockedErr": "0",
375+
"non_fatal|TOTAL_ERR_NONFATAL": "1",
376+
"non_fatal|UncorrIntErr": "0",
377+
"non_fatal|Undefined": "0",
378+
"non_fatal|UnsupReq": "0",
379+
"non_fatal|UnxCmplt": "0"
380+
},
381+
"PCIE_DEVICE|01:00.0": {
382+
"correctable|BadDLLP": "0",
383+
"correctable|BadTLP": "0",
384+
"correctable|CorrIntErr": "0",
385+
"correctable|HeaderOF": "0",
386+
"correctable|NonFatalErr": "0",
387+
"correctable|Rollover": "0",
388+
"correctable|RxErr": "1",
389+
"correctable|TOTAL_ERR_COR": "1",
390+
"correctable|Timeout": "0",
391+
"fatal|ACSViol": "0",
392+
"fatal|AtomicOpBlocked": "0",
393+
"fatal|BlockedTLP": "0",
394+
"fatal|CmpltAbrt": "0",
395+
"fatal|CmpltTO": "0",
396+
"fatal|DLP": "0",
397+
"fatal|ECRC": "0",
398+
"fatal|FCP": "0",
399+
"fatal|MalfTLP": "0",
400+
"fatal|RxOF": "0",
401+
"fatal|SDES": "0",
402+
"fatal|TLP": "0",
403+
"fatal|TLPBlockedErr": "0",
404+
"fatal|TOTAL_ERR_FATAL": "0",
405+
"fatal|UncorrIntErr": "0",
406+
"fatal|Undefined": "0",
407+
"fatal|UnsupReq": "0",
408+
"fatal|UnxCmplt": "0",
409+
"id": "0x0002",
359410
"non_fatal|ACSViol": "0",
360411
"non_fatal|AtomicOpBlocked": "0",
361412
"non_fatal|BlockedTLP": "0",

0 commit comments

Comments
 (0)