Automatically Set Port Descriptions

Document

Wed, 11/23/2016 - 08:29
May 19th, 2012

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
Loading.
candrade Wed, 08/29/2012 - 06:07

A very pretty script!!

Will this script change the port´s description every 180 seconds?

Tommy Vindvik Mon, 01/21/2013 - 06:55

I like it!

Have made an improved version, please comment and/or improve further:

  • Trim domain name
  • Short interface name (Te/Gi/Fa)
  • Write config changes, and post a syslog message

regexp in the event are for the uplink module on 3750-X/3560-X, adapt to your own need.

event manager applet auto-update-port-description authorization bypass
<p>description "Auto-update port-description based on CDP neighbors info"</p><p>action 0.0 comment "Event line regexp: Deside which interface to auto-update description on"</p><p>event neighbor-discovery interface regexp .*GigabitEthernet[1-9]/1/[1-4]$ cdp add</p><p>action 1.0 comment "Trim domain name"</p><p>action 1.1 string trimright "$_nd_cdp_entry_name" ".your.domain.name"</p><p>action 1.2 string trimright "$_string_result" ".another.domain.name"</p><p>action 1.3 set _host "$_string_result"</p><p>action 2.0 comment "Convert long interface name to short"</p><p>action 2.1 string first "Ethernet" "$_nd_port_id"</p><p>action 2.2 if "$_string_result" eq 7</p><p>action 2.21 string replace "$_nd_port_id" 0 14 "Gi"</p><p>action 2.3 elseif "$_string_result" eq 10</p><p>action 2.31 string replace "$_nd_port_id" 0 17 "Te"</p><p>action 2.4 elseif "$_string_result" eq 4</p><p>action 2.41 string replace "$_nd_port_id" 0 11 "Fa"</p><p>action 2.5 end</p><p>action 2.6 set _int "$_string_result"</p><p>action 3.0 comment "Actual config of port description"</p><p>action 3.1 cli command "enable"</p><p>action 3.2 cli command "config t"</p><p>action 3.3 cli command "interface $_nd_local_intf_name"</p><p>action 3.4 cli command "description $_host:$_int"</p><p>action 3.5 cli command "do write"</p><p>action 4.0 syslog msg "EEM script updated description on $_nd_local_intf_name and saved config"</p>

Description would be something like: my-test-sw:Gi1/1/1 instead of my-test-sw.my.domain.name:GigabitEthernet1/1/1

Question: When (and why) are "action exit" required at the end of an applet? Could not find any good information on this.

Regards

Tommy V

Tommy Vindvik Fri, 04/05/2013 - 03:40

Improved even further, please comment and/or improve further:

  • Trim domain name - now with regexp
  • Verifiy switch or router remote end. I don't want this script to update decription on AP's and so on.
  • Do not update description if remote host and interface is unchanged. This will retain additional information in description like circuit id, vendor and so on even after a link failure
  • If description is changed, show old description in syslog message

regexp in the event are for the uplink module on 3750-X/3560-X, adapt to your own need.

