Source code

I wanted to give myself a refresher on VXLAN. I have worked with a bit on and off, however, most of my day to day is usually enterprise networking outside of the data center. I was going to just stand up a lab and mess around, but I figured why not create the lab with Ansible so I can spin it up again at anytime.

It is going to be a standard flood and learn design. The topology consists of a layer 3 leaf spine with 2 spines and 4 leafs. Leaf04 is going to eventually become the edge leaf.

Underlay Topology

VXLAN

Underlay Addressing

Device Interface IP <> Device Interface IP
spine01 eth1 172.16.0.1/30 <> leaf01 eth1 172.16.0.2/30
spine01 eth2 172.16.0.5/30 <> leaf02 eth1 172.16.0.6/30
spine01 eth3 172.16.0.9/30 <> leaf03 eth1 172.16.0.10/30
spine01 eth4 172.16.0.13/30 <> leaf04 eth1 172.16.0.14/30
spine01 lo0 192.168.0.1/32
spine02 eth1 172.17.0.1/30 <> leaf01 eth2 172.17.0.2/30
spine02 eth2 172.17.0.5/30 <> leaf02 eth2 172.17.0.6/30
spine02 eth3 172.17.0.9/30 <> leaf03 eth2 172.17.0.10/30
spine02 eth4 172.17.0.13/30 <> leaf04 eth2 172.17.0.14/30
spine02 lo0 192.168.0.2/32
leaf01 po12 10.12.12.1/30 <> leaf02 po12 10.12.12.2/30
leaf01 lo0 192.168.1.1/32
leaf02 lo0 192.168.1.2/32
leaf03 lo0 192.168.1.3/32
leaf04 lo0 192.168.1.4/32

Inventory files

The current file structure looks like this.

.
├── ansible.cfg
├── backup
├── configs
├── group_vars
│   └── eos_leafs.yml
├── host_vars
│   ├── leaf01.yml
│   ├── leaf02.yml
│   ├── leaf03.yml
│   ├── leaf04.yml
│   ├── spine01.yml
│   └── spine02.yml
├── hosts.yml
├── templates
│   └── vxlan.j2
└── vxlan-playbook.yml

ansible.cfg

[defaults]
host_key_checking = False
retry_files_enabled = False
inventory = hosts.yml

Pretty standard setup here. Now for the inventory file.

hosts.yml

---

all:
  vars:
    mgmtgw: 192.168.128.1
    timezone: America/New_York
    domain: billgrant.io
    ntpserver1: 0.pool.ntp.org
    ntpserver2: 1.pool.ntp.org
    nameserver1: 8.8.8.8
    nameserver2: 8.8.4.4
    ansible_python_interpreter: /usr/bin/env python3 
  
  children:

    eos_spines:
      hosts:
        spine01:
          ansible_host: 192.168.128.201
          mgmtip: 192.168.128.201/24
        spine02:
          ansible_host: 192.168.128.202
          mgmtip: 192.168.128.202/24

    eos_leafs:
      hosts:
        leaf01: 
          ansible_host: 192.168.128.203
          mgmtip: 192.168.128.203/24
        leaf02:
          ansible_host: 192.168.128.204
          mgmtip: 192.168.128.204/24
        leaf03:
          ansible_host: 192.168.128.205
          mgmtip: 192.168.128.205/24
        leaf04:
          ansible_host: 192.168.128.206
          mgmtip: 192.168.128.206/24

    eos:
      vars:
        ansible_connection: httpapi
        ansible_network_os: eos
        ansible_user: admin
        ansible_ssh_pass: admin
        ansible_become: yes
        ansible_become_method: enable
      children:
        eos_spines:
        eos_leafs:

For each device we have a host_vars file.

spine01.yml

---

interfaces:
  - name: Loopback0
    description: router-id
    ipv4: 192.168.0.1/32
    shutdown: False
  - name: Ethernet1
    description: P2P Link to Leaf-1
    ipv4: 172.16.0.1/30
    shutdown: False
    switchport: False
  - name: Ethernet2
    description: P2P Link to Leaf-2
    ipv4: 172.16.0.5/30
    shutdown: False
    switchport: False
  - name: Ethernet3
    description: P2P Link to Leaf-3
    ipv4: 172.16.0.9/30
    shutdown: False
    switchport: False
  - name: Ethernet4
    description: P2P Link to Leaf-3
    ipv4: 172.16.0.13/30
    shutdown: False
    switchport: False

