on 05-19-2012 11:30 PM
In preparing for CiscoLive! in San Diego, I am provisioning our access layer 3560-E switches. Since things have a tendency to change a lot at an event like CiscoLive! I thought it would be best to make sure our port descriptions are always up-to-date when it comes to reflecting what devices are connected. To help me do that, I wrote up this small EEM applet policy. It will update the port's description based on the CDP neighbor learned on that port. This policy requires EEM 3.2, so you're looking at 12.2(55)SE or higher for the 3560s. It will also work on 3750s and ISR G2 routers running 15.x code.
event manager applet update-port-description
event neighbor-discovery interface regexp GigabitEthernet.* cdp add
action 1.0 cli command "enable"
action 2.0 cli command "config t"
action 3.0 cli command "interface $_nd_local_intf_name"
action 4.0 cli command "description $_nd_cdp_entry_name:$_nd_port_id"
The result of this will be a description like the following on switch ports:
description SDCC_IDF_1.11:TenGigabitEthernet0/1
@derek-shnosh Can you walk me through that? It says "Debug EEM action cli debugging is on" I do a "clear cdp table" but nothing shows?
After you enable debugging, you have to turn on terminal monitoring with term mon.
Try to configure an event manager user with priv-15.
username eem_svc priv 15 algorithm-type scrypt secret <SUPER_SECRET_PASSWORD>
event manager session cli username "eem_svc"
If you're using TACACS/RADIUS, you may also need to adjust your aaa authorization priorities so the EEM user doesn't try to authorize against TACACS/RADIUS.
aaa authentication login default group ISE-TACACS local
aaa authentication login CONSOLE local
aaa authorization console
aaa authorization exec default local group ISE-TACACS if-authenticated
aaa authorization commands 15 default local group ISE-TACACS if-authenticated
Notice how the aaa authentication priority is ISE-TACACS > local and the aaa authorization priority is local > ISE-TACACS.
To provide a follow up, @Ethan Campbell and I sync'ed up via discord and got an EEM applet working based on his requirements with the following script.
event manager applet cdp_desc
event neighbor-discovery interface regexp .* cdp add
action 00.00 cli command "enable"
action 01.00 comment "Get shorthand for local interface..."
action 01.01 string range "$_nd_local_intf_name" 0 2
action 01.02 set local_type "$_string_result"
action 01.03 regexp "[/0-9]+$" "$_nd_local_intf_name" local_int
action 02.00 comment "Get shorthand for neighbor interface..."
action 02.01 string range "$_nd_port_id" 0 2
action 02.02 set nei_intf_type "$_string_result"
action 02.03 regexp "[/0-9]+$" "$_nd_port_id" nei_int
action 03.00 comment "Accommodate mgmt0 interfaces..."
action 03.01 if $neiint eq "0"
action 03.02 set nei_int "mgmt"
action 03.03 end
action 04.00 comment "Get shorthand for hostname (strip domain name)..."
action 04.01 regexp "^[^\.\(]+" "$_nd_cdp_entry_name" nei
action 05.00 comment "Build a new interface description based on neighbor information..."
action 05.01 set newdesc "$nei:$nei_intf_type$nei_int"
action 06.00 comment "Check current description on local interface..."
action 06.01 cli command "show int $_nd_local_intf_name | i ^[\ ]*[Dd]escription"
action 06.02 set output "$_cli_result"
action 06.03 regexp "^\ *[Dd]escription" "$output"
action 06.04 if $_regexp_result ne "1"
action 06.05 set olddesc "<none>"
action 06.06 else
action 06.07 set i "0"
action 06.08 foreach line "$output" "\n"
action 06.09 increment i
action 06.10 if $i eq "1"
action 06.11 string trim "$line"
action 06.12 set line "$_string_result"
action 06.13 regexp "^\ *[Dd]escription:\ *(.*)" "$line" match olddesc
action 06.14 end
action 06.15 end
action 06.16 end
action 07.00 comment "Update description, if necessary..."
action 07.01 if $newdesc eq $olddesc
action 07.02 syslog msg " ## New CDP neighbor on $local_type$local_int ($newdesc), description does not require updating."
action 07.03 else
action 07.04 syslog msg " ## New CDP neighbor on $local_type$local_int ($newdesc), updating description (was: $olddesc)."
action 07.05 cli command "conf t"
action 07.06 cli command "int $_nd_local_intf_name"
action 07.07 cli command "desc $newdesc"
action 07.08 cli command "end"
action 07.09 cli command "write mem" pattern "confirm|#"
action 07.10 cli command ""
action 07.11 end
Here is modified script that works well in our environment
Script designed to automatically update interface descriptions on a switch/router based on CDP (Cisco Discovery Protocol) neighbor information. Let me break it down step by step:
What the script does
Trigger: It runs whenever a new CDP neighbor is discovered on an interface (event neighbor-discovery interface regexp .*E*[0-9\/]+$ cdp add).
Neighbor validation: It checks if the neighbor device is a Cisco platform (router, switch, UCS, Nexus, etc.) using regex on the CDP platform string.
Hostname processing: It trims the neighbor’s DNS name to just the hostname (removes domain suffix).
Interface type parsing: It extracts the neighbor’s interface type (e.g., GigabitEthernet, TenGigabitEthernet, FortyGigabitEthernet, etc.) and converts it into a short format (Gi, Te, Fo, etc.) with the port number.
Local interface classification: It inspects the local interface configuration to see if it has:
Root guard → marks as "DOWNLINK"
QoS policy → marks as "UPLINK"
Description building: It constructs a new description string in the format:
<UPLINK/DOWNLINK> - <NeighborHostname> - <NeighborInterface>
Change check: If the current description already matches the new one, it does nothing (logs a syslog message saying no change was needed).
Update action: If different, it enters interface configuration mode and updates the description, then logs the change to syslog.
Example outcome
Suppose interface GigabitEthernet1/0/1 connects to a neighbor switch named SW1 on its GigabitEthernet0/24 port.
Local interface has root guard → "DOWNLINK"
New description becomes:
DOWNLINK - SW1 - Gi0/24
The script applies this description automatically.
event manager applet auto-update-host-description authorization bypass
description "Auto-update port-description based on CDP neighbor info"
event neighbor-discovery interface regexp .*E*[0-9\/]+$ cdp add
action 0.0 comment "Event line regexp: Decide which interface to auto-update description on"
action 1.0 comment "Verify CDP neighbor to be Switch or Router"
action 1.1 comment "auto port description script Version 001"
action 1.2 regexp "(cisco|AIR|UCS|N5K|N9K)" "$_nd_cdp_platform"
action 1.3 if $_regexp_result eq "1"
action 1.4 comment "Trim domain name"
action 1.5 regexp "^([^\.]+)" "$_nd_cdp_entry_name" match dnsname
action 4.0 regexp "([a-zA-z-]*)([0-9\/]*)" "$_nd_port_id" portm portn portnum
action 4.10 regexp "GigabitEthernet" "$_nd_port_id"
action 4.11 if $_regexp_result eq "1"
action 4.12 set port_type "Gi$portnum"
action 4.13 end
action 4.14 regexp "TenGigabitEthernet" "$_nd_port_id"
action 4.15 if $_regexp_result eq "1"
action 4.16 set port_type "Te$portnum"
action 4.17 end
action 4.18 regexp "TwentyFiveGigE" "$_nd_port_id"
action 4.19 if $_regexp_result eq "1"
action 4.20 set port_type "Twe$portnum"
action 4.21 end
action 4.22 regexp "HundredGigE" "$_nd_port_id"
action 4.23 if $_regexp_result eq "1"
action 4.24 set port_type "Hu$portnum"
action 4.25 end
action 4.26 regexp "Br-Ethernet" "$_nd_port_id"
action 4.27 if $_regexp_result eq "1"
action 4.28 set port_type "Eth$portnum"
action 4.29 end
action 4.30 regexp "TwoGigabitEthernet" "$_nd_port_id"
action 4.31 if $_regexp_result eq "1"
action 4.32 set port_type "Tw$portnum"
action 4.33 end
action 4.34 regexp "FortyGigabitEthernet" "$_nd_port_id"
action 4.35 if $_regexp_result eq "1"
action 4.36 set port_type "Fo$portnum"
action 4.37 end
action 4.99 set int "$port_type"
action 4.5 regexp "([a-zA-z]*)" "$_nd_port_id"
action 5.10 comment "Check interface config for root guard or qos"
action 5.14 cli command "enable"
action 5.15 cli command "config t"
action 5.16 cli command "do show running-config interface $_nd_local_intf_name | i guard root|QOS"
action 5.17 regexp "Interface: (.*)" "$_cli_result" match $_nd_local_intf_name
action 5.18 set interface_config "$_cli_result"
action 5.19 set plat2 ""
action 5.20 regexp "guard root" "$interface_config"
action 5.21 if $_regexp_result eq "1"
action 5.22 set plat2 "DOWNLINK"
action 5.23 else
action 5.24 regexp "QOS-OUT|QOS_OUT" "$interface_config"
action 5.25 if $_regexp_result eq "1"
action 5.26 set plat2 "UPLINK"
action 6.37 end
action 6.38 end
action 6.40 set idt1 "$plat2"
action 8.0 comment "Check old description if any, and do no change if same idt - dnsname - int"
action 8.2 cli command "do show interface $_nd_local_intf_name | incl Description:"
action 8.21 set olddesc "<none>"
action 8.22 set olddesc_sub1 "<none>"
action 8.23 regexp "Description: (.+)\r" "$_cli_result" olddesc olddesc_sub1
action 8.24 set newdesc "$idt1 - $dnsname - $int"
action 8.25 if $olddesc_sub1 eq "$newdesc"
action 8.26 syslog msg "EEM script did NOT change description on $_nd_local_intf_name, since remote dnsname and interface is unchanged"
action 8.27 exit 10
action 8.28 end
action 8.3 cli command "interface $_nd_local_intf_name"
action 8.4 cli command "description $newdesc"
action 8.6 syslog msg "EEM script updated description on $_nd_local_intf_name from $olddesc to Description: $newdesc"
action 9.10 exit
action 9.9 end
Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: