-
Notifications
You must be signed in to change notification settings - Fork 414
Added IOSXE parser for 'show wireless iot-coexistence summary' #972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| -------------------------------------------------------------------------------- | ||
| New Parser | ||
| -------------------------------------------------------------------------------- | ||
|
|
||
| * IOSXE | ||
| * ShowWirelessIotCoexistenceSummary | ||
| * Added parser for 'show wireless iot-coexistence summary' | ||
| * Parses AP IoT coexistence information including admin/oper states | ||
| * Supports APs with and without IoT counter data |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| from genie import abstract | ||
| abstract.declare_token(os='iosxe') | ||
|
|
||
|
|
||
| from .show_wireless import ShowWirelessIotCoexistenceSummary | ||
|
|
||
|
Comment on lines
+4
to
+6
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is unnecessary. Our library abstraction mechanism handles importing parsers. Please remove this |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5660,3 +5660,170 @@ def cli(self, output=None): | |
| continue | ||
|
|
||
| return ret_dict | ||
|
|
||
| # ============================================= | ||
| # Schema for 'show wireless iot-coexistence summary' | ||
| # ============================================= | ||
| class ShowWirelessIotCoexistenceSummarySchema(MetaParser): | ||
| """Schema for show wireless iot-coexistence summary""" | ||
|
|
||
| schema = { | ||
| Optional('ap_list'): { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The top-level key in a schema shouldn't be Optional. You need at least one static key that will always be there if a match has been made |
||
| Any(): { | ||
| 'radio_mac': str, | ||
| 'coex_admin_state': str, | ||
| 'coex_oper_state': str, | ||
| 'iot_counters': { | ||
| Optional('tx_pkts'): int, | ||
| Optional('rx_pkts'): int, | ||
| Optional('crc_errors'): int, | ||
| Optional('low_pri_requests'): int, | ||
| Optional('high_pri_requests'): int, | ||
| Optional('low_pri_denied'): int, | ||
| Optional('high_pri_denied'): int, | ||
| Optional('low_pri_tx_abort'): int, | ||
| Optional('high_pri_tx_abort'): int | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| # ============================================= | ||
| # Parser for 'show wireless iot-coexistence summary' | ||
| # ============================================= | ||
| class ShowWirelessIotCoexistenceSummary(ShowWirelessIotCoexistenceSummarySchema): | ||
| """Parser for show wireless iot-coexistence summary | ||
|
|
||
| Sample output: | ||
|
|
||
| # show wireless iot-coexistence summary | ||
| AP Name Radio MAC Admin State Oper State Tx Pkts Rx Pkts CRC Errors Low Pri Requests High Pri Requests Low Pri Denied High Pri Denied Low Pri Tx Abort High Pri Tx Abort | ||
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| APCC6E.2AFC.B310 c418.fcbe.41e0 Enabled Enabled 11546 11490 0 386 386 38 19 14 11 | ||
| AP3C57.31C5.983C 4ca6.4d23.0f60 Disabled Disabled | ||
| APCC9C.3EE7.4F50 00df.1d87.6d60 Enabled Not Supported | ||
|
|
||
| Empty output: | ||
|
|
||
| # show wireless iot-coexistence summary | ||
| AP Name Radio MAC Admin State Oper State Tx Pkts Rx Pkts CRC Errors Low Pri Requests High Pri Requests Low Pri Denied High Pri Denied Low Pri Tx Abort High Pri Tx Abort | ||
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| """ | ||
|
|
||
| cli_command = 'show wireless iot-coexistence summary' | ||
|
|
||
| def cli(self, output=None): | ||
| """Parsing logic for CLI command | ||
|
|
||
| Args: | ||
| output (str): Command output. If None, executes command on device. | ||
|
|
||
| Returns: | ||
| dict: Parsed AP data with COEX states and counters. | ||
| Returns {} if no APs found (valid empty state). | ||
| """ | ||
|
|
||
| if output is None: | ||
| output = self.device.execute(self.cli_command) | ||
|
|
||
| # Initialize result dictionary | ||
| show_wireless_iot_coexistence_summary_dict = {} | ||
|
|
||
| # Regex patterns for parsing | ||
| # Pattern 1: AP(s) with counters | ||
| # Example: APCC6E.2AFC.B310 c418.fcbe.41e0 Enabled Enabled 11546 11490 0 386 386 38 19 14 11 | ||
| p_ap_with_counters = re.compile( | ||
| r'^(?P<ap_name>\S+)\s+' | ||
| r'(?P<radio_mac>[\da-f]{4}\.[\da-f]{4}\.[\da-f]{4})\s+' | ||
| r'(?P<admin_state>\S+)\s+' | ||
| r'(?P<oper_state>(?:\S+\s+)*?\S+?)\s+' | ||
| r'(?P<tx_pkts>\d+)\s+' | ||
| r'(?P<rx_pkts>\d+)\s+' | ||
| r'(?P<crc_errors>\d+)\s+' | ||
| r'(?P<low_pri_requests>\d+)\s+' | ||
| r'(?P<high_pri_requests>\d+)\s+' | ||
| r'(?P<low_pri_denied>\d+)\s+' | ||
| r'(?P<high_pri_denied>\d+)\s+' | ||
| r'(?P<low_pri_tx_abort>\d+)\s+' | ||
| r'(?P<high_pri_tx_abort>\d+)\s*$' | ||
| ) | ||
|
|
||
| # Pattern 2: AP(s) without counters | ||
| # Example: AP3C57.31C5.983C 4ca6.4d23.0f60 Disabled Disabled | ||
| # Example: APCC9C.3EE7.4F50 00df.1d87.6d60 Enabled Not Supported | ||
| p_ap_without_counters = re.compile( | ||
| r'^(?P<ap_name>\S+)\s+' | ||
| r'(?P<radio_mac>[\da-f]{4}\.[\da-f]{4}\.[\da-f]{4})\s+' | ||
| r'(?P<admin_state>\S+)\s+' | ||
| r'(?P<oper_state>.+?)\s*$' | ||
| ) | ||
|
|
||
| # Pattern 3: Separator line (marks start of data section) | ||
| p_separator = re.compile(r'^-{20,}') | ||
|
|
||
| # State flag to track when we're past the header | ||
| data_section_started = False | ||
|
|
||
| # Parse output line by line | ||
| for line in output.splitlines(): | ||
| line = line.strip() | ||
|
|
||
| # Skip empty lines | ||
| if not line: | ||
| continue | ||
|
|
||
| # Detect separator line | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These comments should be examples of what's being matched. It's a lot easier to debug a parser when you can quickly reference the line it's matching |
||
| if p_separator.match(line): | ||
| data_section_started = True | ||
| continue | ||
|
|
||
| # Only process lines after separator | ||
| if not data_section_started: | ||
| continue | ||
|
|
||
| # Try matching AP with counters first | ||
| match = p_ap_with_counters.match(line) | ||
| if match: | ||
| # Initialize ap_list if first AP found | ||
| if 'ap_list' not in show_wireless_iot_coexistence_summary_dict: | ||
| show_wireless_iot_coexistence_summary_dict['ap_list'] = {} | ||
|
Comment on lines
+5789
to
+5790
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could just use |
||
|
|
||
| group = match.groupdict() | ||
| ap_name = group['ap_name'] | ||
| show_wireless_iot_coexistence_summary_dict['ap_list'][ap_name] = { | ||
| 'radio_mac': group['radio_mac'], | ||
| 'coex_admin_state': group['admin_state'], | ||
| 'coex_oper_state': group['oper_state'], | ||
| 'iot_counters': { | ||
| 'tx_pkts': int(group['tx_pkts']), | ||
| 'rx_pkts': int(group['rx_pkts']), | ||
| 'crc_errors': int(group['crc_errors']), | ||
| 'low_pri_requests': int(group['low_pri_requests']), | ||
| 'high_pri_requests': int(group['high_pri_requests']), | ||
| 'low_pri_denied': int(group['low_pri_denied']), | ||
| 'high_pri_denied': int(group['high_pri_denied']), | ||
| 'low_pri_tx_abort': int(group['low_pri_tx_abort']), | ||
| 'high_pri_tx_abort': int(group['high_pri_tx_abort']) | ||
| } | ||
| } | ||
| continue | ||
|
|
||
| # Try matching AP without counters | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
| match = p_ap_without_counters.match(line) | ||
| if match: | ||
| # Initialize ap_list if first AP found | ||
| if 'ap_list' not in show_wireless_iot_coexistence_summary_dict: | ||
| show_wireless_iot_coexistence_summary_dict['ap_list'] = {} | ||
|
Comment on lines
+5816
to
+5817
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
|
|
||
| group = match.groupdict() | ||
| ap_name = group['ap_name'] | ||
| show_wireless_iot_coexistence_summary_dict['ap_list'][ap_name] = { | ||
| 'radio_mac': group['radio_mac'], | ||
| 'coex_admin_state': group['admin_state'], | ||
| 'coex_oper_state': group['oper_state'].strip(), | ||
| 'iot_counters': {} | ||
| } | ||
|
|
||
| # Return empty dict if no APs found, otherwise return parsed data | ||
| return show_wireless_iot_coexistence_summary_dict | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| expected_output = { | ||
| 'ap_list': { | ||
| 'APCC6E.2AFC.B310': { | ||
| 'radio_mac': 'c418.fcbe.41e0', | ||
| 'coex_admin_state': 'Enabled', | ||
| 'coex_oper_state': 'Enabled', | ||
| 'iot_counters': { | ||
| 'tx_pkts': 11546, | ||
| 'rx_pkts': 11490, | ||
| 'crc_errors': 0, | ||
| 'low_pri_requests': 386, | ||
| 'high_pri_requests': 386, | ||
| 'low_pri_denied': 38, | ||
| 'high_pri_denied': 19, | ||
| 'low_pri_tx_abort': 14, | ||
| 'high_pri_tx_abort': 11 | ||
| } | ||
| }, | ||
| 'AP3C57.31C5.983C': { | ||
| 'radio_mac': '4ca6.4d23.0f60', | ||
| 'coex_admin_state': 'Disabled', | ||
| 'coex_oper_state': 'Disabled', | ||
| 'iot_counters': {} | ||
| }, | ||
| 'APCC9C.3EE7.4F50': { | ||
| 'radio_mac': '00df.1d87.6d60', | ||
| 'coex_admin_state': 'Enabled', | ||
| 'coex_oper_state': 'Not Supported', | ||
| 'iot_counters': {} | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| AP Name Radio MAC Admin State Oper State Tx Pkts Rx Pkts CRC Errors Low Pri Requests High Pri Requests Low Pri Denied High Pri Denied Low Pri Tx Abort High Pri Tx Abort | ||
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| APCC6E.2AFC.B310 c418.fcbe.41e0 Enabled Enabled 11546 11490 0 386 386 38 19 14 11 | ||
| AP3C57.31C5.983C 4ca6.4d23.0f60 Disabled Disabled | ||
| APCC9C.3EE7.4F50 00df.1d87.6d60 Enabled Not Supported |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| expected_output = { | ||
| 'ap_list': { | ||
| 'AP3C57.31C5.983C': { | ||
| 'radio_mac': '4ca6.4d23.0f60', | ||
| 'coex_admin_state': 'Disabled', | ||
| 'coex_oper_state': 'Not supported', | ||
| 'iot_counters': {} | ||
| }, | ||
| 'APCC9C.3EE7.4F50': { | ||
| 'radio_mac': 'ecf4.0c0e.46e0', | ||
| 'coex_admin_state': 'Disabled', | ||
| 'coex_oper_state': 'Disabled', | ||
| 'iot_counters': {} | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| | IOT COUNTERS | ||
| AP Name Radio MAC Coex Admin Coex Oper | Tx pkts Rx pkts CRC Low Pri High Pri Low Pri High Pri Low Pri High Pri | ||
| State State | errors requests requests denied denied Tx abort Tx abort | ||
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| AP3C57.31C5.983C 4ca6.4d23.0f60 Disabled Not supported | ||
| APCC9C.3EE7.4F50 ecf4.0c0e.46e0 Disabled Disabled |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| expected_output = { | ||
| 'ap_list': { | ||
| 'AP3C57.31C5.983C': { | ||
| 'radio_mac': '4ca6.4d23.0f60', | ||
| 'coex_admin_state': 'Disabled', | ||
| 'coex_oper_state': 'Not supported', | ||
| 'iot_counters': {} | ||
| }, | ||
| 'APCC6E.2AFC.B8F0': { | ||
| 'radio_mac': 'c418.fcbe.3fe0', | ||
| 'coex_admin_state': 'Enabled', | ||
| 'coex_oper_state': 'Enabled', | ||
| 'iot_counters': { | ||
| 'tx_pkts': 149, | ||
| 'rx_pkts': 145, | ||
| 'crc_errors': 0, | ||
| 'low_pri_requests': 29, | ||
| 'high_pri_requests': 29, | ||
| 'low_pri_denied': 2, | ||
| 'high_pri_denied': 1, | ||
| 'low_pri_tx_abort': 1, | ||
| 'high_pri_tx_abort': 0 | ||
| } | ||
| }, | ||
| 'APCC6E.2AFC.B310': { | ||
| 'radio_mac': 'c418.fcbe.41e0', | ||
| 'coex_admin_state': 'Enabled', | ||
| 'coex_oper_state': 'Enabled', | ||
| 'iot_counters': { | ||
| 'tx_pkts': 46, | ||
| 'rx_pkts': 45, | ||
| 'crc_errors': 0, | ||
| 'low_pri_requests': 9, | ||
| 'high_pri_requests': 9, | ||
| 'low_pri_denied': 0, | ||
| 'high_pri_denied': 0, | ||
| 'low_pri_tx_abort': 0, | ||
| 'high_pri_tx_abort': 0 | ||
| } | ||
| }, | ||
| 'APCC9C.3EE7.4F50': { | ||
| 'radio_mac': 'ecf4.0c0e.46e0', | ||
| 'coex_admin_state': 'Enabled', | ||
| 'coex_oper_state': 'Enabled', | ||
| 'iot_counters': { | ||
| 'tx_pkts': 1358, | ||
| 'rx_pkts': 1337, | ||
| 'crc_errors': 0, | ||
| 'low_pri_requests': 142, | ||
| 'high_pri_requests': 142, | ||
| 'low_pri_denied': 14, | ||
| 'high_pri_denied': 7, | ||
| 'low_pri_tx_abort': 4, | ||
| 'high_pri_tx_abort': 2 | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| | IOT COUNTERS | ||
| AP Name Radio MAC Coex Admin Coex Oper | Tx pkts Rx pkts CRC Low Pri High Pri Low Pri High Pri Low Pri High Pri | ||
| State State | errors requests requests denied denied Tx abort Tx abort | ||
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| AP3C57.31C5.983C 4ca6.4d23.0f60 Disabled Not supported | ||
| APCC6E.2AFC.B8F0 c418.fcbe.3fe0 Enabled Enabled 149 145 0 29 29 2 1 1 0 | ||
| APCC6E.2AFC.B310 c418.fcbe.41e0 Enabled Enabled 46 45 0 9 9 0 0 0 0 | ||
| APCC9C.3EE7.4F50 ecf4.0c0e.46e0 Enabled Enabled 1358 1337 0 142 142 14 7 4 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You no longer need to include changes to
github_parser.json(and honestly I thought we had added this file to the .gitignore)