bgp:
  asn: 65000
  routerid: 192.168.0.1
  distance: 20 200 200
  maxpaths: 2 ecmp 64
  networks: 
    - 192.168.0.1/32
  neighbors:
    - ipv4: 172.16.0.2
      remoteas: 65001
      maxroutes: 12000
    - ipv4: 172.16.0.6
      remoteas: 65001
    - ipv4: 172.16.0.10
      remoteas: 65002
      maxroutes: 12000
    - ipv4: 172.16.0.14
      remoteas: 65003
      maxroutes: 12000

spine02.yml

---

interfaces:
  - name: Loopback0
    description: router-id
    ipv4: 192.168.0.2/32
    shutdown: False
  - name: Ethernet1
    description: P2P Link to Leaf-1
    ipv4: 172.17.0.1/30
    shutdown: False
    switchport: False
  - name: Ethernet2
    description: P2P Link to Leaf-2
    ipv4: 172.17.0.5/30
    shutdown: False
    switchport: False
  - name: Ethernet3
    description: P2P Link to Leaf-3
    ipv4: 172.17.0.9/30
    shutdown: False
    switchport: False
  - name: Ethernet4
    description: P2P Link to Leaf-4
    ipv4: 172.17.0.13/30
    shutdown: False
    switchport: False

bgp:
  asn: 65000
  routerid: 192.168.0.2
  distance: 20 200 200
  maxpaths: 2 ecmp 64
  networks: 
    - 192.168.0.2/32
  neighbors:
    - ipv4: 172.17.0.2
      remoteas: 65001
      maxroutes: 12000
    - ipv4: 172.17.0.6
      remoteas: 65001
      maxroutes: 12000
    - ipv4: 172.17.0.10
      remoteas: 65002
      maxroutes: 12000
    - ipv4: 172.17.0.14
      remoteas: 65003
      maxroutes: 12000

leaf01.yml

---

interfaces:
  - name: Loopback0
    description: router-id
    ipv4: 192.168.1.1/32
    shutdown: False
  - name: Ethernet1
    description: P2P Link to Spine01
    ipv4: 172.16.0.2/30
    shutdown: False
    switchport: False
  - name: Ethernet2
    description: P2P Link to Spine02
    ipv4: 172.17.0.2/30
    shutdown: False
    switchport: False
  - name: Ethernet10
    description: mlag Link to Leaf02
    channelgroup: 12 mode active
    shutdown: False
  - name: Ethernet11
    description: mlag Link to Leaf02
    channelgroup: 12 mode active
    shutdown: False
  - name: Port-Channel12
    description: mlag to peer Leaf02
    shutdown: False
    switchport: trunk
    trunkoptions:
      - group mlagpeer
  - name: Vlan4094
    description: mlag
    ipv4: 10.12.12.1/30
    shutdown: False
  - name: Vlan100
    description: operations
    ipv4: 10.100.100.1/24
    shutdown: False
    varpaddr:  10.100.100.254
  - name: Vlan200
    description: staff
    ipv4: 10.200.200.1/24
    shutdown: False
    varpaddr:  10.200.200.254

varpmac: aa:00:bb:11:cc:22

vlans:
  - name: mlag
    number: 4094
    options:
      - trunk group mlagpeer
  - name: operations
    number: 100
  - name: staff
    number: 200

mlag:
  domainid: leaf12
  localinterface: Vlan4094
  peeraddress: 10.12.12.2
  peerlink: Port-Channel12
  reloaddelay: 500

bgp:
  asn: 65001
  routerid: 192.168.1.1
  distance: 20 200 200
  maxpaths: 2 ecmp 2
  networks: 
    - 192.168.1.1/32
  redistribute: connected
  neighbors:
    - ipv4: 172.16.0.1
      remoteas: 65000
      maxroutes: 12000
      prefixlist:
        - name: to-spines
          type: prefixlist
          direction: out
    - ipv4: 172.17.0.1
      remoteas: 65000
      maxroutes: 12000
      prefixlist:
        - name: to-spines
          type: prefixlist
          direction: out
    - ipv4: 10.12.12.2
      remoteas: 65001
      nexthop: self
      maxroutes: 12000

leaf02.yml

---

interfaces:
  - name: Loopback0
    description: router-id
    ipv4: 192.168.1.2/32
    shutdown: False
  - name: Ethernet1
    description: P2P Link to Spine01
    ipv4: 172.16.0.6/30
    shutdown: False
    switchport: False
  - name: Ethernet2
    description: P2P Link to Spine02
    ipv4: 172.17.0.6/30
    shutdown: False
    switchport: False
  - name: Ethernet10
    description: mlag Link to Leaf01
    channelgroup: 12 mode active
    shutdown: False
  - name: Ethernet11
    description: mlag Link to Leaf01
    channelgroup: 12 mode active
    shutdown: False
  - name: Port-Channel12
    description: mlag to peer Leaf01
    shutdown: False
    switchport: trunk
    trunkoptions:
      - group mlagpeer
  - name: Vlan4094
    description: mlag
    ipv4: 10.12.12.2/30
    shutdown: False
  - name: Vlan100
    description: operations
    ipv4: 10.100.100.2/24
    shutdown: False
    varpaddr:  10.100.100.254
  - name: Vlan200
    description: staff
    ipv4: 10.200.200.2/24
    shutdown: False
    varpaddr:  10.200.200.254

varpmac: aa:00:bb:11:cc:22

vlans:
  - name: mlag
    number: 4094
    options:
      - trunk group mlagpeer
  - name: operations
    number: 100
  - name: staff
    number: 200

mlag:
  domainid: leaf12
  localinterface: Vlan4094
  peeraddress: 10.12.12.1
  peerlink: Port-Channel12
  reloaddelay: 500

bgp:
  asn: 65001
  routerid: 192.168.1.2
  distance: 20 200 200
  maxpaths: 2 ecmp 2
  networks: 
    - 192.168.1.2/32
  redistribute: connected
  neighbors:
    - ipv4: 172.16.0.5
      remoteas: 65000
      maxroutes: 12000
      prefixlist:
        - name: to-spines
          type: prefixlist
          direction: out
    - ipv4: 172.17.0.5
      remoteas: 65000
      maxroutes: 12000
      prefixlist:
        - name: to-spines
          type: prefixlist
          direction: out
    - ipv4: 10.12.12.1
      remoteas: 65001
      nexthop: self
      maxroutes: 12000

leaf03.yml

---

interfaces:
  - name: Loopback0
    description: router-id
    ipv4: 192.168.1.3/32
    shutdown: False
  - name: Ethernet1
    description: P2P Link to Spine-1
    ipv4: 172.16.0.10/30
    shutdown: False
    switchport: False
  - name: Ethernet2
    description: P2P Link to Spine-2
    ipv4: 172.17.0.10/30
    shutdown: False
    switchport: False
  - name: Vlan100
    description: operations
    ipv4: 10.100.100.3/24
    shutdown: False
    varp-addr:  10.100.100.254
  - name: Vlan200
    description: staff
    ipv4: 10.200.200.3/24
    shutdown: False
    varp-addr:  10.200.200.254

varpmac: aa:00:bb:11:cc:22

vlans:
  - name: operations
    number: 100
  - name: staff
    number: 200

bgp:
  asn: 65002
  routerid: 192.168.1.3
  distance: 20 200 200
  maxpaths: 2 ecmp 2
  networks:
    - 192.168.1.3/32
  redistribute: connected
  neighbors:
    - ipv4: 172.16.0.9
      remoteas: 65000
      maxroutes: 12000
      prefixlist:
        - name: to-spines
          type: prefixlist
          direction: out
    - ipv4: 172.17.0.9
      remoteas: 65000
      maxroutes: 12000
      prefixlist:
        - name: to-spines
          type: prefixlist
          direction: out

leaf04.yml

---

interfaces:
  - name: Loopback0
    description: router-id
    ipv4: 192.168.1.4/32
    shutdown: False
  - name: Ethernet1
    description: P2P Link to Spine-1
    ipv4: 172.16.0.14/30
    shutdown: False
    switchport: False
  - name: Ethernet2
    description: P2P Link to Spine-2
    ipv4: 172.17.0.14/30
    shutdown: False
    switchport: False
  - name: Vlan100
    description: operations
    ipv4: 10.100.100.4/24
    shutdown: False
    varp-addr:  10.100.100.254
  - name: Vlan200
    description: staff
    ipv4: 10.200.200.4/24
    shutdown: False
    varp-addr:  10.200.200.254

varpmac: aa:00:bb:11:cc:22

vlans:
  - name: operations
    number: 100
  - name: staff
    number: 200

bgp:
  asn: 65003
  routerid: 192.168.1.4
  distance: 20 200 200
  maxpaths: 2 ecmp 2
  networks: 
    - 192.168.1.4/32
  redistribute: connected
  neighbors:
    - ipv4: 172.16.0.13
      remoteas: 65000
      maxroutes: 12000
      prefixlist:
        - name: to-spines
          direction: out
    - ipv4: 172.17.0.13
      remoteas: 65000
      maxroutes: 12000
      prefixlist:
        - name: to-spines
          direction: out

Since we have a prefix list that is identical on all 4 leafs a groups_vars file for the leafs is setup as follows.

eos_leafs.yml

---

prefixlists:
  - name: to-spines
    seq: 10
    action: permit
    ipv4: 192.168.0.0/23
    eq: 32
  - name: to-spines
    seq: 20
    action: permit
    ipv4: 172.16.0.0/23
    eq: 30
  - name: to-spines
    seq: 30
    action: permit
    ipv4: 10.12.12.0/30
    eq: 30

Next up is the configuration template.

eos-vxlan.j2

ip routing
!
lldp run
!
{% if vlans is defined -%}
{% for vlan in vlans -%}
vlan {{ vlan.number }}
   name {{ vlan.name }}
{% if vlan.options is defined %}
{% for option in vlan.options %}
   {{ option }}
{% endfor -%}
{% endif -%}
!
{% endfor -%}
{% endif -%}
{% for interface in interfaces -%}
interface {{ interface.name }}
   description {{ interface.description }}
{% if interface.switchport is defined and interface.switchport == false %}
   no switchport
{% elif interface.switchport is defined and interface.switchport == 'trunk' %}
   switchport mode trunk
{% if interface.trunkoptions is defined %}
{% for option in interface.trunkoptions  %}
   switchport trunk {{ option }}
{% endfor -%}
{% endif -%}
{% endif -%}
{% if interface.ipv4 is defined %}
   ip address {{ interface.ipv4 }}
{% else %}
   no ip address
{% endif -%}
{% if interface.shutdown == false %}
   no shutdown
{% elif interface.shutdown == true %}
   shutdown
{% endif -%}
{% if interface.channelgroup is defined %}
   channel-group {{ interface.channelgroup }}
{% endif -%}
{% if interface.varpaddr is defined %}
   ip virtual-router address {{ interface.varpaddr }}
{% endif -%}
!
{% endfor -%}
{% if varpmac is defined %}
ip virtual-router mac-address {{ varpmac }}
!
{% endif -%}
{% if mlag is defined %}
mlag configuration
   domain-id {{ mlag.domainid }}
   local-interface {{ mlag.localinterface }}
   peer-address {{ mlag.peeraddress }}
   peer-link {{ mlag.peerlink }}
   reload-delay {{ mlag.reloaddelay }}
!
{% endif -%}
{% if prefixlists is defined %}
{% for pl in prefixlists %}
ip prefix-list {{ pl.name }} seq {{ pl.seq }} {{ pl.action }} {{ pl.ipv4 }} eq {{ pl.eq }}
{% endfor -%}
!
{% endif -%}
router bgp {{ bgp.asn }}
   router-id {{ bgp.routerid }}
   maximum-paths {{ bgp.maxpaths }}
   distance bgp {{ bgp.distance }}
{% if bgp.redistribute is defined %}
   redistribute {{ bgp.redistribute }}
{% endif -%}
{% for neighbor in bgp.neighbors %}
   neighbor {{ neighbor.ipv4 }} remote-as {{ neighbor.remoteas }}
{% if neighbor.maxroutes is defined %}
   neighbor {{ neighbor.ipv4 }} maximum-routes {{ neighbor.maxroutes }}
{% endif -%}
{% if neighbor.prefixlist is defined %}
{% for list in neighbor.prefixlist %}
   address-family ipv4
      neighbor {{ neighbor.ipv4 }} prefix-list {{ list.name }} {{ list.direction }}
{% endfor -%}
{% endif -%}
{% if neighbor.nexthop is defined %}
   neighbor {{ neighbor.ipv4 }} next-hop-{{ neighbor.nexthop }}
{% endif -%}
{% endfor -%}
{% for network in bgp.networks %}
   network {{ network }}
{% endfor -%}
!
end

The only thing left is the playbook itself.

vxlan-playbook.yml

---

  - hosts: eos
    gather_facts: no

    tasks:

    - name: Create configuration files
      template:
        src: "templates/{{ ansible_network_os }}-vxlan.j2"
        dest: "configs/{{ inventory_hostname }}-vxlan.config"
      tags:
        - template

    - name: Load configuration file
      eos_config:
        backup: yes
        src: "configs/{{ inventory_hostname }}-vxlan.config"
        defaults: true
        save_when: modified
      register: "{{ inventory_hostname }}"
      tags:
        - configpush

We select only the eos hosts. Then we build the config based off the inventory and variable files. Next we backup the current config, load the new config, and finally write the configuration if changes are present.

Running the playbook.

netops@netserver:~/git/vxlanansible/ansible$ ansible-playbook vxlan-playbook.yml

PLAY [eos] *****************************************************************************************************

TASK [Create configuration files] ******************************************************************************
changed: [spine02]
changed: [spine01]
changed: [leaf03]
changed: [leaf02]
changed: [leaf01]
changed: [leaf04]

TASK [Load configuration file] *********************************************************************************
changed: [leaf03]
changed: [spine01]
changed: [spine02]
changed: [leaf02]
changed: [leaf01]
changed: [leaf04]

PLAY RECAP *****************************************************************************************************
leaf01                     : ok=2    changed=2    unreachable=0    failed=0   
leaf02                     : ok=2    changed=2    unreachable=0    failed=0   
leaf03                     : ok=2    changed=2    unreachable=0    failed=0   
leaf04                     : ok=2    changed=2    unreachable=0    failed=0   
spine01                    : ok=2    changed=2    unreachable=0    failed=0   
spine02                    : ok=2    changed=2    unreachable=0    failed=0

Looks like everything worked. Here are the config files that were created and pushed to the switches.

spine01-vxlan.config

ip routing
!
lldp run
!
interface Loopback0
   description router-id
   ip address 192.168.0.1/32
   no shutdown
!
interface Ethernet1
   description P2P Link to Leaf-1
   no switchport
   ip address 172.16.0.1/30
   no shutdown
!
interface Ethernet2
   description P2P Link to Leaf-2
   no switchport
   ip address 172.16.0.5/30
   no shutdown
!
interface Ethernet3
   description P2P Link to Leaf-3
   no switchport
   ip address 172.16.0.9/30
   no shutdown
!
interface Ethernet4
   description P2P Link to Leaf-3
   no switchport
   ip address 172.16.0.13/30
   no shutdown
!
router bgp 65000
   router-id 192.168.0.1
   maximum-paths 2 ecmp 64
   distance bgp 20 200 200
   neighbor 172.16.0.2 remote-as 65001
   neighbor 172.16.0.2 maximum-routes 12000
   neighbor 172.16.0.6 remote-as 65001
   neighbor 172.16.0.10 remote-as 65002
   neighbor 172.16.0.10 maximum-routes 12000
   neighbor 172.16.0.14 remote-as 65003
   neighbor 172.16.0.14 maximum-routes 12000
   network 192.168.0.1/32
!
end

spine02-vxlan.config

ip routing
!
lldp run
!
interface Loopback0
   description router-id
   ip address 192.168.0.2/32
   no shutdown
!
interface Ethernet1
   description P2P Link to Leaf-1
   no switchport
   ip address 172.17.0.1/30
   no shutdown
!
interface Ethernet2
   description P2P Link to Leaf-2
   no switchport
   ip address 172.17.0.5/30
   no shutdown
!
interface Ethernet3
   description P2P Link to Leaf-3
   no switchport
   ip address 172.17.0.9/30
   no shutdown
!
interface Ethernet4
   description P2P Link to Leaf-4
   no switchport
   ip address 172.17.0.13/30
   no shutdown
!
router bgp 65000
   router-id 192.168.0.2
   maximum-paths 2 ecmp 64
   distance bgp 20 200 200
   neighbor 172.17.0.2 remote-as 65001
   neighbor 172.17.0.2 maximum-routes 12000
   neighbor 172.17.0.6 remote-as 65001
   neighbor 172.17.0.6 maximum-routes 12000
   neighbor 172.17.0.10 remote-as 65002
   neighbor 172.17.0.10 maximum-routes 12000
   neighbor 172.17.0.14 remote-as 65003
   neighbor 172.17.0.14 maximum-routes 12000
   network 192.168.0.2/32
!
end

leaf01-vxlan.config

ip routing
!
lldp run
!
vlan 4094
   name mlag
   trunk group mlagpeer
!
vlan 100
   name operations
!
vlan 200
   name staff
!
interface Loopback0
   description router-id
   ip address 192.168.1.1/32
   no shutdown
!
interface Ethernet1
   description P2P Link to Spine01
   no switchport
   ip address 172.16.0.2/30
   no shutdown
!
interface Ethernet2
   description P2P Link to Spine02
   no switchport
   ip address 172.17.0.2/30
   no shutdown
!
interface Ethernet10
   description mlag Link to Leaf02
   no ip address
   no shutdown
   channel-group 12 mode active
!
interface Ethernet11
   description mlag Link to Leaf02
   no ip address
   no shutdown
   channel-group 12 mode active
!
interface Port-Channel12
   description mlag to peer Leaf02
   switchport mode trunk
   switchport trunk group mlagpeer
   no ip address
   no shutdown
!
interface Vlan4094
   description mlag
   ip address 10.12.12.1/30
   no shutdown
!
interface Vlan100
   description operations
   ip address 10.100.100.1/24
   no shutdown
   ip virtual-router address 10.100.100.254
!
interface Vlan200
   description staff
   ip address 10.200.200.1/24
   no shutdown
   ip virtual-router address 10.200.200.254
!
ip virtual-router mac-address aa:00:bb:11:cc:22
!
mlag configuration
   domain-id leaf12
   local-interface Vlan4094
   peer-address 10.12.12.2
   peer-link Port-Channel12
   reload-delay 500
!
ip prefix-list to-spines seq 10 permit 192.168.0.0/23 eq 32
ip prefix-list to-spines seq 20 permit 172.16.0.0/23 eq 30
ip prefix-list to-spines seq 30 permit 10.12.12.0/30 eq 30
!
router bgp 65001
   router-id 192.168.1.1
   maximum-paths 2 ecmp 2
   distance bgp 20 200 200
   redistribute connected
   neighbor 172.16.0.1 remote-as 65000
   neighbor 172.16.0.1 maximum-routes 12000
   address-family ipv4
      neighbor 172.16.0.1 prefix-list to-spines out
   neighbor 172.17.0.1 remote-as 65000
   neighbor 172.17.0.1 maximum-routes 12000
   address-family ipv4
      neighbor 172.17.0.1 prefix-list to-spines out
   neighbor 10.12.12.2 remote-as 65001
   neighbor 10.12.12.2 maximum-routes 12000
   neighbor 10.12.12.2 next-hop-self
   network 192.168.1.1/32
!
end

leaf02-vxlan.config

ip routing
!
lldp run
!
vlan 4094
   name mlag
   trunk group mlagpeer
!
vlan 100
   name operations
!
vlan 200
   name staff
!
interface Loopback0
   description router-id
   ip address 192.168.1.2/32
   no shutdown
!
interface Ethernet1
   description P2P Link to Spine01
   no switchport
   ip address 172.16.0.6/30
   no shutdown
!
interface Ethernet2
   description P2P Link to Spine02
   no switchport
   ip address 172.17.0.6/30
   no shutdown
!
interface Ethernet10
   description mlag Link to Leaf01
   no ip address
   no shutdown
   channel-group 12 mode active
!
interface Ethernet11
   description mlag Link to Leaf01
   no ip address
   no shutdown
   channel-group 12 mode active
!
interface Port-Channel12
   description mlag to peer Leaf01
   switchport mode trunk
   switchport trunk group mlagpeer
   no ip address
   no shutdown
!
interface Vlan4094
   description mlag
   ip address 10.12.12.2/30
   no shutdown
!
interface Vlan100
   description operations
   ip address 10.100.100.2/24
   no shutdown
   ip virtual-router address 10.100.100.254
!
interface Vlan200
   description staff
   ip address 10.200.200.2/24
   no shutdown
   ip virtual-router address 10.200.200.254
!
ip virtual-router mac-address aa:00:bb:11:cc:22
!
mlag configuration
   domain-id leaf12
   local-interface Vlan4094
   peer-address 10.12.12.1
   peer-link Port-Channel12
   reload-delay 500
!
ip prefix-list to-spines seq 10 permit 192.168.0.0/23 eq 32
ip prefix-list to-spines seq 20 permit 172.16.0.0/23 eq 30
ip prefix-list to-spines seq 30 permit 10.12.12.0/30 eq 30
!
router bgp 65001
   router-id 192.168.1.2
   maximum-paths 2 ecmp 2
   distance bgp 20 200 200
   redistribute connected
   neighbor 172.16.0.5 remote-as 65000
   neighbor 172.16.0.5 maximum-routes 12000
   address-family ipv4
      neighbor 172.16.0.5 prefix-list to-spines out
   neighbor 172.17.0.5 remote-as 65000
   neighbor 172.17.0.5 maximum-routes 12000
   address-family ipv4
      neighbor 172.17.0.5 prefix-list to-spines out
   neighbor 10.12.12.1 remote-as 65001
   neighbor 10.12.12.1 maximum-routes 12000
   neighbor 10.12.12.1 next-hop-self
   network 192.168.1.2/32
!
end

leaf03-vxlan.config

ip routing
!
lldp run
!
vlan 100
   name operations
!
vlan 200
   name staff
!
interface Loopback0
   description router-id
   ip address 192.168.1.3/32
   no shutdown
!
interface Ethernet1
   description P2P Link to Spine-1
   no switchport
   ip address 172.16.0.10/30
   no shutdown
!
interface Ethernet2
   description P2P Link to Spine-2
   no switchport
   ip address 172.17.0.10/30
   no shutdown
!
interface Vlan100
   description operations
   ip address 10.100.100.3/24
   no shutdown
!
interface Vlan200
   description staff
   ip address 10.200.200.3/24
   no shutdown
!
ip virtual-router mac-address aa:00:bb:11:cc:22
!
ip prefix-list to-spines seq 10 permit 192.168.0.0/23 eq 32
ip prefix-list to-spines seq 20 permit 172.16.0.0/23 eq 30
ip prefix-list to-spines seq 30 permit 10.12.12.0/30 eq 30
!
router bgp 65002
   router-id 192.168.1.3
   maximum-paths 2 ecmp 2
   distance bgp 20 200 200
   redistribute connected
   neighbor 172.16.0.9 remote-as 65000
   neighbor 172.16.0.9 maximum-routes 12000
   address-family ipv4
      neighbor 172.16.0.9 prefix-list to-spines out
   neighbor 172.17.0.9 remote-as 65000
   neighbor 172.17.0.9 maximum-routes 12000
   address-family ipv4
      neighbor 172.17.0.9 prefix-list to-spines out
   network 192.168.1.3/32
