Nornir

Nornir is a python framework mainly for network automation. Instead of using another tool like Ansible (that you need to learn), you can do the same just using pure python all the way. Ansible doesnt scale well and can be very slow, with nornir you have threading from day zero, so if you have to run tasks in 100 devices, you will feel and see the difference.

I learnt about nornir via Kirk Byers’ course. Unfortunately I didnt have the chance/time to use it in my former day job so now I have had time to review things and do a small project.

From https://github.com/thomarite/ceos-testing in the nornir section you can find the whole environment. I tested on the 3-node topology.

It is nothing special. The script builds the config for BGP or ISIS using jinj2 and yaml files. I have the feeling that my jinja2 is a bit difficult to follow. Then using napalm connects to the devices to push or check the config.

Just one issue, as it seems due to the nature of cEOS relaying on docker and my filesystem, if you decide to push the config (dry_run=False == commit=True) the task will fail (while trying to write startup config) but it is actually executed.

(testdir2) /testdir2/ceos-testing/nornir master$ python buid-config.py -b isis -c
hostname: r1
task: deploy_config for isis
failed: True
logs: Traceback (most recent call last):
...
File ".../testdir2/lib/python3.7/site-packages/pyeapi/eapilib.py", line 469, in send
raise CommandError(code, msg, command_error=err, output=out)
pyeapi.eapilib.CommandError: Error [1000]: CLI command 5 of 5 'write memory' failed: could not run command [Error copying system:/running-config to flash:/startup-config (Operation not permitted)]
changed: False
diff:

hostname: r2
task: deploy_config for isis
failed: False
logs: None
changed: False
diff:

hostname: r3
task: deploy_config for isis
failed: False
logs: None
changed: False
diff:

This shouldn’t happen on vEOS or the real hardware (if you have the correct aaa config of course)

Route Reflectors – Notes

Reflect:
client -> clients and non-clients
non-client -> clients
No Reflect:
non-client -> no-client (normal ibgp)

always advertises to eBGP peers (normal ebgp)
eBGP learned prefixes, advertised to client and non-clients (normal ebgp)

Full Mesh iBGP:

  • between RRs
  • RRs and non-clients
  • clients just need iBGP to RRs.

Reflects ONLY the best route

RRs dont modify on reflected routes: NEXT_HOP, AS_PATH, LP and MED.

Prevent routing information loops: ORIGINATOR_ID and CLUSTER_LIST

Clustering:

  • ORIGINATOR_ID: The first RR creates the Originator_ID and sets it to the BGP router ID of the router that originates the route. So when a client receives a route with its own Originator ID, it is dropped.
  • CLUSTER_LIST: if the local CLUSTER_ID is found in the list, the route is discarded.
    *This is done ONLY in RRs.
    This is ONLY created or updated on a RR during Reflection.
Hierarchical Route Reflection:
2 levels:
- level1 RRs are clients of level2 RR -> level1 RR dont need full mesh between them
- level2 RRs are full mesh between them.

Consider:
size of top-level mesh
number of alternative paths

Hierarchical Route Reflection:
2 levels:

– level1 RRs are clients of level2 RR -> level1 RR dont need full mesh between them
– level2 RRs are full mesh between them.

Consider:

  • size of top-level mesh
  • number of alternative paths

RR Design Priciples:

  • keep logical and physical topologies congruent to increase redundancy and path optimization and prevent loops
    — follow physical topology
    — change physical topology
    — modify logical topology
    — follow physical topology
    — session between RR and non-client shouldnt traverse a client
    — session between RR and client shouldnt traverse a non-client
  • use comparable metrics in route selection to avoid convergence oscillations
    (ie MED – only used between prefixes from same neighbor AS – not used for different AS)
    — full ibgp mess –> no
    — always-compare-med –> no
    — deterministic-med -> ok
    — med=0 (via RM in) -> ok
    — bgp communities ->
  • set proper intra and inter cluster IGP metrics to avoid convergence oscillations
    — multicluster RR architecture: intracluster metrics lower than intercluster.
  • modify next-hop with care. Do so only to bring the RRs into forwarding path.
  • use peer groups with RR to reduce convergence time.

GCP Networking 101 – IP Forwarding

I had my shiny and tiny GCP network for EVE-NG to test vEOS. I built a new VM (vm2) to be my center for automation so I can test stuff like ansible/napalm/nornir etc… But I couldn’t ping from vm2 to the vEOS instances in eve-ng (vm1). Those instances where in a different network attached to vm1 so it had to “route”.

As usual, I missed one step when I created the EVE-NG VM. The official documentation doesnt mention anything regarding enabling routing in the VM. As I am not used to Cloud environments, I assume that any simple Linux VM can forward traffic if configured.

Surprise Surprise. In GCP (not sure in other cloud providers), you need to enable “forwarding” during the VM creation and you can’t change that afterwards in any way.

After checking the second guide I followed, I realised that guide mentioned the point to enable forwarding to avoid the same problem I was facing…

So I had to gave up and had to build both VMs from scratch….

But at the end, I have routing enabled in both VMs and I can ping to the vEOS images.

And another annoying thing. I couldnt update the next hop in a static route defined in the VPC. So I had to delete it and create again pointing to the new VM with the vEOS.

And dealing with the internal IPs…

Moving on, quite frustrating day. But learned several things about GCP netwoking.

IPv6 EH

I was reading a chat today, and people were talking about issues with EH. As usual, I didn’t pay attention to the very beginning of the conversation. At the end, after reading the initial link from the conversation, this was all related to IPv6 Extended Headers. And it seems they can cause issues even showed in a rfc7872.

This is the agenda from “NPS/CAIDA 2020 Virtual IPv6 Workshop” last week. And this Geoff Huston’s presentation that started the conversation. And one more link from Geoff about measuring IPv6.

And this is an old issue about IPv6, fragmentation, load balancers, anycast networks that was very interesting to read. IPv6 MTU is 1280.

I don’t have production experience with IPv6 so I try to learn from others. At some point I need to create a proper IPv6 lab with IPv6 services (NTP, DNS, DHPC, HTTPs, etc)

EVE-NG: Arista Lab

As my last attempt to build a MPLS-SR Arista lab failed usin cEOS. I decided to try a different approach as I need more resources that my laptop has. For sometime, I wanted to use tesuto but I am not sure if it is still on business. From the main page, you can’t find any link to register (and pay) for the service. Although if you search for “pricing” you can find a link to that. That’s it.

The other option was to use EVE-NG. You can use it in your own bare-metal server or in the cloud.

So finally, I decided to spend some money. I signed up for GCP with a $300 free computing offer. So at least I dont pay for GCP yet and then I bought one year of EVE-NG professional. Let’s see how it goes.

Before buying the license, you need to install eve-ng. So I followed the official documentation to use it in GCP as it is quite up to date.

I consulted other links too just to compare other users experiences like these:

https://github.com/NetDevNotes/Eve-NG-in-Google-Cloud

I had an issue during the process. When I had to configure DHCP, the IP wizard was showing garbage in the script. Hopefully I didnt have to add anything just accept all default values.

So once it is done, you need to https to the VM…. it didnt work. Somehow “apache” was started. So after startup, got access. I can login and change the default password.

root@eveng01:/var/www/html# service apache2 start
root@eveng01:/var/www/html# service apache2 status

So far, I am not planning to give it a static IP to the VM and a FQDN from my domain. Maybe in the future if I use it often.

Now, I need to create the Arista lab. I followed one of the links earlier, it was quite handy.

I created my small 3 nodes lab, apply the config. All this with a couple of reboots in each device and you have the lab up and running!

It is nice to work in a system with plenty of RAM. The VM has 60GB of RAM and 16vCPU. So I should be able to create a lab with 14 vEOS (each one needs 4GB and 1CPU).

$ top
top - 13:00:27 up 1:33, 1 user, load average: 2.12, 1.37, 1.04
Tasks: 266 total, 1 running, 168 sleeping, 0 stopped, 0 zombie
%Cpu(s): 10.3 us, 5.9 sy, 0.0 ni, 83.4 id, 0.0 wa, 0.0 hi, 0.4 si, 0.0 st
KiB Mem : 10.2/61838576 [ ]
KiB Swap: 0.0/0 [ ]
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27623 root 20 0 3034100 1.992g 25696 S 100.4 3.4 11:21.40 qemu-system-x86
26120 root 20 0 3034100 1.951g 26068 S 100.0 3.3 8:54.66 qemu-system-x86
24536 root 20 0 3034100 1.915g 26072 S 43.3 3.2 9:16.11 qemu-system-x86
245 root 25 5 0 0 0 S 8.2 0.0 2:05.36 uksmd
7500 www-data 20 0 377908 30744 12732 S 4.5 0.0 0:17.27 apache2
4262 root 20 0 1138416 15732 13508 S 0.8 0.0 0:25.40 janus
5526 tomcat8 20 0 5925452 348168 17676 S 0.8 0.6 0:43.17 java
159 root 20 0 0 0 0 I 0.4 0.0 0:01.13 kworker/6:1-eve
4363 mysql 20 0 2493932 85712 20408 S 0.4 0.1 0:10.80 mysqld
7210 www-data 20 0 377900 31024 12724 S 0.4 0.1 0:07.08 apache2

