Original Article: [https://blog.sherpherd.top/2024/02/11/RunYourMPLSNetworkWithBIRD_en.html](https://blog.sherpherd.top/2024/02/11/RunYourMPLSNetworkWithBIRD_en.html)
# Intro
Now, most tutorials about running MPLS on Linux are based on FRR. Because in a long time, FRR and its predecessor Quagga are the only choices who provide industry standard MPLS related protocol (LDP, BGP-LU, BGP IPv4/IPv6 MPLS L3VPN, etc.) implementation, by the time, most of other routing software don't even have availiable MPLS support.
The most popular routing software among DN42 users, BIRD, has added availiable MPLS support in its newest version (2.14), now BIRD has MPLS-aware, labeled route producing routing protocol, too. (No LDP still though) [<sup>[1]</sup>](#c1)
The newest BIRD 2.0 User Guide has added MPLS function related chapter[<sup>[2]</sup>](#c2), this is an excerpt:
> In BIRD, the whole process generally works this way: A MPLS-aware routing protocol (say BGP) receives
routing information including remote label. It produces a route with attribute mpls policy (p. 30) specifying
desired MPLS label policy (p. 18). Such route then passes the import filter (which could modify the MPLS
label policy or perhaps assign a static label) and when it is accepted, a local MPLS label is selected (according
to the label policy) and attached to the route, producing labeled route. When a new MPLS label is allocated,
the MPLS-aware protocol automatically produces corresponding MPLS route. When all labeled routes that
use specific local MPLS label are retracted, the corresponding MPLS route is retracted too. <br>
There are three important concepts for MPLS in BIRD: MPLS domains, MPLS tables and MPLS channels.
MPLS domain represents an independent label space, all MPLS-aware protocols are associated with some MPLS domain. It is responsible for label management, handling label allocation requests from MPLS-aware protocols. MPLS table is just a routing table for MPLS routes. Routers usually have one MPLS domain and one MPLS table, with Kernel protocol to export MPLS routes into kernel FIB. <br>
MPLS channels make protocols MPLS-aware, they are responsible for keeping track of active FECs (and corresponding allocated labels), selecting FECs / local labels for labeled routes, and maintaining correspondence between labeled routes and MPLS routes.
As mentioned above, the current BGP implementation of BIRD is MPLS-awared, can be used to assign and distribute MPLS labeled route.
In this article, I will make use of official BIRD document to show readers how to construct a simple MPLS VPN network running with BIRD.
# Prerequisites
* Unless specific configuration, your node must running completely independent kernel (dedicated server, KVM virtualization, etc.), so that you can enable MPLS kernel module.
* If you using Vultr VPS, due to unknown reason, Vultr integrated system image has some trouble with MPLS, please reinstall your system with official ISO after deployment.
PC1, R1, R2 and PC2 all running Debian 12. R1 and R2 both installed newest version BIRD by the time I finished this, the BIRD 2.14.
**Notice: Remember to add third port for R1, R2 and R3 to make them able to access Internet for downloading BIRD software package or compiling dependencies**
# 2 Preliminary Work
## 2.1 Enable MPLS Kernel Module
Run these command on R1 and R2 with root permission:
```
modprobe mpls_router
modprobe mpls_iptunnel
modprobe mpls_gso
```
## 2.2 Kernel Parameter Adjustment
Run these command on R1, R2 and R3 with root permission to adjust parameters related to IP routing and MPLS, make them able to work[<sup>[3]</sup>](#c3):
```
cat >/etc/sysctl.d/90-mpls-router.conf <<EOF
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv4.conf.all.rp_filter=0
net.mpls.platform_labels=1048575
net.ipv4.tcp_l3mdev_accept=1
net.ipv4.udp_l3mdev_accept=1
net.mpls.conf.lo.input=1
EOF
sysctl -p /etc/sysctl.d/90-mpls-router.conf
```
### 2.2.1 Enable MPLS Input on MPLS Port
Every port transits MPLS traffic need to enable MPLS input, run these command on R1 and R2 with root permission to enable MPLS input for their port ens19:
```
sysctl -w net.mpls.conf.ens19.input=1
```
So do on R3:
```
sysctl -w net.mpls.conf.ens19.input=1
sysctl -w net.mpls.conf.ens20.input=1
```
**Notice: Every MPLS traffic transiting port need this configuration**
## 2.3 Create VRF and assign VRF for port
Run these command on R1 and R2 with root permission to create a VRF interface named "blue":
```
ip link add blue type vrf table 500
ip link set blue up
```
Run these command on R1 and R2 with root permission to assign ens20 to VRF blue then enable it:
```
ip link set ens20 master blue up
```
### 2.3.1 Adjust Client-faced Port MTU to Avoid Fragmentation
In practice, increasing MTU of core network link is always harder than decreasing client-faced port MTU, and using MPLS incur additional packet header overhead (4 bytes per label), this made large packet may get fragmented when entering MPLS network. To avoid this, we need to approviately decrease the MTU of client-faced port.
Run these command on PC1 and PC2 with root permission to adjust MTU of eth0 then enable it:
```
ip link set eth0 mtu 1492 up
```
Run these command on R1 and R2 with root permission to adjust MTU of ens20:
```
ip link set ens20 mtu 1492
```
## 2.4 IP Address and Static Route Configuration
Run command with root permission on nodes below to done this.
R1:
```
ip addr add 203.0.113.1/32 dev lo
ip addr add 203.0.113.1/32 dev ens19 peer 203.0.113.3/32
ip addr add 192.168.1.1/24 dev ens20
```
R2:
```
ip addr add 203.0.113.2/32 dev lo
ip addr add 203.0.113.2/32 dev ens19 peer 203.0.113.3/32
ip addr add 192.168.2.1/24 dev ens20
```
R3:
```
ip addr add 203.0.113.3/32 dev lo
ip addr add 203.0.113.3/32 dev ens19 peer 203.0.113.1/32
ip addr add 203.0.113.3/32 dev ens20 peer 203.0.113.2/32
```
PC1:
```
ip addr add 192.168.1.2/24 dev eth0
ip route add 192.168.2.0/24 via 192.168.1.1
```
PC1:
```
ip addr add 192.168.2.2/24 dev eth0
ip route add 192.168.1.0/24 via 192.168.2.1
```
## 2.5 Installing BIRD
The compile installed BIRD is incomplete, it lacks system service file, docs, etc.
If you want complete BIRD, you have to build software package then install from it.
If you don't want build yourself, you can download them here (deb package):
PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data.
64 bytes from 192.168.2.2: icmp_seq=1 ttl=61 time=5.53 ms
64 bytes from 192.168.2.2: icmp_seq=2 ttl=61 time=5.03 ms
64 bytes from 192.168.2.2: icmp_seq=3 ttl=61 time=3.73 ms
64 bytes from 192.168.2.2: icmp_seq=4 ttl=61 time=5.97 ms
--- 192.168.2.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 3.729/5.063/5.965/0.838 ms
root@pc1:~# traceroute 192.168.2.2
traceroute to 192.168.2.2 (192.168.2.2), 30 hops max, 60 byte packets
1 192.168.1.1 (192.168.1.1) 5.787 ms 6.165 ms *
2 * * *
3 * * *
4 192.168.2.2 (192.168.2.2) 36.865 ms 37.489 ms 44.775 ms
root@pc1:~#
```
PC2:
```
root@pc2:~# ping -c 4 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=61 time=21.7 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=61 time=4.35 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=61 time=13.6 ms
64 bytes from 192.168.1.2: icmp_seq=4 ttl=61 time=4.67 ms
--- 192.168.1.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3007ms
rtt min/avg/max/mdev = 4.352/11.098/21.731/7.181 ms
root@pc2:~# traceroute 192.168.1.2
traceroute to 192.168.1.2 (192.168.1.2), 30 hops max, 60 byte packets
1 192.168.2.1 (192.168.2.1) 17.272 ms 17.125 ms 17.175 ms
2 * * *
3 * * *
4 192.168.1.2 (192.168.1.2) 27.517 ms 27.945 ms 32.354 ms
root@pc2:~#
```
# 5 Reference
<spanid="c1">1. BIRD Team. (2023, October 7). _News Archive_. bird.network.cz. [https://bird.network.cz/?o_news/](https://bird.network.cz/?o_news/)</span>
<spanid="c2">2. BIRD Team. (2023, October 7). BIRD 2.0 User’s Guide. _MPLS_, 9-10. [https://bird.network.cz/download/bird-doc-2.14.tar.gz](https://bird.network.cz/download/bird-doc-2.14.tar.gz)</span>
<spanid="c3">3. James Swineson. (2020, February 22). _Use Linux as an MPLS Router_. blog.swineson.me. [https://blog.swineson.me/en/use-linux-as-an-mpls-router/](https://blog.swineson.me/en/use-linux-as-an-mpls-router/)</span>