MPLS howto¶
Short introduction into Linux MPLS. Requirements:
kernel >= 4.4
modules: mpls_router, mpls_iptunnel
$ sudo sysctl net.mpls.platform_labels=$x, where $x -- number of labels
pyroute2 >= 0.4.0
MPLS labels¶
Possible label formats:
# int
"newdst": 20
# list of ints
"newdst": [20]
"newdst": [20, 30]
# string
"newdst": "20/30"
# dict
"newdst": {"label": 20}
# list of dicts
"newdst": [{"label": 20, "tc": 0, "bos": 0, "ttl": 16},
{"label": 30, "tc": 0, "bos": 1, "ttl": 16}]
IPRoute¶
MPLS routes¶
Label swap:
from pyroute2 import IPRoute
from pyroute2.common import AF_MPLS
ipr = IPRoute()
# get the `eth0` interface's index:
idx = ipr.link_lookup(ifname="eth0")[0]
# create the request
req = {"family": AF_MPLS,
"oif": idx,
"dst": 20,
"newdst": [30]}
# set up the route
ipr.route("add", **req)
Please notice that "dst" can specify only one label, even being a list. Label push:
req = {"family": AF_MPLS,
"oif": idx,
"dst": 20,
"newdst": [20, 30]}
ipr.route("add", **req)
One can set up also the via field:
from socket import AF_INET
req = {"family": AF_MPLS,
"oif": idx,
"dst": 20,
"newdst": [30],
"via": {"family": AF_INET,
"addr": "1.2.3.4"}}
ipr.route("add", **req)
MPLS lwtunnel¶
To inject IP packets into MPLS:
req = {"dst": "1.2.3.0/24",
"oif": idx,
"encap": {"type": "mpls",
"labels": [202, 303]}}
ipr.route("add", **req)
NDB¶
Note
basic MPLS routes management in NDB since version 0.5.11
List MPLS routes:
>>> from pyroute2.common import AF_MPLS
>>> ndb.routes.dump().filter(family=AF_MPLS)
('localhost', 0, 28, 20, 0, 0, 254, 4, 0, 1, 0, ...
('localhost', 0, 28, 20, 0, 0, 254, 4, 0, 1, 0, ...
>>> ndb.routes.dump().filter(family=AF_MPLS).select('oif', 'dst', 'newdst')
(40627, '[{"label": 16, "tc": 0, "bos": 1, "ttl": 0}]', '[{"label": 500, ...
(40627, '[{"label": 40, "tc": 0, "bos": 1, "ttl": 0}]', '[{"label": 40, ...
List lwtunnel routes:
>>> ndb.routes.dump().filter(lambda x: x.encap is not None)
('localhost', 0, 2, 24, 0, 0, 254, 4, 0, 1, 16, '10.255.145.0', ...
('localhost', 0, 2, 24, 0, 0, 254, 4, 0, 1, 0, '192.168.142.0', ...
>>> ndb.routes.dump().filter(lambda x: x.encap is not None).select('dst', 'encap')
('10.255.145.0', '[{"label": 20, "tc": 0, "bos": 0, "ttl": 0}, ...
('192.168.142.0', '[{"label": 20, "tc": 0, "bos": 0, "ttl": 0}, ...
Create MPLS routes:
>>> from pyroute2.common import AF_MPLS
>>> ndb.routes.create(family=AF_MPLS,
dst=128, # label
oif=1, # output interface
newdst=[128, 132]).commit() # label stack
Create lwtunnel:
>>> ndb.routes.create(dst='192.168.145.0/24',
gateway='192.168.140.5',
encap={'type': 'mpls',
'labels': [128, 132]}).commit()