Unfortunately, I am hitting the same problem, and this time, the MAC addresses are the ones you expect to see based on the interface outputs:

I have asked again Arista if this is expected…

In the main time, I need to learn how to map the devices in the VM to external ports so I can access directly from my laptop.

UPDATE

My Arista SE confirmed that cEOS doesnt support MPLS Data Plane. And this should work with vEOS. So I asked in Arista forum about this problem with vEOS and turns out that this works but you need to be sure that a “physical” interface is attached to the VRF, a Loopback or SVI is not enough.

This seems to be the original post about the problem:

https://eos.arista.com/forum/see-bgp-routes-unable-to-ping/

So I just added a VPC to et3 in each device in CUST-A VRF and I can ping across VRFs!!!

r4#ping vrf CUST-A 192.168.0.2 source 192.168.0.1
PING 192.168.0.2 (192.168.0.2) from 192.168.0.1 : 72(100) bytes of data.
80 bytes from 192.168.0.2: icmp_seq=1 ttl=65 time=70.9 ms
80 bytes from 192.168.0.2: icmp_seq=2 ttl=65 time=64.3 ms
80 bytes from 192.168.0.2: icmp_seq=3 ttl=65 time=58.2 ms
80 bytes from 192.168.0.2: icmp_seq=4 ttl=65 time=50.6 ms
80 bytes from 192.168.0.2: icmp_seq=5 ttl=65 time=58.6 ms
--- 192.168.0.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 47ms
rtt min/avg/max/mdev = 50.613/60.554/70.943/6.786 ms, pipe 5, ipg/ewma 11.817/65.414 ms
r4#

And the funny thing. I can’t see anymore the MPLS packets in the tcpdump 🙂

Anyway, good news, I can carry on creating more complex labs and test some scripting/automation stuff.

This is the latest diagram:

FTP Passive

I have a supplier at my employer that requires to use a FTP server to send big files when you open a support ticket. For a long time (a couple of years) whenever I had to upload big files, I had to use my personal VM because my ftp connections failed from the office. I always blamed the super-smart firewall.

One day, I decided to fix the issue and allow the connection in our corporate firewall. I failed. Still couldnt upload files from the office. So keep using my personal VM.

This week I had to upload again a big file. This time I am working from home, so pretty much it is going to work the upload. Wrong! It fails. Ok, I checked a bit and got to the conclusion that it is my ISP or modem at home that is blocking FTP. Most ISP use CGN to stretch as much as possible the limited IPv4. I have IPv6 at home and my VM has IPv6 too… but the ftp server doesnt.

I checked the internet if there was any know issue with my ISP and FTP connections. No luck. I connected to my modem, nothing obvious messing around with FTP.

I decided to give it a proper go to this issue. I knew that it worked from my VM and it didnt from home. I noticed that I was running the same ftp client version in the VM and at home. So let’s debug the ftp client and take a packet capture in both locations.

CLI from the VM:

$ ftp -vd b.b.b.b
ftp: setsockopt: Bad file descriptor
Name: ftp
---> USER ftp
331 Please specify the password.
Password:
---> PASS XXXX
230 Login successful.
---> SYST
215 UNIX Type: L8
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd support
---> CWD support
250 Directory successfully changed.
ftp> cd 211211
---> CWD 211211
250 Directory successfully changed.
ftp> put TEST.txt
local: TEST.txt remote: TEST.txt
---> TYPE I
200 Switching to Binary mode.
ftp: setsockopt (ignored): Permission denied
---> PORT a,a,a,a,162,57
200 PORT command successful. Consider using PASV.
---> STOR TEST.txt
150 Ok to send data.
226 Transfer complete.
28 bytes sent in 0.00 secs (854.4922 kB/s)
ftp> quit
---> QUIT

And this is the packet capture:

After typing “put” in packet 33, I see a “PASV” message from the server and a new connection (initiated by the server!) is established for the data transfer. All good.

So now, make the same from home and compare.

CLI from home without debug:

$ ftp b.b.b.b
Connected to b.b.b.b.
Name: ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd support
250 Directory successfully changed.
ftp> cd 211211
250 Directory successfully changed.
ftp> put TEST.txt
local: TEST.txt remote: TEST.txt
500 Illegal PORT command.
ftp: bind: Address already in use
ftp> quit
221 Goodbye.

CLI from home with debug:

