This is the first post related to FRR Routing test, mainly anything related to EVPN or L2/L3 VPN in general. As starting point, the following note shows the config example for basic EVPN type 2 and it was tested to work with Cisco Nexus and Arista EOS.
Test Summary
Lab environment
- Basic leaf-spine IP fabric
- vMX as spine and RR
- vEOS, Nexus 9Kv and FRRouting as leaf
- FRRouting run as docker inside Ubuntu 16.04 linux VM
- Traffic type
- L2 stretch with EVPN type 2
- “L3 VPN” with EVPN type 5
Result
- L2 stretch EVPN type 2 works between FRR, NXOS and EOS.
- IRB routing with EVPN-type 2 is not tested yet
- vlan-based evpn is tested. Vlan aware is not tested yet.
- EVPN type 5
- It seems that FRR can receive EVPN type 5 routes (see the sample output section below)
- But, FRR does not advertise anything.
- “advertise-subnet” command as indicated in Cumulus Linux guide is not available in this FRR version (build based on FRR github master branch as of 2018-01-14)
Details
(Optional) upgrade kernel to 4.8
This is optional for later testing, e.g: setup vrf, run mpls/ldp. Not really needed in this post.
apt-get -y install linux-image-4.8.0-41-generic linux-image-extra-4.8.0-41-generic
Update sysctl config to allow forwarding
“net.ipv4.ip_forward = 1” and “net.ipv6.conf.all.forwarding=1” should be good enough for this test, but no harm to implement the whole sysctl setting as recommended by FRRouting.
Put the following into /etc/sysctl.d/99frr_defaults.conf
# /etc/sysctl.d/99frr_defaults.conf
# Place this file at the location above and reload the device.
# or run the sysctl -p /etc/sysctl.d/99frr_defaults.conf
# Enables IPv4/IPv6 Routing
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding=1
# Routing
net.ipv6.route.max_size=131072
net.ipv4.conf.all.ignore_routes_with_linkdown=1
net.ipv6.conf.all.ignore_routes_with_linkdown=1
# Best Settings for Peering w/ BGP Unnumbered
# and OSPF Neighbors
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.lo.rp_filter = 0
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.default.arp_notify = 1
net.ipv4.conf.default.arp_ignore=1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.all.arp_notify = 1
net.ipv4.conf.all.arp_ignore=1
net.ipv4.icmp_errors_use_inbound_ifaddr=1
# Miscellaneous Settings
# Keep ipv6 permanent addresses on an admin down
net.ipv6.conf.all.keep_addr_on_down=1
# igmp
net.ipv4.igmp_max_memberships=1000
net.ipv4.neigh.default.mcast_solicit = 10
# MLD
net.ipv6.mld_max_msf=512
# Garbage Collection Settings for ARP and Neighbors
net.ipv4.neigh.default.gc_thresh2=7168
net.ipv4.neigh.default.gc_thresh3=8192
net.ipv4.neigh.default.base_reachable_time_ms=14400000
net.ipv6.neigh.default.gc_thresh2=3584
net.ipv6.neigh.default.gc_thresh3=4096
net.ipv6.neigh.default.base_reachable_time_ms=14400000
# Use neigh information on selection of nexthop for multipath hops
net.ipv4.fib_multipath_use_neigh=1
# Allows Apps to Work with VRF
net.ipv4.tcp_l3mdev_accept=1
Reboot the host
In theory, we can apply the new rule by using sysctl -p …, but it happened to me that for some reason, the bridge interface does not forward traffic between interface until i reboot the host. No idea why.
setup the network
- setup vxlan interface(s), 1 vxlan per vni
In this example i have vni 10100. I created vxlan100 because the this vni correspon to vlan 100 on the other side. It just my numbering scheme.
ip link add vxlan100 type vxlan id 10100 dstport 4789 local 10.0.0.94
ip link set dev vxlan100 up
- setup IGP link
In this example, i have ens5 interface connected to spine switch. I will enable ospf on this interface when i configure the FRR.
ip a add 10.11.94.2/30 dev ens5
ip link set dev ens5 up
- configure loopback IP
ip a add 10.0.0.94/32 dev lo
ip link set dev lo up
- Setup CE / host facing interface and the bridge
In this example, i have ens6 interface connected to the vxlan CE. I created bridge br100 to connect vxlan tunnel (vxlan100) to the physical interface (ens6)
ip link set dev ens6 up
brctl addbr br100
brctl addif br100 vxlan100
brctl addif br100 ens6
ip a add 10.21.100.94/24 dev br100
ip link set dev br100 up
Run docker image
In this case, because i want to use FRRouting inside docker as the same as if i run natively on the linux host, so I put the container with -net=host. To make it simple, i also provide full proviledge to the container.
# docker run -d -it --net=host --name frr --privileged --restart=always rendoaw/docker_frr
Attach to docker container
There are 2 options. The first option is to attach directly to FRRouting vty shell as shown below. The other option is to attach to bash shell and run vtysh from there. The later option is usefull if we need to modify any FRRouting setting, for example enable/disable some daemons.
root@linux-94:/home/ubuntu# docker exec -it frr vtysh
Hello, this is FRRouting (version 3.1-devyes-gb782607).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
This is a git build of frr-3.1-dev-680-gb782607
Associated branch(es):
local:master
github/frrouting/frr.git/master
linux-94#
(Reference) FRRouting config and show output examples
- Sample EVPN config
root@linux-94:/home/ubuntu# docker exec -it frr vtysh
Hello, this is FRRouting (version 3.1-devyes-gb782607).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
This is a git build of frr-3.1-dev-680-gb782607
Associated branch(es):
local:master
github/frrouting/frr.git/master
linux-94# sh run
Building configuration...
Current configuration:
!
frr version 3.1-devyes
frr defaults traditional
hostname linux-94
username cumulus nopassword
!
service integrated-vtysh-config
!
log syslog informational
!
vrf vrf-110
vni 20110
!
interface ens5
ip ospf network point-to-point
!
router-id 10.0.0.94
!
router bgp 64000
coalesce-time 1000
neighbor 10.0.0.11 remote-as 64000
neighbor 10.0.0.11 update-source 10.0.0.94
!
address-family l2vpn evpn
neighbor 10.0.0.11 activate
vni 20110
rd 10.0.0.94:110
route-target import 64000:110
route-target export 64000:110
advertise-default-gw
exit-vni
vni 10100
rd 10.0.0.94:100
route-target import 64200:100
route-target export 64200:100
exit-vni
advertise-all-vni
advertise ipv4 unicast
exit-address-family
vrf-policy test
exit-vrf-policy
vnc defaults
exit-vnc
!
router bgp 64000 vrf vrf-110
coalesce-time 1000
!
address-family ipv4 unicast
network 0.0.0.0/0
exit-address-family
!
router ospf
network 10.0.0.0/24 area 0
network 10.11.0.0/16 area 0
!
line vty
!
end
linux-94#
- Sample show output
linux-94# show ip ospf neighbor
Neighbor ID Pri State Dead Time Address Interface
RXmtL RqstL DBsmL
10.0.0.11 128 Full/DROther 38.688s 10.11.94.1 ens5:10.11.94.2
0 0 0
linux-94# show bgp l2vpn evpn summary
BGP router identifier 10.0.0.94, local AS number 64000 vrf-id 0
BGP table version 0
RIB entries 25, using 3800 bytes of memory
Peers 1, using 20 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/P
fxRcd
10.0.0.11 4 64000 531 308 0 0 0 01:25:50
20
Total number of neighbors 1
linux-94# show bgp l2vpn evpn route
BGP table version is 0, local router ID is 10.0.0.94
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal
Origin codes: i - IGP, e - EGP, ? - incomplete
EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]
EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]
Network Next Hop Metric LocPrf Weight Path
Route Distinguisher: 10.0.0.11:100
*>i[2]:[0]:[0]:[48]:[00:05:86:2b:d6:f0]
10.0.0.11 100 0 i
*>i[2]:[0]:[0]:[48]:[00:05:86:2b:d6:f0]:[32]:[10.21.100.11]
10.0.0.11 100 0 i
*>i[3]:[0]:[32]:[10.0.0.11]
10.0.0.11 100 0 i
Route Distinguisher: 10.0.0.21:110
*>i[5]:[0]:[24]:[10.21.121.0]
10.0.1.21 0 100 0 ?
Route Distinguisher: 10.0.0.21:32867
*>i[3]:[0]:[32]:[10.0.1.21]
10.0.1.21 100 0 i
Route Distinguisher: 10.0.0.22:100
*>i[2]:[0]:[0]:[48]:[52:55:00:02:11:19]
10.0.0.22 100 0 i
*>i[3]:[0]:[32]:[10.0.0.22]
10.0.0.22 100 0 i
Route Distinguisher: 10.0.0.22:200
*>i[2]:[0]:[0]:[48]:[52:55:00:02:11:19]
10.0.0.22 100 0 i
*>i[3]:[0]:[32]:[10.0.0.22]
10.0.0.22 100 0 i
Route Distinguisher: 10.0.0.23:110
*>i[5]:[0]:[24]:[10.23.123.0]
10.0.1.23 0 100 0 ?
Route Distinguisher: 10.0.0.23:200
*>i[3]:[0]:[32]:[10.0.1.23]
10.0.1.23 100 0 i
Route Distinguisher: 10.0.0.25:100
*>i[2]:[0]:[0]:[48]:[8e:15:27:dd:79:0a]
10.0.0.25 100 0 i
*>i[2]:[0]:[0]:[48]:[8e:15:27:dd:79:0a]:[32]:[10.21.100.125]
10.0.0.25 100 0 i
*>i[3]:[0]:[32]:[10.0.0.25]
10.0.0.25 100 0 i
Route Distinguisher: 10.0.0.25:110
*>i[5]:[0]:[24]:[10.25.125.0]
10.0.0.25 100 0 i
Route Distinguisher: 10.0.0.27:2
*>i[2]:[0]:[0]:[48]:[52:55:01:00:27:00]:[32]:[10.21.100.27]
10.0.0.27 100 0 i
*>i[2]:[0]:[0]:[48]:[52:55:01:00:27:00]:[128]:[fe80::5055:1ff:fe00:2700]
10.0.0.27 100 0 i
*>i[3]:[0]:[32]:[10.0.0.27]
10.0.0.27 100 0 i
Route Distinguisher: 10.0.0.93:100
*>i[2]:[0]:[0]:[48]:[8e:e4:2a:e4:51:ad]
10.0.0.93 100 0 i
*>i[3]:[0]:[32]:[10.0.0.93]
10.0.0.93 100 0 i
Route Distinguisher: 10.0.0.94:100
*> [2]:[0]:[0]:[48]:[ae:6c:61:26:ef:ea]
10.0.0.94 32768 i
*> [3]:[0]:[32]:[10.0.0.94]
10.0.0.94 32768 i
Displayed 22 prefixes (22 paths)
linux-94#
-
Sample tcpdump output
- TCPDUMP from physical interface (encapsulated packet)
# tcpdump -e -s 0 -nv -i ens5 port 4789 ae:6c:61:26:ef:ea > 8e:15:27:dd:79:0a, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 26385, offset 0, flags [DF], proto ICMP (1), length 84) 10.21.100.194 > 10.21.100.125: ICMP echo request, id 24417, seq 80, length 64 02:50:09.041530 52:55:00:02:11:22 > 52:55:01:00:94:01, ethertype IPv4 (0x0800), length 148: (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 134) 10.0.0.25.25167 > 10.0.0.94.4789: VXLAN, flags [I] (0x08), vni 10100 8e:15:27:dd:79:0a > ae:6c:61:26:ef:ea, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 23894, offset 0, flags [none], proto ICMP (1), length 84) 10.21.100.125 > 10.21.100.194: ICMP echo reply, id 24417, seq 80, length 64
- TCPDUMP (decapsulated packet)
# tcpdump -e -s 0 -nv -i br100 02:51:32.095689 ae:6c:61:26:ef:ea > 8e:15:27:dd:79:0a, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 36301, offset 0, flags [DF], proto ICMP (1), length 84) 10.21.100.194 > 10.21.100.125: ICMP echo request, id 24417, seq 163, length 64 02:51:32.126877 8e:15:27:dd:79:0a > ae:6c:61:26:ef:ea, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 34235, offset 0, flags [none], proto ICMP (1), length 84) 10.21.100.125 > 10.21.100.194: ICMP echo reply, id 24417, seq 163, length 64