Skip to content
Open
Show file tree
Hide file tree
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
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
115 changes: 65 additions & 50 deletions sdk_generator/outputs/github_parser.json
Copy link
Collaborator

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)

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/genie/libs/parser/iosxe/__init__.py
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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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

167 changes: 167 additions & 0 deletions src/genie/libs/parser/iosxe/show_wireless.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'): {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could just use setdefault here


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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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