Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3fc5ebf
Added rogue ep/coop exception mac check for the CFD CSCwp64296
psureshb Dec 19, 2025
9234893
rogue exception macs detection failure after stateless reload test me…
psureshb Dec 22, 2025
4a06b4f
Revert "Added rogue ep/coop exception mac check for the CFD CSCwp64296"
psureshb Dec 22, 2025
12ba803
added test for rogue exception MACs missing due to missing presListen…
psureshb Dec 22, 2025
42f466b
added the defect CSCwp64296 documentation.
psureshb Dec 24, 2025
37d6c89
recommended action edited, cdets link replaced by cloudapps link
psureshb Dec 24, 2025
35de39e
added log files
psureshb Dec 24, 2025
40d9ea6
removed the log files in the directory
psureshb Dec 24, 2025
b52bc5f
Merge branch 'master' of github.com:psureshb/ACI-Pre-Upgrade-Validati…
psureshb Jan 19, 2026
34194e9
resolved merge conficts due to new method "apic_downgrade_compat_warn…
psureshb Jan 19, 2026
e921c6b
refactor: Update rogue_ep_coop_exception_mac_check logic and test cas…
psureshb Feb 11, 2026
51ab0b7
doc update
psureshb Feb 11, 2026
a03259b
Merge branch 'master' into psureshb
takishida Mar 5, 2026
d94df42
doc: Update the doc with proper conditions to check
takishida Mar 5, 2026
88a2d75
refactor: Update rogue_ep_coop_exception_mac_check logic and test cas…
psureshb Mar 11, 2026
5b412d7
refactor: Enhance rogue_ep_coop_exception_mac_check for improved vali…
psureshb Mar 12, 2026
efc43a6
Merge branch 'psureshb' of github.com:psureshb/ACI-Pre-Upgrade-Valida…
psureshb Mar 12, 2026
2754328
refactor: Revise rogue_ep_coop_exception_mac_check and documentation …
psureshb Mar 13, 2026
1ec83a3
fix: Update exception MAC API query and test cases for version accuracy
psureshb Mar 13, 2026
f1637c3
refactor: Update documentation and test cases for Rogue/COOP Exceptio…
psureshb Mar 16, 2026
1d642a6
fix: Clarify root cause of missing presListener objects for Rogue/COO…
psureshb Mar 16, 2026
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
32 changes: 31 additions & 1 deletion aci-preupgrade-validation-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -6053,6 +6053,35 @@ def auto_firmware_update_on_switch_check(cversion, tversion, **kwargs):

return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url)


@check_wrapper(check_title='Rogue EP Exception List missing on switches')
def rogue_ep_coop_exception_mac_check(cversion, tversion, **kwargs):
result = PASS
headers = ["Rogue Exception MACs Count", "presListener Count"]
data = []
recommended_action = 'Delete the affected exception list and create again'
doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#rogue-ep-exception-list-missing-on-switches'

exception_mac_api = 'fvRogueExceptionMac.json?rsp-subtree-include=count'
presListener_api = 'presListener.json?query-target-filter=and(eq(presListener.lstDn,"exceptcont"))&rsp-subtree-include=count'

# Check if there are any rogue exception MACs and insufficient presListener entries.
# Affected source version is in range [5.2(3e):6.0(3d)]. Fixed on 6.0(9e)+ and 6.1(4h)+.
if ((cversion.older_than("6.0(3d)")) and
(tversion.older_than("6.0(9e)") or ((tversion.same_as("6.1(1f)") or tversion.newer_than("6.1(1f)")) and tversion.older_than("6.1(4h)")))
) or cversion.same_as(tversion):
exception_macs = icurl('class', exception_mac_api)
exception_macs_count = int(exception_macs[0]['moCount']['attributes']['count'])
if exception_macs_count > 0:
presListener_response = icurl('class', presListener_api)
presListener_count = int(presListener_response[0]['moCount']['attributes']['count'])
if presListener_count >= 0 and presListener_count < 32:
log.info("Insufficient presListener entries ({} found) for {} exception MACs.".format(presListener_count, exception_macs_count))
result = FAIL_O
data.append([exception_macs_count, presListener_count])

return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url)

# ---- Script Execution ----


Expand Down Expand Up @@ -6216,7 +6245,8 @@ class CheckManager:
isis_database_byte_check,
configpush_shard_check,
auto_firmware_update_on_switch_check,