event manager applet auto-update-port-description authorization bypass
description "Auto-update port-description based on CDP neighbors info"
action 0.0 comment "Event line regexp: Deside which interface to auto-update description on"<p>event neighbor-discovery interface regexp .*GigabitEthernet[1-9]/1/[1-4]$ cdp add</p><p> action 1.0 comment "Verify CDP neighbor to be Switch or Router"</p><p> action 1.1 regexp "(Switch|Router)" $_nd_cdp_capabilities_string</p><p> action 1.2 if $_regexp_result eq 1</p><p> action 2.0 comment "Trim domain name"</p><p> action 2.1 regexp "^([^\.]+)\." $_nd_cdp_entry_name match host</p><p> action 3.0 comment "Convert long interface name to short"</p><p> action 3.1 string first "Ethernet" "$_nd_port_id"</p><p> action 3.2 if "$_string_result" eq 7</p><p> action 3.21 string replace "$_nd_port_id" 0 14 "Gi"</p><p> action 3.3 elseif "$_string_result" eq 10</p><p> action 3.31 string replace "$_nd_port_id" 0 17 "Te"</p><p> action 3.4 elseif "$_string_result" eq 4</p><p> action 3.41 string replace "$_nd_port_id" 0 11 "Fa"</p><p> action 3.5 end</p><p> action 3.6 set int "$_string_result"</p><p> action 4.0 comment "Check old description if any, and do no change if same host:int"</p><p> action 4.1 cli command "enable"</p><p> action 4.11 cli command "config t"</p><p> action 4.2 cli command "do show interface $_nd_local_intf_name | incl Description:"</p><p> action 4.21 set olddesc "&lt;none&gt;"</p><p> action 4.22 set olddesc_sub1 "&lt;none&gt;"</p><p> action 4.23 regexp "Description: ([a-zA-Z0-9:/\-]*)([a-zA-Z0-9:/\-\ ]*)" "$_cli_result" olddesc olddesc_sub1</p><p> action 4.24 if "$olddesc_sub1" eq "$host:$int"</p><p> action 4.25 syslog msg "EEM script did NOT change desciption on $_nd_local_intf_name, since remote host and interface is unchanged"</p><p> action 4.26 exit 10</p><p> action 4.27 end</p><p> action 4.3 cli command "interface $_nd_local_intf_name"</p><p> action 4.4 cli command "description $host:$int"</p><p> action 4.5 cli command "do write"</p><p> action 4.6 syslog msg "EEM script updated description on $_nd_local_intf_name from $olddesc to Description: $host:$int and saved config"</p><p> action 5.0 end</p> action 6.0 exit 1

Description would be something like: my-test-sw:Gi1/1/1 instead of my-test-sw.my.domain.name:GigabitEthernet1/1/1

Does someone have a better way to shorten interface names?

Regards

Tommy V

Joe Clarke Fri, 04/05/2013 - 17:26

Thanks for the mod!

Why not do something like this to shorten the port names:

action 3.1 string range $_nd_port_id 0 1

action 3.6 set int "$_string_result"

Tommy Vindvik Wed, 04/10/2013 - 23:23

Joseph Clarke wrote:

                       

Thanks for the mod!

Why not do something like this to shorten the port names:

action 3.1 string range $_nd_port_id 0 1

action 3.6 set int "$_string_result"

                   

Hmmmm....well....

That gives "Gi" for "GigabitEthernet", but it also removes the interface number part (1/1/1)......

Regards,

Tommy V

Tommy Vindvik Fri, 04/12/2013 - 04:32

Joseph,

Any inprovements in regexp for applets i EEM v4.0?

Tried using something like:

action 3.1 regexp "(^[a-zA-Z]{2})[a-zA-Z]*([0-9/]*)" "$_nd_port_id" short_int sub1 sub2

to shorten portnames and get the interface number part, but it seems like EEM v3.2 does not support curly bracket quantifiers?

Joe Clarke Fri, 04/12/2013 - 06:38

Unfortunately, no.  CLI-based EEM uses the built-in basic regexp engine, and that is not likely to change.  If you use Tcl, you get full Tcl 8.3.4 regexp support, though.

Joe Clarke Mon, 08/26/2013 - 10:19

This is an EEM applet that's designed to be run directly on an IOS device.  It can be deployed using an external NMS, but execution will happen locally per device.

Collin Clark Tue, 04/09/2013 - 14:43

I'm trying to run this on a stack of 3750-X's running 15.0(2)SE, but I'm getting the following errors-

002407: Apr  9 16:41:33.564 CDT: %HA_EM-3-FMPD_UNKNOWN_ENV: fh_parse_var: could not find environment variable: _nd_cdp_capabilities_string

002408: Apr  9 16:41:33.564 CDT: %HA_EM-3-FMPD_ERROR: Error executing applet auto-update-port-description statement 1.1

Any suggestions on where to start looking?



Joe Clarke Tue, 04/09/2013 - 15:47

In looking at the code, this variable should be set and set even in the case of capabilities being empty.  If you enable "debug event manager detector nei" do you see any messages about capabilities when the event is triggered?

Collin Clark Wed, 04/10/2013 - 07:18

I do-

002611: Apr 10 09:05:41.302 CDT: ND Update CDP Notification Event for STACK.corp.com on Gi1/0/17

002612: Apr 10 09:05:41.302 CDT: ND Update CDP Notification Event for STACK.corp.com on Gi2/0/17

002613: Apr 10 09:05:41.302 CDT: ND Update CDP Notification Event for STACK.corp.com on Gi1/0/16

002614: Apr 10 09:05:41.302 CDT: ND Update CDP Notification Event for STACK.corp.com on Gi2/0/16

002615: Apr 10 09:05:41.310 CDT: fh_fd_nd_event_match: num_matches = 0

002616: Apr 10 09:05:41.310 CDT: fh_fd_nd_event_match: num_matches = 0

002617: Apr 10 09:05:41.310 CDT: fh_fd_nd_event_match: num_matches = 0

002618: Apr 10 09:05:41.310 CDT: fh_fd_nd_event_match: num_matches = 0

Please let me preface with something that could be causing the problem. I copied the script and then added 'event none'. Is that the correct procedure?

mtimm Wed, 04/10/2013 - 07:19

Hi Collin,

No, this variable will not be set for the none event detector.  It will only be set for the neighbor discovery event detector.

Mike

Collin Clark Wed, 04/10/2013 - 09:23

If I remove the event none and run it (event manager run [applet name]) I get this

EEM policy update-port-description not registered with event none Event Detector

Joe Clarke Wed, 04/10/2013 - 09:31

The policy in the comments as well as the policy in this doc are designed to only be run on the reception of a new CDP neighbor event.  They cannot be run manually as they are designed.

Collin Clark Wed, 04/10/2013 - 10:23

OK. Stupid question then Joe :-) How do I register it so a new CDP neighbor event changes the description?

Joe Clarke Wed, 04/10/2013 - 10:28

If you take either of these examples and simply configure them on your device as-is, then they will be listening for CDP events.  You can test by clearing your CDP neighbor table.

Collin Clark Wed, 04/10/2013 - 11:41

Thanks Joe...it's slowly starting to sink in. I cleaned up the mess I was making. I cleared the cdp table. I see in the log that it sees a new event but it still does not name the port.

015051: Apr 10 13:38:19.867 CDT: ND Add CDP Notification Event for STACK.corp.com on Gi2/0/16

015052: Apr 10 13:38:19.867 CDT: Event type = CDP ADD

015053: Apr 10 13:38:19.867 CDT: Interface spec is a regexp

015054: Apr 10 13:38:19.867 CDT: Interface did not Match regexp

015055: Apr 10 13:38:19.867 CDT: nd_match_one_event: ret=FALSE

015056: Apr 10 13:38:19.867 CDT: fh_fd_nd_event_match: num_matches = 0

Joe Clarke Wed, 04/10/2013 - 11:49

The regexp in the comment would not have matched.  You want something like:

event neighbor-discovery interface regexp .*GigabitEthernet[1-9]/[0-9]/[0-9]+$ cdp add

Collin Clark Wed, 04/10/2013 - 12:40

It works for routers (ASR1001) but fails on switches (remote 3750-X stack to be specific).

If you see something obvious can you give me a hint (ie what line to look at)?

Collin Clark Wed, 04/10/2013 - 13:45

Sorry for the last post Joe, your regex above got the switches working. I greatly appreciate your help (as always).

Tommy Vindvik Wed, 04/10/2013 - 23:38

Collin:

The event "event neighbor-discovery interface regexp .*GigabitEthernet[1-9]/1/[1-4]$ cdp add" controls what the script should act on. In this case cdp add events from the interfaces specified in the regexp. Regexp in my examples are adapted to only include the uplink/network modules on a 3750-X or a stack of 3750-X.

.*GigabitEthernet allows for interfaces GigabitEthernet with zero or more characters in front. Thus also including TenGigabitEthernet. Remembering the port numbering in a 3750 stack, the [1-9]/1/[1-4]$ part of the regexp says "switch 1-9, module 1, port 1-4". This matches the network/uplink module.

To match "any" Gigabit ports, you could use the regexp from Joseph: .*GigabitEthernet[1-9]/[0-9]/[0-9]+$

This "reads": Any interface with zero or more characters in front of GigabitEthernet, switch 1-9, modules 0-9, port 0-9999999 (the + sign equals that the digits in the square brackets in front could be repeated zero or more times).

Or you could use the regexp from the first post: GigabitEthernet.*

This reads:  Any GigabitEthernet interface with zero or more characters following.

Understanding the power of regexp could be a bit challenging, but the it's worth it

(somewhat of a regexp newbie my self )

Regards,

Tommy V

Collin Clark Fri, 04/12/2013 - 06:33

I was a little confused on how it grabbed the info but I think I understand it now. Regex is one of things (for me) where I learn it, then forget it. I don't use it enough for it to stick   I have a question for you. I'm trying to AP's as well. I added

action 1.1 regexp "(Switch|Router|Trans-Bridge)" $_nd_cdp_capabilities_string

but it doesn't see the AP's. Is there another place I should be looking?

Joe Clarke Fri, 04/12/2013 - 06:40

You may want to print the capabilities string just to make sure EEM is capturing the whole thing.  You could also try matching on "AIR" in the $_nd_cdp_platform.

mtimm Fri, 04/12/2013 - 06:53

Debugs can be enabled which will display the environmental variables that are published and what values those variables are set to. 

debug event manager policydir       

That may be helpful in determining what the capabilities string is set to for an AP.

Mike

Tommy Vindvik Fri, 04/12/2013 - 06:45

....or you could remove the following lines to allow the script to run on any CDP speaking neighbor:

action 1.1 regexp "(Switch|Router)" $_nd_cdp_capabilities_string

action 1.2 if $_regexp_result eq 1

action 5.0 end

Collin Clark Fri, 04/12/2013 - 09:58

Very helpful. I'll probably use that except on access layer switches (dang IP Phones).

Zeek Ferraros Wed, 06/26/2013 - 07:28

Hi,

I've tried the short script on post 1 on my C3560 switches. At first the script didn't work until I realized I had to change GigabitEthernet to FastEthernet since I have no gig ports on my 3560s.

The script now works but I am only getting the MAC of the IP Phones connected to the switchports and hostname of router connected to the switch. For some reason I don't get the mac of windows servers connected to the switch or Wireless access Points.

I've also tried the other two extended scripts from this thread without modification (only GigabitEthernet to FastEthernet) and didn't get any resutls.

Does anyone have a a working script for C3560-48 or C3560-24 switches?

I am running IOS c3560-ipservicesk9-mz.122-55.SE6.bin on all my switches.

Thanks in advance.

Zeek

Collin Clark Wed, 06/26/2013 - 09:36

Zeek-

This script does not pull the MAC address of non-Cisco devices and update the description. You could try and install the CDP client on the server. I'm not sure how that would look in CDP (a good thing to lab when I get some time).

http://www.tallsoft.com/cdpmonitor.htm

The extended scripts won't work with the 3560 because of the interface numbering scheme. Use the OP script.

Joe Clarke Wed, 06/26/2013 - 21:54

Collin is right, but you could use the MAC Address event detector as well to create an applet that matches on learning a MAC address on a port.  Use this to set the initial description, then if CDP overwrites it you have more details.  You ED line would be something like:

event mat interface regexp ".*Ethernet.*" type add

Then you can use $_mat_intf_name to get the interface on which the event occurred and $_mat_mac_address to get the learned MAC address.

Collin Clark Tue, 08/06/2013 - 18:02

Here you go-

event manager applet auto-update-port-description authorization bypass

description "Auto-update port-description based on CDP neighbor info"

event neighbor-discovery interface regexp .*GigabitEthernet[1-9]/[0-9]/[0-9]+$ cdp add

action 0.0  comment "Event line regexp: Deside which interface to auto-update description on"

action 1.0  comment "Verify CDP neighbor to be Switch or Router"

action 1.1  regexp "(Switch|Router|AIR)" "$_nd_cdp_capabilities_string"

action 1.2  if $_regexp_result eq "1"

action 2.0  comment "Trim domain name"

action 2.1  regexp "^([^\.]+)\." "$_nd_cdp_entry_name" match host

action 3.0  comment "Convert long interface name to short"

action 3.1  string first "Ethernet" "$_nd_port_id"

action 3.2  if $_string_result eq "7"

action 3.21 string replace "$_nd_port_id" 0 14 "Gi"

action 3.3  elseif $_string_result eq 10

action 3.31 string replace "$_nd_port_id" 0 17 "Te"

action 3.4  elseif $_string_result eq 4

action 3.41 string replace "$_nd_port_id" 0 11 "Fa"

action 3.5  end

action 3.6  set int "$_string_result"

action 4.0  comment "Check old description if any, and do no change if same host:int"

action 4.1  cli command "enable"

action 4.11 cli command "config t"

action 4.2  cli command "do show interface $_nd_local_intf_name | incl Description:"

action 4.21 set olddesc "<none>"

action 4.22 set olddesc_sub1 "<none>"

action 4.23 regexp "Description: ([a-zA-Z0-9:/\-]*)([a-zA-Z0-9:/\-\ ]*)" "$_cli_result" olddesc olddesc_sub1

action 4.24 if $olddesc_sub1 eq "$host:$int"

action 4.25 syslog msg "EEM script did NOT change desciption on $_nd_local_intf_name, since remote host and interface is unchanged"

action 4.26 exit 10

action 4.27 end

action 4.3  cli command "interface $_nd_local_intf_name"

action 4.4  cli command "description $host:$int"

action 4.5  cli command "do write"

action 4.6  syslog msg "EEM script updated description on $_nd_local_intf_name from $olddesc to Description: $host:$int and saved config"

action 5.0  end

action 6.0  exit 1

!

c.baugh Wed, 08/05/2015 - 13:59

Hello.  I have a question.

I configured my switch with the actions listed above. I plugged in an access point and the port description was populated as expected.  I then moved the access point to another port and it worked again.

 

However, now I have two ports with the same description, but the WAP is not plugged into one of the ports.  How would I get the port to reset or clear the description if the port is down/down, or populate the description with the mac address of the currently connected device (if it does not do CDP) ???  Just clearing the CDP table does not help. 

Your help is greatly appreciated. //Craig

Joe Clarke Wed, 08/05/2015 - 16:03

At CiscoLive, I use a complimentary applet to default the port.  However, the initial idea of this was to be able to find missing APs.  If the port was up, then the description was valid.  If down, that was the previous spot of the AP.  If you want to add the compliment, have a look at:

 

