.. _mpls: 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()