$ ftp -vd b.b.b.b
ftp: setsockopt: Bad file descriptor
Name: ftp
---> USER ftp
331 Please specify the password.
Password:
---> PASS XXXX
230 Login successful.
---> SYST
215 UNIX Type: L8
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd support
---> CWD support
250 Directory successfully changed.
ftp> cd 211211
---> CWD 211211
250 Directory successfully changed.
ftp> put TEST.txt
local: TEST.txt remote: TEST.txt
---> TYPE I
200 Switching to Binary mode.
ftp: setsockopt (ignored): Permission denied
---> PORT 192,168,1,158,202,145
500 Illegal PORT command.
ftp: bind: Address already in use
ftp> quit
---> QUIT
221 Goodbye.

So with and without debug I keep seeing “ftp: bind: Address already in use”…..

And this is the packet capture from home:

So after I type “put” in packet 32, the answer from the server is a “500”.

I wasnt clearly paying attention to the clues. I was still banging my head why the server was sending a “500 Ilegal PORT command”.

I was comparing both captures and both debug outputs… but still didnt it.

I thought I understood FTP. I knew that you use port TCP 21 to establish the control session and the data session / transfer is via new TCP session using a random port. That’s one of the reasons that using NAT or CGN can screw up your FTP sessions.

So I assumed that the issues wasnt my ISP. So it had to be my side (or me).

So finally, I decided to search for “ftp: bind: Address already in use” as it was the message that came up with and without debugging.

Oh boy, first entry in the face!

https://www.linuxquestions.org/questions/linux-distributions-5/problems-with-ftp-server-bind-address-allready-in-use-213509/

An entry from 2004…. it can’t fix my problem for sure…. keep reading and update from 2020… it says it works…. oh boy II

try using a passive connection with "ftp -p" instead, see if it helps...

There we go:

$ ftp -vdp b.b.b.b
ftp: setsockopt: Bad file descriptor
Name: ftp
---> USER ftp
331 Please specify the password.
Password:
---> PASS XXXX
230 Login successful.
---> SYST
215 UNIX Type: L8
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd support
---> CWD support
250 Directory successfully changed.
ftp> cd 211211
---> CWD 211211
250 Directory successfully changed.
ftp> put TEST.txt
local: TEST.txt remote: TEST.txt
---> TYPE I
200 Switching to Binary mode.
ftp: setsockopt (ignored): Permission denied
---> PASV
227 Entering Passive Mode (b,b,b,b,46,248).
---> STOR TEST.txt
150 Ok to send data.
226 Transfer complete.
26 bytes sent in 0.00 secs (12.5386 kB/s)
ftp> quit
---> QUIT
221 Goodbye.

it worked !!!

I felt embarrassed. Time to search for FTP passive vs active…

Really good explanation. I hope I will never forget it.

  • FTP Active: The client issues a PORT command to the server signalling that it will “actively” provide an IP and port number so the server opens the Data Connection back to the client.
  • FTP Passive: The client issues a PASV command to indicate that it will wait “passively” for the server to supply an IP and port number, after which the client opens a Data Connection to the server.

So it worked in my VM because somehow the ftp server sent a PASV command (maybe because it detects there is no NAT as I have a public IP???).

From home, it failed because, by default, the connection is ftp active, so when the server tried to open the new data connection to me(something I couldnt see in the packet capture…) it failed as my ADSL modem wouldnt allow inbound connections.

Once I enabled “-p” in my connection to the server, all worked because it was me who started the new data connection and my firewall allows everything outbound.

Happy to solve the problem after a couple of years, and after a couple of hours of “serious” troubleshooting. It was shocking how blind I was. I had the ftp error message and the PASV from the trace.

Anyway, I learned something new.

BGP-Free Core

This week I have been following a discussion in NANOG about LDPv6 (there are lot of emails but it is VERY interesting) and I realized that I didnt recognize the term “BGP-Free Core”. So I searched about it. It seems it wasnt an obscure subject and funny enough I have used that design in my MPLS labs in GNS3… So what is BGP-Free core? These are the links I read:

https://blog.ipspace.net/2012/01/bgp-free-service-provider-core-in.html

And this is my favourite.

As in my basic MPLS lab, we only use BGP between PEs, and the P router only does IGP and LDP, it doesnt have to know anything about VRFs.

So for that reason, you need to increase the MTU in your links (4bytes per MPLS label) and link usage increases for the extra overhead.

So it is important to know stuff but as well how to name that stuff 😛

Docker MTU + Docker tcpdump

I am troubleshooting an issue in a docker setup with some Arista cEOS where I can’t ping inside a VRF. First I though it was a MTU issue as when you use MPLS, there is an extra tag in the L2 frame.

…But my pings weren’t that big.

Still wanted to increase the MTU because that’s the expected thing to do in your WAN links if you run MPLS and want your users in different VRFs to be able to use the full 1500 bytes.

After some searching, It seems you can change the default value using the config file as per this link:

$ ip link show docker0
9: docker0: mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:be:73:8c:d3 brd ff:ff:ff:ff:ff:ff
$ cat /etc/docker/daemon.json
{
"data-root": "/home/somebody/storage/docker",
"mtu": 1600
}
$ sudo service docker restart
..
$ ip link show docker0
9: docker0: mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:fb:c0:cf:a2 brd ff:ff:ff:ff:ff:ff

And restart docker. But still had mtu 1500. Checking another link it seems I actually need to create a container so the bridge come up with the new value

$ docker run -d busybox top
...
9: docker0: mtu 1600 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:fb:c0:cf:a2 brd ff:ff:ff:ff:ff:ff

Funny thing, once I started my lab again (using docker-topo) still got MTU 1500!!!

Will have to dig a bit why docker-topo doesnt take the docker mtu 1600 from the config file.

Solution: docker-topo is creating user-defined bridges, so it needs to be told that the mtu is different. The “mtu:1600” in the docker config it is only for the default bridge so when you start the busybox, it is attached to the default bridge and you see 1600.

The other thing I was curious was if I could tcpdump the networks created by docker.

Yes, you can!

# docker network ls

# ifconfig 

# tcpdump -i br-xxxx 

MPLS Segment Routing – Arista Lab

We have been able to create some nice MPLS labs using GNS3 and Cisco IOS. In my current employer, we use Arista so I wanted to create a lab environment with Arista kit to simulate a MPLS Segment Routing network. Keeping in mind that I try to run everything on my laptop, using GNS3 + Arista is not an option. You need to use the Arista vEOS image in GNS3 and it demands 2GB RAM per device and 1 CPU. In the past, I think I just managed to start two vEOS VMs before my laptop gave up. But Arista offers a version of EOS for containers.

So, what’s the difference between a virtual machine (VM) and a container? Well, searching the internet is going to give you many all answers. In my very simplify way:

  • VM: needs an hypervisor to simulate hardware. It uses kernel and user space. It has a full OS. So it is like simulation a whole server/pc (imagine a standalone house)
  • Container: runs in user space. Set of processes that are isolated from the rest of the system. Containers provide a way to virtualize an OS so that multiple workloads can run on a single OS instance (imagine an apartment in a building)

You just need to register in Arista web page to download a cEOS image.

Regarding MPLS Segment Routing (or SPRING for Juniper) it is an evolution of the standard MPLS, that was originally developed to improve the routing performance in core networks: avoid to make a routing look-ups per packet in core devices was very expensive in 80/90s (my very simplify way). MPLS started to being deployed around end 90s and became a defacto technology in all service providers. More info here.

Segment Routing is still based in labels, but adds improvements as it doesnt need a protocol for label exchange (one less thing to worry about). As well, it is based in “source routing” as the sources chooses the path and encodes it in the packet.

There are many sources in the internet that can explain MPLS SR better than me like all these:

https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/seg_routing/configuration/xe-3s/segrt-xe-3s-book/intro-seg-routing.html

https://www.segment-routing.net/tutorials/

As we are going to use Arista, I based my learning in these presentations:

https://ripe77.ripe.net/presentations/16-20181015-SegmentRouting.pdf

https://www.netnod.se/sites/default/files/2018-03/Peter%20Lundqvist_Arista_8.pdf

And reading more Arista docs.

All the code and how to build the lab is here:

https://github.com/thomarite/ceos-testing

So what we need and what we are going to use in this lab:

  • IPv4 (yeah, I should start working in IPv6…)
  • IGP: we use ISIS
  • Label Distribution: ISIS-SR
  • BGP: using loobacks as best practices and using IGP for building a full-mesh
  • L3/2VPN: EVPN
  • All devices are PE

So let’s build the basic IP connectivity for r01:

!
hostname r01
!
interface Ethernet1
no switchport
ip address 10.0.10.1/30
!
interface Ethernet2
no switchport
ip address 10.0.12.1/30
!
interface Loopback1
description CORE Loopback
ip address 10.0.0.1/32
!
ip routing
!

Now let’s build our IGP with ISIS. We are going to use our Lo1 IP as network ID for each router. As well, we will keep it simple and define all routers as ISIS L2. We dont need anything fancy. We just want ISIS to build our iBGP peering. We will enable ISIS in the core interfaces (in this simple lab, all links and loopbacks)

!
router isis CORE
net 49.0000.0001.0010.0000.0000.0001.00  <-- BASED IN Lo1 !!!
is-type level-2
log-adjacency-changes
set-overload-bit on-startup wait-for-bgp timeout 180
!
interface Ethernet1
no switchport
ip address 10.0.10.1/30
isis enable CORE
isis metric 40
isis network point-to-point
!
interface Ethernet2
no switchport
ip address 10.0.12.1/30
isis enable CORE
isis metric 50
isis network point-to-point
!
interface Loopback1
description CORE Loopback
ip address 10.0.0.1/32
isis enable CORE
isis metric 1
!

It is seems there is a bug in the cEOS I am using as “show isis neighbors” fails but the routing is actually correct. Let’s see from r22:

r22#show ip route
VRF: default
Codes: C - connected, S - static, K - kernel,
O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
N2 - OSPF NSSA external type2, B - BGP, B I - iBGP, B E - eBGP,
R - RIP, I L1 - IS-IS level 1, I L2 - IS-IS level 2,
O3 - OSPFv3, A B - BGP Aggregate, A O - OSPF Summary,
NG - Nexthop Group Static Route, V - VXLAN Control Service,
DH - DHCP client installed default route, M - Martian,
DP - Dynamic Policy Route, L - VRF Leaked
Gateway of last resort is not set
I L2 10.0.0.1/32 [115/131] via 10.0.10.9, Ethernet1
I L2 10.0.0.2/32 [115/91] via 10.0.10.9, Ethernet1
I L2 10.0.0.3/32 [115/91] via 10.0.23.1, Ethernet2
I L2 10.0.0.4/32 [115/51] via 10.0.23.1, Ethernet2
I L2 10.0.0.5/32 [115/41] via 10.0.10.9, Ethernet1
C 10.0.0.6/32 is directly connected, Loopback1
I L2 10.0.10.0/30 [115/130] via 10.0.10.9, Ethernet1
I L2 10.0.10.4/30 [115/90] via 10.0.23.1, Ethernet2
C 10.0.10.8/30 is directly connected, Ethernet1
I L2 10.0.12.0/30 [115/140] via 10.0.23.1, Ethernet2
I L2 10.0.13.0/30 [115/90] via 10.0.10.9, Ethernet1
C 10.0.23.0/30 is directly connected, Ethernet2
r22#
r22# show logging
...
Log Buffer:
May 24 16:18:22 r22 SuperServer: %SYS-5-SYSTEM_RESTARTED: System restarted
May 24 16:24:29 r22 ConfigAgent: %SYS-5-CONFIG_E: Enter configuration mode from console by root on vty4 (UnknownIpAddr)
May 24 16:24:29 r22 ConfigAgent: %SYS-5-CONFIG_I: Configured from console by root on vty4 (UnknownIpAddr)
May 24 16:24:29 r22 ConfigAgent: %SYS-5-CONFIG_STARTUP: Startup config saved from system:/running-config by root on vty4 (UnknownIpAddr).
May 24 16:24:39 r22 Isis: %ISIS-4-ISIS_ADJCHG: L2 Neighbor State Change for SystemID 0000.0000.0004 on eth2 to UP
May 24 16:24:42 r22 Isis: %ISIS-4-ISIS_ADJCHG: L2 Neighbor State Change for SystemID 0000.0000.0005 on eth1 to UP
May 24 16:26:34 r22 ConfigAgent: %SYS-5-CONFIG_STARTUP: Startup config saved from system:/running-config by root on vty4 (UnknownIpAddr).
r22#
r22#show isis neighbors
% Internal error
% To see the details of this error, run the command 'show error 2'

Let’s build BGP, from r01 is like this:

!
router bgp 100
router-id 10.0.0.1
graceful-restart restart-time 300
graceful-restart
maximum-paths 2
neighbor AS100-CORE peer group
neighbor AS100-CORE remote-as 100
neighbor AS100-CORE next-hop-self
neighbor AS100-CORE update-source Loopback1
neighbor AS100-CORE timers 2 6
neighbor AS100-CORE additional-paths receive
neighbor AS100-CORE additional-paths send any
neighbor AS100-CORE password 7 Nmg+xbfVkywN7BBIllK5yw==
neighbor AS100-CORE send-community standard extended
neighbor AS100-CORE maximum-routes 0
neighbor 10.0.0.2 peer group AS100-CORE
neighbor 10.0.0.2 description R02
neighbor 10.0.0.3 peer group AS100-CORE
neighbor 10.0.0.3 description R11
neighbor 10.0.0.4 peer group AS100-CORE
neighbor 10.0.0.4 description R12
neighbor 10.0.0.5 peer group AS100-CORE
neighbor 10.0.0.5 description R21
neighbor 10.0.0.6 peer group AS100-CORE
neighbor 10.0.0.6 description R22
!

So once we have configured BGP in all routers, we should see a full mesh between all routers. This is from r22:

r22#show ip bgp summary
BGP summary information for VRF default
Router identifier 10.0.0.6, local AS number 100
Neighbor Status Codes: m - Under maintenance
Description Neighbor V AS MsgRcvd MsgSent InQ OutQ Up/Down State PfxRcd PfxAcc
R01 10.0.0.1 4 100 7 7 0 0 00:00:05 Estab 0 0
R02 10.0.0.2 4 100 7 7 0 0 00:00:05 Estab 0 0
R11 10.0.0.3 4 100 7 7 0 0 00:00:05 Estab 0 0
R12 10.0.0.4 4 100 6 7 0 0 00:00:04 Estab 0 0
R21 10.0.0.5 4 100 6 7 0 0 00:00:04 Estab 0 0
r22#

Now, enable MPLS and SR extension in ISIS:

!
mpls ip
!
mpls label range isis-sr 800000 65536
!
router isis CORE
  segment-routing mpls
    router-id 10.0.0.1  <-- based on Lo1 in each router
    no shutdown
!
interface Loopback1
  description CORE Loopback
  node-segment ipv4 index 1  <-- this has to be different in each node!!!
!

And you should see 5 ISIS-SR tunnels from each router. From r22:

r22#show isis segment-routing tunnel
Index Endpoint Nexthop Interface Labels TI-LFA
tunnel index

1 10.0.0.2/32 10.0.10.9 Ethernet1 [ 800002 ] -
2 10.0.0.3/32 10.0.23.1 Ethernet2 [ 800003 ] -
3 10.0.0.4/32 10.0.23.1 Ethernet2 [ 3 ] -
4 10.0.0.5/32 10.0.10.9 Ethernet1 [ 3 ] -
5 10.0.0.1/32 10.0.10.9 Ethernet1 [ 800001 ] -
r22#

As you can see above, the labels are based on the base index (800000) defined in the “mpls label range” command and the “node-segment index” defined in the loopback interface. So the label that identifies uniquely r01 is 800000 + 1 = 800001. The label “3” means you are a Penultime-Hop-P router and you remove the label to save a label look-up in the egress router.

Now, let’s configure EVPN for L2/L3VPN deployment in our MPLS network. From r01 should be:

!
service routing protocols model multi-agent --> you will have to reboot
!
router bgp 100
!
address-family evpn
neighbor default encapsulation mpls next-hop-self source-interface Loopback1
neighbor 10.0.0.2 activate
neighbor 10.0.0.3 activate
neighbor 10.0.0.4 activate
neighbor 10.0.0.5 activate
neighbor 10.0.0.6 activate
!

So once this is configured in all routers, we should see again a full mesh of EVPN BGP peers. From r12 this time:

r12#show bgp evpn summary
BGP summary information for VRF default
Router identifier 10.0.0.4, local AS number 100
Neighbor Status Codes: m - Under maintenance
Description Neighbor V AS MsgRcvd MsgSent InQ OutQ Up/Down State PfxRcd PfxAcc
R01 10.0.0.1 4 100 1254 1251 0 0 00:03:27 Estab 1 1
R02 10.0.0.2 4 100 1111 1107 0 0 00:03:27 Estab 1 1
R11 10.0.0.3 4 100 961 962 0 0 00:03:27 Estab 1 1
R21 10.0.0.5 4 100 884 888 0 0 00:03:27 Estab 1 1
R22 10.0.0.6 4 100 814 811 0 0 00:03:27 Estab 1 1
r12#

Now, let’s create a L3VPN with CUST-A vrf. We define it in all routers. For r01 should be:

!
vrf instance CUST-A
rd 100:1
!
interface Loopback2
vrf CUST-A
ip address 192.168.0.1/32   <-- each device has a unique one
!
ip routing vrf CUST-A
!
router bgp 100
!
vrf CUST-A
rd 100:1
route-target import evpn 100:1
route-target export evpn 100:1
network 192.168.0.1/32

Let’s see if the routing works from r12

r12#
r12#show bgp evpn
BGP routing table information for VRF default
Router identifier 10.0.0.4, local AS number 100
Route status codes: s - suppressed, * - valid, > - active, # - not installed, E - ECMP head, e - ECMP
S - Stale, c - Contributing to ECMP, b - backup
% - Pending BGP convergence
Origin codes: i - IGP, e - EGP, ? - incomplete
AS Path Attributes: Or-ID - Originator ID, C-LST - Cluster List, LL Nexthop - Link Local Nexthop
Network Next Hop Metric LocPref Weight Path 
RD: 100:1 ip-prefix 192.168.0.1/32 10.0.0.1 - 100 0 i 
RD: 100:1 ip-prefix 192.168.0.2/32 10.0.0.2 - 100 0 i 
RD: 100:1 ip-prefix 192.168.0.3/32 10.0.0.3 - 100 0 i 
RD: 100:1 ip-prefix 192.168.0.5/32 10.0.0.5 - 100 0 i 
RD: 100:1 ip-prefix 192.168.0.6/32 10.0.0.6 - 100 0 i
r12#
r12#show ip route vrf CUST-A
VRF: CUST-A
Codes: C - connected, S - static, K - kernel,
O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
N2 - OSPF NSSA external type2, B - BGP, B I - iBGP, B E - eBGP,
R - RIP, I L1 - IS-IS level 1, I L2 - IS-IS level 2,
O3 - OSPFv3, A B - BGP Aggregate, A O - OSPF Summary,
NG - Nexthop Group Static Route, V - VXLAN Control Service,
DH - DHCP client installed default route, M - Martian,
DP - Dynamic Policy Route, L - VRF Leaked
Gateway of last resort is not set
B I 192.168.0.1/32 [200/0] via 10.0.0.1/32, IS-IS SR tunnel index 5, label 116384
via 10.0.10.5, Ethernet1, label 800001
B I 192.168.0.2/32 [200/0] via 10.0.0.2/32, IS-IS SR tunnel index 2, label 116384
via 10.0.10.5, Ethernet1, label 800002
B I 192.168.0.3/32 [200/0] via 10.0.0.3/32, IS-IS SR tunnel index 3, label 100000
via 10.0.10.5, Ethernet1, label imp-null(3)
C 192.168.0.4/32 is directly connected, Loopback2
B I 192.168.0.5/32 [200/0] via 10.0.0.5/32, IS-IS SR tunnel index 4, label 116384
via 10.0.23.2, Ethernet2, label 800005
B I 192.168.0.6/32 [200/0] via 10.0.0.6/32, IS-IS SR tunnel index 1, label 116384
via 10.0.23.2, Ethernet2, label imp-null(3)
r12#

So, all looks good. EVPN table shows all the prefixes for rd 100:1 and the routing table for CUST-A shows all Lo2 defined in each router.

BTW, I am not able to ping inside the VRF, I think it is something related to the broadcast of ARP:

UPDATE: Arista confirms that cEOS-lab doesn’t support MPLS dataplane. I need to use vEOS (vagrant). So that means I dont think my laptop has enough resources to build this lab in vEOS 🙁

r01#ping vrf CUST-A ip 192.168.0.6 interface loopback 2
PING 192.168.0.6 (192.168.0.6) from 192.168.0.1 lo2: 72(100) bytes of data.
--- 192.168.0.6 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 40ms
r01#

-- from other session in r01 --

r01#bash
bash-4.2# ip netns exec ns-CUST-A tcpdump -i lo2
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo2, link-type EN10MB (Ethernet), capture size 262144 bytes
^C12:46:03.324918 02:00:00:00:00:00 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 192.168.0.6 tell 192.168.0.1, length 28
12:46:04.348750 02:00:00:00:00:00 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 192.168.0.6 tell 192.168.0.1, length 28
12:46:05.376723 02:00:00:00:00:00 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 192.168.0.6 tell 192.168.0.1, length 28
3 packets captured
3 packets received by filter
0 packets dropped by kernel
bash-4.2#

-- from other session in r22, we dont see anything --

r22#bash
bash-4.2# ip netns exec ns-CUST-A tcpdump -i lo2
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo2, link-type EN10MB (Ethernet), capture size 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel
bash-4.2#

New Approach for Datacenter Networks and Stacks for Low Latency

In a irc channel this week, one guy posted a link about visualization latency in a data center switching network .

And it was really good video for understanding how congestion happens inside the switch infrastructure and a very original idea to overcome this problem!

I tried to get a bit more info about the video and ended in the page of that paper:

http://www.cs.ucl.ac.uk/news/article/sigcomm_best_paper_award_for_mark_handley/

And see if there was any implementation:

https://github.com/nets-cs-pub-ro/NDP/wiki

I am not a researcher but the idea is quite original and it seems you dont need to re-invent the wheel. In the github repo even there is an example in P4. P4 is going to be big, and Barefoot has already commercial solutions about it with their tofino chip. Let’s see what Intel does with it…

Based on a continuation paper, it seems there is no much traction from the big cloud providers, and it surprises me, these guys have the muscle to make this kind of things. I always heard that hardware is very expensive to built and software is not. So there are few player willing to invest in new ideas. Everytime you hear about unicorn companies, nearly all of them are software companies.

And another paper says it needs more tuning/debugging.

I don’t know if it will successful in the future but I think it was interesting watching the video and reading about the concept.