event manager applet reset-port authorization bypass
 event syslog pattern "LINK-3-UPDOWN.*Interface GigabitEthernet.*changed state to down"
 action 001  regexp "Interface ([^,]+)" $_syslog_msg match intf
 action 002  cli command "enable"
 action 003  cli command "show int $intf | inc Description:"
 action 004  regexp "STATIC:" $_cli_result
 action 005  if $_regexp_result eq 1
 action 006   exit 0
 action 007  end
 action 008  cli command "config t"
 action 009  cli command "default interface $intf"
 action 010  cli command "interface $intf"
 action 011  cli command "switchport trunk encapsulation dot1q"
 action 012  cli command "switchport access vlan 2000"
 action 013  cli command "load-interval 30"
 action 014  cli command "srr-queue bandwidth share 1 30 35 5"
 action 015  cli command "priority-queue out"
 action 016  cli command "udld port aggressive"
 action 017  cli command "mls qos trust dscp"
 action 020  cli command "spanning-tree link-type point-to-point"
 action 021  cli command "end"

 

Hi

the EEM script works very well, but Wireless Access Points (1252) are not discovered correctly. It seems to me that they propagate their capability as "Trans-Bridge" instead of "AIR". So I changed "Switch|Router|AIR" in action 1.1 to "Switch|Router|Trans-Bridge" but it was not working. I got an error message referring to action 4.4 related to pasing the hostname. Any hint would be appreciated. Thanks! Knut

Ramz PV Tue, 11/05/2013 - 03:31

Hi,

       script is working well for the newly connected device. I want to use the script for giving Interface description for the existing setup. please help.

Tommy Vindvik Tue, 11/05/2013 - 03:38

Hi Ramz,

You have to trigger a CDP event for the script to run. The easiest way to do this, is to shut/no shut the ports.

Or you could maybe do a "no cdp enable"/"cdp enable" if you don't want to affect traffic. I have not tested this.

Regards

Tommy V

Ramz PV Tue, 11/05/2013 - 05:22

Hi Tommy,

            I think we can go ahead with the second option "no cdp enable"/"cdp enable". but the command should run only on the interfaces where the cisco devices are connected. can we incorporate the same in the same EEM script with a delay of 180+ seonds between the commands("no cdp enable"/"cdp enable").

event manager applet update-port-description<br/>event neighbor-discovery interface regexp GigabitEthernet.* cdp add <br/>action 1.0 cli command "enable"<br/>action 2.0 cli command "config t"<br/>action 3.0 cli command "interface $_nd_local_intf_name"<br/>action 4.0 cli command "description $_nd_cdp_entry_name:$_nd_port_id"<br/>
Tommy Vindvik Tue, 11/05/2013 - 05:40

Ramz,

Since the script triggers every time CDP info is added (as in changed or just connected), disabling CDP on a port and enabling it again will trigger the same CDP info. The script would then change the description. It should anyhow be pretty safe to test.

I short: Yes

Regards

Tommy V

Joe Clarke Tue, 11/05/2013 - 12:22

You can use the CDP update events by changing the type to "all".  CDP messages are sent periodically, so that should trigger.  IT will, though, trigger multiple configuration changes.

Ramz PV Tue, 11/05/2013 - 21:26

Hi,

          cdp "all" & "update" are making multiple configuration changes and it is populating in my logging. Is it possible to add an event only once for clearing cdp table as soon as add the EEM script. Rest of the time it should check for CDP "add" event only.

Tommy Vindvik Tue, 11/05/2013 - 23:14

Rantz,

Several possible way to do this.

While the applet is "installed" and using the "cdp add" event do one of the following to add any neighbors:

1) shut/no shut pr interface

2) Change the hostname of remote switch/router

3) "no cdp enable"/"cdp enable" pr interface

4) In enable mode, do a "clear cdp table"

All of these will create a "cdp add" event, and thus trigger the script to run.

Regards

Tommy V

Joe Clarke Wed, 11/06/2013 - 11:58

It sounds like what would be easiest for you is to configure the applet with an "add" event, then just do a clear on the CDP table.  You'd only need to do that once.  After that, the applet will notice all new neighbors.

Ramz PV Sun, 11/10/2013 - 23:47

Thanks all for your support and suggestions.... it worked by clearing the CDP table...

Actions

This Document

Related Content