!
end

leaf04-vxlan.config

ip routing
!
lldp run
!
vlan 100
   name operations
!
vlan 200
   name staff
!
interface Loopback0
   description router-id
   ip address 192.168.1.4/32
   no shutdown
!
interface Ethernet1
   description P2P Link to Spine-1
   no switchport
   ip address 172.16.0.14/30
   no shutdown
!
interface Ethernet2
   description P2P Link to Spine-2
   no switchport
   ip address 172.17.0.14/30
   no shutdown
!
interface Vlan100
   description operations
   ip address 10.100.100.4/24
   no shutdown
!
interface Vlan200
   description staff
   ip address 10.200.200.4/24
   no shutdown
!
ip virtual-router mac-address aa:00:bb:11:cc:22
!
ip prefix-list to-spines seq 10 permit 192.168.0.0/23 eq 32
ip prefix-list to-spines seq 20 permit 172.16.0.0/23 eq 30
ip prefix-list to-spines seq 30 permit 10.12.12.0/30 eq 30
!
router bgp 65003
   router-id 192.168.1.4
   maximum-paths 2 ecmp 2
   distance bgp 20 200 200
   redistribute connected
   neighbor 172.16.0.13 remote-as 65000
   neighbor 172.16.0.13 maximum-routes 12000
   address-family ipv4
      neighbor 172.16.0.13 prefix-list to-spines out
   neighbor 172.17.0.13 remote-as 65000
   neighbor 172.17.0.13 maximum-routes 12000
   address-family ipv4
      neighbor 172.17.0.13 prefix-list to-spines out
   network 192.168.1.4/32
!
end

Let’s check a few things.

spine01#show ip bgp summary 
BGP summary information for VRF default
Router identifier 192.168.0.1, local AS number 65000
Neighbor Status Codes: m - Under maintenance
  Neighbor         V  AS           MsgRcvd   MsgSent  InQ OutQ  Up/Down State  PfxRcd PfxAcc
  172.16.0.2       4  65001            109       106    0    0 01:38:04 Estab  5      5
  172.16.0.6       4  65001            107       106    0    0 01:38:06 Estab  5      5
  172.16.0.10      4  65002            107       106    0    0 01:38:08 Estab  2      2
  172.16.0.14      4  65003            106       106    0    0 01:38:04 Estab  2      2
spine02#show ip bgp summary
BGP summary information for VRF default
Router identifier 192.168.0.2, local AS number 65000
Neighbor Status Codes: m - Under maintenance
  Neighbor         V  AS           MsgRcvd   MsgSent  InQ OutQ  Up/Down State  PfxRcd PfxAcc
  172.17.0.2       4  65001            108       107    0    0 01:39:52 Estab  5      5
  172.17.0.6       4  65001            106       107    0    0 01:39:52 Estab  5      5
  172.17.0.10      4  65002            105       107    0    0 01:39:52 Estab  2      2
  172.17.0.14      4  65003            105       107    0    0 01:39:52 Estab  2      2
leaf01#show mlag 
MLAG Configuration:   
domain-id              :              leaf12
local-interface        :            Vlan4094
peer-address           :          10.12.12.2
peer-link              :      Port-Channel12
peer-config            :          consistent
                                            
MLAG Status:          
state                  :              Active
negotiation status     :           Connected
peer-link status       :                  Up
local-int status       :                  Up
system-id              :   52:00:00:03:37:66
dual-primary detection :            Disabled
                                            
MLAG Ports:           
Disabled               :                   0
Configured             :                   0
Inactive               :                   0
Active-partial         :                   0
Active-full            :                   0
leaf01#ping 192.168.0.1 repeat 1
PING 192.168.0.1 (192.168.0.1) 72(100) bytes of data.
80 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=10.0 ms

--- 192.168.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 10.049/10.049/10.049/0.000 ms

That’s it for the underlay. The source code for this post can be found here. In part two we will be building the overlay.