How dACLs Work: The Download Mechanism
Unlike static ACLs that you configure on the switch and reference by name, downloadable ACLs are dynamically created on the switch during 802.1X authentication. ISE sends a Cisco AVPair in the Access-Accept that tells the switch the name of the dACL to request. The switch then makes a second RADIUS request (an Authorization request using aaa authorization network default group radius) specifically to download the ACL content. ISE responds with the ACL entries. The switch installs the ACL in its ACL table and applies it to the authenticated session.
The Cisco AVPair in the Access-Accept looks like this:
Cisco-AVPair = "ACS:CiscoSecure-Defined-ACL=#ACSACL#-IP-Employee-Compliant-5f3a9b12"
The string after #ACSACL#-IP- is the dACL name as stored on the switch. The hash suffix (5f3a9b12) is ISE's internal version identifier for the ACL content. When the switch requests the ACL, it uses this full string as the ACL name.
This two-step process means there are two separate RADIUS exchanges that can both fail, and they fail independently.
Step 1: Verify the dACL Is Actually Being Applied
SW9300# show authentication sessions interface GigabitEthernet1/0/5 details
Sample output — dACL applied:
Server Policies:
Vlan Group: Vlan: 10
ACS ACL: xACSACLx-IP-Employee-Compliant-5f3a9b12
ACS ACL: xACSACLx-IP-Employee-Compliant-5f3a9b12 — the switch downloaded and is referencing this ACL for the session. The xACSACLx-IP- prefix is always present on IOS XE dACLs.
Sample output — no dACL applied:
Server Policies:
Vlan Group: Vlan: 10
No ACS ACL line means no dACL was applied to this session. Either ISE did not send the dACL AVPair, the download failed, or the ACL download succeeded but the switch could not install it.
Sample output — dACL name present but empty content:
Server Policies:
Vlan Group: Vlan: 10
ACS ACL: xACSACLx-IP-Employee-Compliant-5f3a9b12
Method status list:
Method State
dot1x Authc Success
The ACL name is present but you need to check the actual ACL content:
SW9300# show ip access-lists xACSACLx-IP-Employee-Compliant-5f3a9b12
Sample output — dACL with content:
Extended IP access list xACSACLx-IP-Employee-Compliant-5f3a9b12
10 permit udp any any eq 67 (DHCP)
20 permit udp any any eq 68
30 permit ip any 10.0.0.0 0.0.255.255
40 deny ip any any
Sample output — dACL exists but is empty:
Extended IP access list xACSACLx-IP-Employee-Compliant-5f3a9b12
An empty ACL means the switch created the ACL entry (from the AVPair name) but the content download failed or returned an empty ACL from ISE. No entries in the ACL means the ACL is empty — which on IOS XE does NOT mean permit all. An empty ACL applied to a session will deny all traffic matching the implicit deny.
Step 2: Check What ISE Sent in the Access-Accept
Enable debug and trigger a re-authentication:
SW9300# debug radius attributes
SW9300# clear authentication sessions interface GigabitEthernet1/0/5
Watch for the Access-Accept exchange:
Sample output — ISE sending dACL AVPair:
*Mar 19 11:30:10.441: RADIUS: Received from id 1645/55 10.0.0.10:1812 Access-Accept, len 242
*Mar 19 11:30:10.441: RADIUS: User-Name [1] 14 "CORP\jsmith"
*Mar 19 11:30:10.441: RADIUS: Session-Timeout [27] 6 36000
*Mar 19 11:30:10.441: RADIUS: Tunnel-Type [64] 6 VLAN(13)
*Mar 19 11:30:10.441: RADIUS: Tunnel-Medium-Type [65] 6 ALL_802(6)
*Mar 19 11:30:10.441: RADIUS: Tunnel-Pvt-Group-ID [81] 7 "10"
*Mar 19 11:30:10.441: RADIUS: Cisco AVPair [1] 72 "ACS:CiscoSecure-Defined-ACL=#ACSACL#-IP-Employee-Compliant-5f3a9b12"
The Cisco AVPair with ACS:CiscoSecure-Defined-ACL= is present. The switch will now make a second RADIUS request to download this ACL.
Sample output — ISE NOT sending dACL AVPair:
*Mar 19 11:30:10.441: RADIUS: Received from id 1645/55 10.0.0.10:1812 Access-Accept, len 168
*Mar 19 11:30:10.441: RADIUS: User-Name [1] 14 "CORP\jsmith"
*Mar 19 11:30:10.441: RADIUS: Session-Timeout [27] 6 36000
*Mar 19 11:30:10.441: RADIUS: Tunnel-Type [64] 6 VLAN(13)
*Mar 19 11:30:10.441: RADIUS: Tunnel-Medium-Type [65] 6 ALL_802(6)
*Mar 19 11:30:10.441: RADIUS: Tunnel-Pvt-Group-ID [81] 7 "10"
No Cisco AVPair — ISE sent the VLAN assignment but not the dACL reference. The authorization profile in ISE does not have a dACL configured. Move to Step 3 to check ISE policy.
Disable debug:
SW9300# undebug all
Step 3: Check ISE Authorization Profile dACL Configuration
Navigation: Policy > Policy Elements > Results > Authorization > Authorization Profiles > [Profile Name]
Under "Common Tasks," verify:
- DACL Name checkbox is checked
- The dACL name matches exactly (case-sensitive) the name of the dACL defined in the Downloadable ACLs section
- The dACL is defined for the correct IP version (IPv4 vs IPv6)
Navigation: Policy > Policy Elements > Results > Authorization > Downloadable ACLs
Verify the dACL entry exists and has content. Click the dACL name to view the ACL entries. Common errors:
- dACL name in the Authorization Profile references a name that does not exist in the Downloadable ACLs list (typo, case mismatch, name changed after the profile was built)
- dACL exists but has no entries (empty ACL)
- dACL has a syntax error (invalid wildcard masks, missing protocol keywords)
Test the dACL syntax using ISE's built-in validator: In the Downloadable ACL editor, click the "Check ACL Syntax" button. ISE validates the ACL entries and highlights syntax errors.
Verify which dACL ISE actually returned for this authentication:
Navigation: Operations > RADIUS > Live Logs > [Click authentication entry] > Other Attributes
Look for the ACS:CiscoSecure-Defined-ACL attribute in the Attributes section. The full dACL name ISE sent is listed there. If it does not match what you expect, the Authorization Rule is returning a different profile than intended.
Step 4: Confirm the Switch Has Authorization Configured for dACL Download
dACL download requires a separate AAA authorization configuration. If this is missing, the switch cannot request the ACL content from ISE — it receives the ACL name in the Access-Accept but cannot retrieve the ACL entries.
SW9300# show running-config | include aaa authorization
aaa authorization network default group ISE-SERVERS
This line must be present. Without aaa authorization network default group ISE-SERVERS, the switch has no mechanism to request the ACL content from RADIUS. The session will show the ACL name in show authentication sessions details but the ACL will be empty.
If this line is missing, add it:
SW9300(config)# aaa authorization network default group ISE-SERVERS
Then clear and re-authenticate to trigger a fresh dACL download:
SW9300# clear authentication sessions interface GigabitEthernet1/0/5
Step 5: Verify the dACL Is Actually Enforcing Traffic
A dACL can appear applied (visible in show authentication sessions details and show ip access-lists) but not actually enforcing traffic if ip device tracking is not functioning correctly or if the ACL is applied to the wrong interface context.
dACLs on IOS XE with authentication open mode are not enforced regardless of ACL content — authentication open allows all traffic through even when a dACL is applied. This is by design for monitor mode deployments.
Check:
SW9300# show running-config interface GigabitEthernet1/0/5 | include authentication open
authentication open
If authentication open is present, dACLs are not enforced on this port. For production enforcement, authentication open should be removed and replaced with authentication port-control auto. In phased deployments (monitor mode), authentication open is intentional during the assessment phase. For phased deployment strategy details, see Article 27 — Phased 802.1X Deployment Strategy for Enterprise Networks.
Verify the dACL has hit counters incrementing (confirming traffic is being matched):
SW9300# show ip access-lists xACSACLx-IP-Employee-Compliant-5f3a9b12
Sample output with hit counters:
Extended IP access list xACSACLx-IP-Employee-Compliant-5f3a9b12
10 permit udp any any eq 67 (18 matches)
20 permit udp any any eq 68 (18 matches)
30 permit ip any 10.0.0.0 0.0.255.255 (2847 matches)
40 deny ip any any (12 matches)
Hit counters incrementing on the deny rule (40 deny ip any any (12 matches)) means traffic is being blocked. If you expect this traffic to be permitted, the ACL content needs updating.
Zero hit counters on any rule means no traffic has matched that rule — either no traffic is being generated by the endpoint, or the dACL is not in the forwarding path for some reason.
Step 6: dACL Caching Issues
IOS XE caches downloaded ACLs. If the dACL content changes in ISE (you add or remove a rule), existing sessions on the switch continue to use the old cached version. New sessions pick up the updated ACL. This can cause inconsistent behavior where some endpoints have the old ACL and some have the new one.
To force all sessions to use the updated dACL, you must either:
-
Use CoA to trigger reauthentication — ISE sends a CoA-Request with reauthenticate action. The switch re-authenticates, downloads the new dACL version, and applies it. This is the production-safe approach.
-
Clear the cache manually:
SW9300# clear ip access-list counters
SW9300# clear authentication sessions
clear authentication sessions clears all active sessions, forcing re-authentication. All clients will briefly lose network access. Use during a maintenance window.
The dACL version is embedded in the ACL name (the hex hash suffix). When you modify and save a dACL in ISE, ISE increments the hash. The new dACL name is xACSACLx-IP-Employee-Compliant-6g4b0c23 (different suffix). The switch downloads the new ACL name on the next authentication.
Check cached ACLs:
SW9300# show ip access-lists | include xACSACLx
This lists all currently cached dACLs. If you see multiple versions of the same dACL (different hash suffixes), the cache has both old and new versions. Old version ACLs are cleaned up when all sessions using them terminate.
Step 7: dACL Size and Complexity Limits
IOS XE has limits on the size and complexity of downloadable ACLs. A dACL that exceeds these limits fails to install and the session may fall back to no ACL (permit all) or be placed in a failure state.
Practical limits for Catalyst 9300 running IOS XE 17.9.x:
- Maximum ACE (Access Control Entry) count per dACL: 256
- Maximum dACLs simultaneously installed: limited by TCAM capacity (hardware-dependent)
Check TCAM utilization:
SW9300# show platform hardware fed switch active fwd-asic resource tcam utilization
If TCAM is at or near capacity, new dACL downloads fail silently. The show authentication sessions details will show the ACS ACL name but show ip access-lists may not show the expected entries.
If your dACLs are large (50+ ACEs), consider restructuring them:
- Use object-group ACLs in ISE where possible to reduce ACE count
- Split complex policies into multiple authorization profiles with simpler, smaller ACLs
- Use VLAN-based segmentation to reduce the need for per-user ACLs
Step 8: IPv6 dACL Considerations
If endpoints are dual-stack (IPv4 and IPv6), you need separate dACLs for each address family. ISE supports both IP (IPv4) and IPv6 dACL types.
Check whether your sessions are using IPv6 traffic that is bypassing the IPv4 dACL:
SW9300# show authentication sessions interface GigabitEthernet1/0/5 details
If IPv6 addresses are showing in the session but only an IPv4 dACL is applied, IPv6 traffic is uncontrolled. Add an IPv6 dACL in ISE:
Navigation: Policy > Policy Elements > Results > Authorization > Downloadable ACLs
Click "Add." Set the ACL type to "IPv6." Add the appropriate ACEs. Reference this IPv6 dACL from the Authorization Profile alongside the IPv4 dACL.
Both dACLs are then sent in the Access-Accept and applied to the session — one for IPv4 traffic, one for IPv6.
Troubleshooting
Symptom: dACL downloads successfully and is visible in show ip access-lists, but endpoint traffic is not being blocked by deny rules
Cause: The endpoint is sending traffic sourced from a different IP address than what the dACL is written for. dACLs on IOS XE use the session's IP address as the source match context — if the ACL uses deny ip any any this should always match, but if the ACL uses specific source IP conditions (deny ip host 10.0.10.25 any), it will not match traffic from a secondary IP on the endpoint.
Fix: Check the endpoint's IP address vs what the dACL expects. Use broad source criteria in dACLs (e.g., permit ip any 10.0.0.0 0.0.255.255 rather than permit ip host 10.0.10.25 10.0.0.0 0.0.255.255). dACLs in Cisco 802.1X context are applied inbound on the port, matching source addresses of authenticated endpoints. Keep the source condition as any and control destination:
permit tcp any 10.0.1.0 0.0.0.255 eq 443
permit udp any any eq 53
deny ip any any
Also verify ip device tracking is enabled and has the correct IP for the endpoint:
SW9300# show ip device tracking all
If the endpoint's IP is not in the device tracking table, the dACL may not be properly bound to the session.
Symptom: dACL applies correctly on re-authentication but is missing from sessions that were established before the dACL was configured in ISE
Cause: Existing sessions were authenticated before the dACL existed in ISE. Those sessions received Access-Accepts without the dACL AVPair. The dACL is only applied to new authentications (or re-authentications via CoA).
Fix: Trigger a reauthentication for all existing sessions via CoA from ISE:
Navigation: Operations > RADIUS > Live Sessions
Select all active sessions on the affected switch (filter by NAS IP Address 10.0.99.1). Right-click and select "Reauthenticate." ISE sends CoA-Request messages to the switch for each session. Each re-authentication returns a new Access-Accept with the dACL AVPair, and the dACL is applied.
For large-scale re-authentication (hundreds of sessions), use ISE's Adaptive Network Control to trigger a bulk CoA rather than manually selecting sessions.
Symptom: dACL name appears in show authentication sessions but running show ip access-lists returns no matching ACL
Cause: The ACL download (second RADIUS exchange) failed or was never triggered. aaa authorization network default group radius may be missing, ISE may have rejected the authorization request, or the ACL name in ISE does not match the name referenced in the AVPair.
Fix: Enable debug for authorization:
SW9300# debug aaa authorization
SW9300# debug radius
SW9300# clear authentication sessions interface GigabitEthernet1/0/5
Watch for the second RADIUS exchange (the authorization request for the ACL):
*Mar 19 11:45:22.001: AAA/AUTHOR: auth_type 2 (network)
*Mar 19 11:45:22.002: RADIUS: Sending Access-Request for ACL download to 10.0.0.10
*Mar 19 11:45:22.145: RADIUS: Received Access-Accept with ACL entries
If you see the authorization request but no Access-Accept, ISE is not responding to the ACL download request. Check ISE for authorization policy errors. If you see no authorization request at all, aaa authorization network default group ISE-SERVERS is missing from the switch configuration.
After adding the missing authorization configuration:
SW9300(config)# aaa authorization network default group ISE-SERVERS
Clear and re-authenticate. The dACL should now download and install correctly.
What's Next: Article 25 — Troubleshooting 802.1X with show authentication sessions and debug Commands — the complete reference for IOS XE 802.1X diagnostic commands, covering every field in show authentication sessions details, the full set of useful debug combinations, and how to read RADIUS packet captures from the switch.