|
7 | 7 |
|
8 | 8 | try:
|
9 | 9 | import os
|
| 10 | + import re |
10 | 11 | import sys
|
11 | 12 | from collections import OrderedDict
|
12 | 13 |
|
@@ -108,162 +109,162 @@ def pcie_show():
|
108 | 109 | Id = item["id"]
|
109 | 110 | click.echo("bus:dev.fn %s:%s.%s - dev_id=0x%s, %s" % (Bus, Dev, Fn, Id, Name))
|
110 | 111 |
|
111 |
| -# Show PCIe AER status |
112 | 112 |
|
| 113 | +# PCIe AER stats helpers |
113 | 114 |
|
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 | +} |
118 | 122 |
|
119 | 123 |
|
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>" |
124 | 126 |
|
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) |
128 | 129 |
|
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) |
134 | 132 |
|
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) |
139 | 136 |
|
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) |
144 | 139 |
|
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) |
149 | 142 |
|
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) |
152 | 144 |
|
153 |
| - # Tabulate Header |
154 |
| - device_name = "%s:%s.%s\n0x%s" % (Bus, Dev, Fn, Id) |
155 |
| - header.append(device_name) |
156 | 145 |
|
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 | +] |
161 | 154 |
|
162 |
| - click.echo(tabulate(list(table.values()), header, tablefmt="grid")) |
163 | 155 |
|
| 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 |
164 | 169 |
|
165 |
| -@pcie_aer.command() |
166 |
| -@click.option('-nz', '--no-zero', is_flag=True) |
167 |
| -def fatal(no_zero): |
168 |
| - '''Show PCIe AER fatal attributes''' |
169 | 170 | statedb = SonicV2Connector()
|
170 | 171 | statedb.connect(statedb.STATE_DB)
|
171 |
| - header = ['AER - FATAL'] |
172 | 172 |
|
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'] |
175 | 173 | table = OrderedDict()
|
176 | 174 | for field in fields:
|
177 | 175 | table[field] = [field]
|
178 | 176 |
|
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) |
188 | 183 |
|
189 |
| - pcie_dev_key = "PCIE_DEVICE|0x%s|%s:%s.%s" % (Id, Bus, Dev, Fn) |
| 184 | + for pcie_dev_key in pcie_dev_list: |
190 | 185 | aer_attribute = statedb.get_all(statedb.STATE_DB, pcie_dev_key)
|
191 | 186 | if not aer_attribute:
|
192 | 187 | continue
|
193 | 188 |
|
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)): |
195 | 193 | continue
|
196 | 194 |
|
| 195 | + pcie_dev = pcie_dev_key.split("|")[1] |
| 196 | + Id = aer_attribute['id'] |
| 197 | + |
197 | 198 | # Tabulate Header
|
198 |
| - device_name = "%s:%s.%s\n0x%s" % (Bus, Dev, Fn, Id) |
| 199 | + device_name = "%s\n%s" % (pcie_dev, Id) |
199 | 200 | header.append(device_name)
|
200 | 201 |
|
201 | 202 | # Tabulate Row
|
202 | 203 | for field in fields:
|
203 |
| - key = "fatal|" + field |
| 204 | + key = severity + "|" + field |
204 | 205 | table[field].append(aer_attribute.get(key, 'NA'))
|
205 | 206 |
|
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") |
207 | 209 |
|
| 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] |
208 | 215 |
|
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("") |
217 | 219 |
|
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 |
223 | 224 |
|
224 |
| - resultInfo = platform_pcieutil.get_pcie_check() |
225 |
| - for item in resultInfo: |
226 |
| - if item["result"] == "Failed": |
227 |
| - continue |
228 | 225 |
|
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 |
233 | 234 |
|
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 |
238 | 235 |
|
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") |
241 | 242 |
|
242 |
| - # Tabulate Header |
243 |
| - device_name = "%s:%s.%s\n0x%s" % (Bus, Dev, Fn, Id) |
244 |
| - header.append(device_name) |
245 | 243 |
|
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 | + |
250 | 251 |
|
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") |
252 | 258 |
|
253 | 259 |
|
254 | 260 | @pcie_aer.command(name='all')
|
255 |
| -@click.option('-nz', '--no-zero', is_flag=True) |
| 261 | +@pcie_aer_click_options |
256 | 262 | @click.pass_context
|
257 |
| -def all_errors(ctx, no_zero): |
| 263 | +def all_errors(ctx, no_zero, device_key): |
258 | 264 | '''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") |
267 | 268 |
|
268 | 269 |
|
269 | 270 | # Show PCIE Vender ID and Device ID
|
|
0 commit comments