Post

Cisco CDP configuration with Ansible

Some Cisco IOS configuration settings are half-baked like the CDP settings for interfaces.

If you disable cdp for a interface you specify no cdp enable. This setting will show up in the running config.

To re-enable: cdp enable but this setting will NOT show up in the running config.

If an interface has cdp enabled there won’t be any cdp enable config setting be present - even with show run all.

Here is how I dealt with this situation.

Data

I have following data:

1
2
3
4
5
6
7
8
9
10
11
12
devices:
  workstation:
    linux-1:  { name: 'linux-1', user: 'test1', ip_addr: '10.0.20.3' }
    linux-2:  { name: 'linux-2', user: 'test2', ip_addr: '10.0.20.4' }
  laptop:
    nb-linux-1: { name: 'nb-linux-1', user: 'test1', ip_addr: '10.0.30.10' }
    nb-linux-2: { name: 'nb-linux-2', user: 'test1', ip_addr: '10.0.30.11' }
  access-points:
    wifi-ap-01: { name: 'wifi-ap-01', ip_addr: '10.0.100.10' }
    wifi-ap-02: { name: 'wifi-ap-02', ip_addr: '10.0.100.11' }
  server:
    hv-vm-01: { name: 'hv-vm-01', ipmi: { name: 'hv-vm-01-ipmi', ip_addr: '10.0.100.20' } }

The data for the interface configuration looks like this:

1
2
3
4
5
6
7
8
# host_vars/swi-acs-01.yml
# the numbers are the port numbers - 1 = Gi1/0/1, 2 = Gi1/0/2
switch_interface_hash:
    1: { device: "{{ devices['workstation']['linux-1'] }}" }
    2: { device: "{{ devices['workstation']['linux-2'] }}" }
    3: { device: "{{ devices['access-points']['wifi-ap-01'] }}" }
    4: { switchport_enabled: false }
    5: { device: "{{ devices['server']['hv-vm-01']['ipmi'] }}" }

Enable CDP globally

I will get the running config first ‘cause this will speed up later tasks

1
2
3
4
5
6
7
8
9
10
- name: get running-config
  ios_config:
    backup: true
    defaults: true
  register: running_config_backup_result

- name: enable cdp on switch
  ios_config:
    lines: 'cdp run'
    running_config: "{{ lookup('file', running_config_backup_result['backup_path']) }}"

Get CDP settings

This command shows the CDP state of all interfaces.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
swi-acs-01#show cdp interface
 CDP is not enabled on interface FastEthernet0

GigabitEthernet1/0/1 is up, line protocol is up
  Encapsulation ARPA
  Sending CDP packets every 60 seconds
  Holdtime is 180 seconds
 CDP is not enabled on interface GigabitEthernet1/0/2

GigabitEthernet1/0/3 is up, line protocol is up
  Encapsulation ARPA
  Sending CDP packets every 60 seconds
  Holdtime is 180 seconds
 CDP is not enabled on interface GigabitEthernet1/0/4

 CDP is not enabled on interface GigabitEthernet1/0/5

 CDP is not enabled on interface GigabitEthernet1/0/6

 CDP is not enabled on interface GigabitEthernet1/0/7

 CDP is not enabled on interface GigabitEthernet1/0/8

 CDP is not enabled on interface GigabitEthernet1/0/9

 CDP is not enabled on interface GigabitEthernet1/0/10

I will register this output for later use.

1
2
3
4
5
- name: get cdp interface settings
  ios_command:
    commands: 'show cdp interface'
  register: check_cdp_interface
  changed_when: false

Disable CDP on interface

When the device doesn’t process CDP packets disable it.

Some devices like the Cisco Access-Points or the IPMI/BMC of the Cisco UCS server’s do understand the protocol. For them we need to skip this setting and this is done via the last when statement.

{% raw %}

1
2
3
4
5
6
7
8
9
- name: disable cdp on interface
  ios_config:
    lines: 'no cdp enable'
    parents: "interface GigabitEthernet1/0/{{ item.key }}"
    running_config: "{{ lookup('file', running_config_backup_result['backup_path']) }}"
  loop: "{{ switch_interface_hash | dict2items | default({}) }}"
  when:
    - item.value.switchport_enabled is undefined
    - not item.value.device.name | regex_search('^(wifi-ap-\d+|hv-vm-\d+-ipmi)') # exclude some devices

{% endraw %}

Enable CDP on interface

To ensure that CDP is enabled on the desired interfaces we will use the registered output from before.

{% raw %}

1
2
3
4
5
6
7
8
9
10
- name: enable cdp on interface
  ios_config:
    lines: 'cdp enable'
    parents: "interface GigabitEthernet1/0/{{ item.key }}"
    running_config: "{{ lookup('file', running_config_backup_result['backup_path']) }}"
  loop: "{{ switch_interface_hash | dict2items | default({}) }}"
  when:
    - item.value.switchport_enabled is undefined
    - item.value.device.name | regex_search('^(wifi-ap-\d+|hv-vm-\d+-ipmi)')
    - '"CDP is not enabled on interface GigabitEthernet1/0/" ~ item.key ~ "\n\n" in check_cdp_interface.stdout[0]'

{% endraw %}

It would be also possible and maybe a little bit more cleaner to iterate over all interfaces and execute the command show cdp interface <INTERFACE> and then parse the output but it would be also slower.

This post is licensed under CC BY 4.0 by the author.