rogue_ep_coop_exception_mac_check,

]
ssh_checks = [
# General
Expand Down
18 changes: 17 additions & 1 deletion docs/docs/validations.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ Items | Defect | This Script
[ISIS DTEPs Byte Size][d27] | CSCwp15375 | :white_check_mark: | :no_entry_sign:
[Policydist configpushShardCont Crash][d28] | CSCwp95515 | :white_check_mark: | :no_entry_sign:
[Auto Firmware Update on Switch Discovery][d29] | CSCwe83941 | :white_check_mark: | :no_entry_sign:
[Rogue EP Exception List missing on switches][d30] | CSCwp64296 | :white_check_mark: | :no_entry_sign:

[d1]: #ep-announce-compatibility
[d2]: #eventmgr-db-size-defect-susceptibility
Expand Down Expand Up @@ -224,6 +225,8 @@ Items | Defect | This Script
[d27]: #isis-dteps-byte-size
[d28]: #policydist-configpushshardcont-crash
[d29]: #auto-firmware-update-on-switch-discovery
[d30]: #rogue-ep-exception-list-missing-on-switches


## General Check Details

Expand Down Expand Up @@ -2648,6 +2651,7 @@ Due to [CSCwp95515][59], upgrading to an affected version while having any `conf

If any instances of `configpushShardCont` are flagged by this script, Cisco TAC must be contacted to identify and resolve the underlying issue before performing the upgrade.


### Auto Firmware Update on Switch Discovery

[Auto Firmware Update on Switch Discovery][63] automatically upgrades a new switch to the target firmware version before registering it to the ACI fabric. This feature activates in three scenarios:
Expand All @@ -2668,6 +2672,17 @@ To avoid this risk, consider disabling Auto Firmware Update before upgrading to
This issue occurs because older switch firmware versions are not compatible with switch images 6.0(3) or newer. The APIC version is not a factor.


### Rogue EP Exception List missing on switches

The Rogue/COOP Exception List feature, introduced in 5.2(3), allows exclusion of specific MAC addresses from Rogue Endpoint Control and COOP Dampening. Initially, each MAC address had to be configured individually in each bridge domain. In 6.0(3), this feature was enhanced to support fabric-wide exception lists with wildcard options per bridge domain and the ability to exclude MAC addresses in L3Outs.

However, due to [CSCwp64296][64], when upgrading spine switches to version 6.0(3)+ from an older version with Rogue/COOP Exception Lists configured, some exception lists may not be pushed to the spine switches. As a result, the feature may stop functioning after the upgrade.

The root cause is that internal objects called `presListener` for Rogue/COOP Exception List, which publish the configuration from APICs to switches, may be missing on the APICs after an upgrade.

Recommended action: Delete the affected exception list and create it again. If needed, contact Cisco TAC to help recover missing `presListener` objects on APICs.


[0]: https://github.com/datacenter/ACI-Pre-Upgrade-Validation-Script
[1]: https://www.cisco.com/c/dam/en/us/td/docs/Website/datacenter/apicmatrix/index.html
[2]: https://www.cisco.com/c/en/us/support/switches/nexus-9000-series-switches/products-release-notes-list.html
Expand Down Expand Up @@ -2731,4 +2746,5 @@ To avoid this risk, consider disabling Auto Firmware Update before upgrading to
[60]: https://www.cisco.com/c/en/us/solutions/collateral/data-center-virtualization/application-centric-infrastructure/white-paper-c11-743951.html#Inter
[61]: https://www.cisco.com/c/en/us/solutions/collateral/data-center-virtualization/application-centric-infrastructure/white-paper-c11-743951.html#EnablePolicyCompression
[62]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwe83941
[63]: https://www.cisco.com/c/en/us/td/docs/dcn/aci/apic/all/apic-installation-aci-upgrade-downgrade/Cisco-APIC-Installation-ACI-Upgrade-Downgrade-Guide/m-auto-firmware-update.html
[63]: https://www.cisco.com/c/en/us/td/docs/dcn/aci/apic/all/apic-installation-aci-upgrade-downgrade/Cisco-APIC-Installation-ACI-Upgrade-Downgrade-Guide/m-auto-firmware-update.html
[64]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwp64296
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "0",
"dn": "",
"status": ""
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "32",
"dn": "",
"status": ""
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "1",
"dn": "",
"status": ""
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "0",
"dn": "",
"status": ""
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "27",
"dn": "",
"status": ""
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "31",
"dn": "",
"status": ""
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "5",
"dn": "",
"status": ""
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import os
import pytest
import logging
import importlib
from helpers.utils import read_data

log = logging.getLogger(__name__)
dir = os.path.dirname(os.path.abspath(__file__))

script = importlib.import_module("aci-preupgrade-validation-script")

test_function = "rogue_ep_coop_exception_mac_check"

exception_mac_api = 'fvRogueExceptionMac.json?rsp-subtree-include=count'

presListener_api = 'presListener.json'
presListener_api += '?query-target-filter=and(eq(presListener.lstDn,"exceptcont"))&rsp-subtree-include=count'

@pytest.mark.parametrize(
"icurl_outputs, tversion, cversion, expected_result",
[
# PASS cases
# Non affected tversion (fixed 6.1(4h)), affected cversion, no exception MACs
(
{exception_mac_api: read_data(dir, "no_rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.1(4h)",
"5.2(5e)",
script.PASS,
),
# Non affected tversion (fixed 6.0(9e)), affected cversion, no exception MACs
(
{exception_mac_api: read_data(dir, "no_rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.0(9e)",
"6.0(1h)",
script.PASS,
),
# Non affected cversion (too old), affected tversion, no exception MACs
(
{exception_mac_api: read_data(dir, "no_rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.0(5h)",
"5.2(1a)",
script.PASS,
),
# Non affected cversion (too new), affected tversion, no exception MACs
(
{exception_mac_api: read_data(dir, "no_rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.0(5h)",
"6.0(5h)",
script.PASS,
),
# Non affected cversion and tversion, no exception MACs
(
{exception_mac_api: read_data(dir, "no_rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.1(4h)",
"5.2(1a)",
script.PASS,
),
# Non affected cversion and tversion, with exception MACs
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.1(4h)",
"5.2(1a)",
script.PASS,
),
# Non affected cversion and tversion corner case, with exception MACs
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.0(8h)",
"6.0(3e)",
script.PASS,
),
# Affected edge cversion (5.2(3e)) and tversion (6.1(3f)), no exception MACs
(
{exception_mac_api: read_data(dir, "no_rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.1(3f)",
"5.2(3e)",
script.PASS,
),
# Affected edge cversion (6.0(2j)) and tversion (6.0(8h)), no exception MACs
(
{exception_mac_api: read_data(dir, "no_rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.0(8h)",
"6.0(2j)",
script.PASS,
),
# Affected cversion and tversion, no exception MACs
(
{exception_mac_api: read_data(dir, "no_rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.1(2f)",
"5.2(8g)",
script.PASS,
),
# Affected cversion and tversion, exception MACs present but 32 exceptcont listeners present
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.0(3e)",
"5.2(8g)",
script.PASS,
),
# Affected edge cversion and tversion, exception MACs present but 32 exceptcont listeners present
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.1(3f)",
"5.2(3e)",
script.PASS,
),
# FAIL cases
# Affected edge cversion (5.2(3e)) and tversion (6.1(3f)), exception MACs present, one missing exceptcont presListener
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont_one_missing.json")},
"6.1(3f)",
"5.2(3e)",
script.FAIL_O,
),
# Affected cversion and tversion, exception MACs present, 31 exceptcont presListeners (missing 1)
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont_31_missing.json")},
"6.0(3e)",
"5.2(8g)",
script.FAIL_O,
),
# Affected cversion and tversion, exception MACs present, many exceptcont presListeners missing
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont_many_missing.json")},
"6.1(2f)",
"5.2(8g)",
script.FAIL_O,
),
# Affected cversion and tversion, exception MACs present, no exceptcont presListeners
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont_32_missing.json")},
"6.1(2f)",
"5.2(8g)",
script.FAIL_O,
),
# Affected edge cversion (6.0(2j)) and tversion (6.0(8h)), exception MACs present, no exceptcont presListeners
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont_32_missing.json")},
"6.0(8h)",
"6.0(2j)",
script.FAIL_O,
),
# After APIC upgrade.
# Same cversion and tversion, exception MACs present, no exceptcont presListeners
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont_32_missing.json")},
"6.1(2f)",
"6.1(2f)",
script.FAIL_O,
),
# Same cversion and tversion, exception MACs present, exceptcont listeners missing
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont_31_missing.json")},
"6.1(2f)",
"6.1(2f)",
script.FAIL_O,
),
# Same cversion and tversion, exception MACs present, 32 exceptcont presListeners present
(
{exception_mac_api: read_data(dir, "rogue_mac_response.json"),
presListener_api: read_data(dir, "presListener_exceptcont.json")},
"6.1(2f)",
"6.1(2f)",
script.PASS,
),
],
)
def test_rogue_ep_coop_exception_mac_check(run_check, mock_icurl, tversion, cversion, expected_result):
"""Test rogue_ep_coop_exception_mac_check with various scenarios."""
result = run_check(cversion=script.AciVersion(cversion), tversion=script.AciVersion(tversion) if tversion else None)
assert result.result == expected_result