MPLS howto — pyroute2 0.5.9 documentation

# 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
    "dst": 20

    # list of ints
    "newdst": [20]
    "newdst": [20, 30]

    # string
    "labels": "20/30"

Any of these notations should be accepted by pyroute2, if not – try another format and submit an issue to the project github page. The code is quite new, some issues are possible.

Refer also to the test cases, there are many usage samples:

- tests/general/test_ipr.py
- tests/general/test_ipdb.py

## 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)

Notice, that dst is a single label, while newdst is a stack. 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)

## IPDB

### MPLS routes

The IPDB database also supports MPLS routes, they are reflected in the ipdb.routes.tables[“mpls”]:

    >>> (ipdb
    ...  .routes
    ...  .add({"family": AF_MPLS,
    ...        "oif": ipdb.interfaces["eth0"]["index"],
    ...        "dst": 20,
    ...        "newdst": [30]})
    ...  .commit())
    <skip>
    >>> (ipdb
    ...  .routes
    ...  .add({"family": AF_MPLS,
    ...        "oif": ipdb.interfaces["eth0"]["index"],
    ...        "dst": 22,
    ...        "newdst": [22, 42]})
    ...  .commit())
    <skip>
    >>> ipdb.routes.tables["mpls"].keys()
    [20, 22]

Pls notice, that there is only one MPLS routing table.

Multipath MPLS:

    with IDPB() as ipdb:
        (ipdb
         .routes
         .add({"family": AF_MPLS,
               "dst": 20,
               "multipath": [{"via": {"family": AF_INET,
                                      "addr": "10.0.0.2"},
                              "oif": ipdb.interfaces["eth0"]["index"],
                              "newdst": [30]},
                             {"via": {"family": AF_INET,
                                      "addr": "10.0.0.3"},
                              "oif": ipdb.interfaces["eth0"]["index"],
                              "newdst": [40]}]})
         .commit())

### MPLS lwtunnel

LWtunnel routes reside in common route tables:

    with IPDB() as ipdb:
        (ipdb
         .routes
         .add({"dst": "1.2.3.0/24",
               "oif": ipdb.interfaces["eth0"]["index"],
               "encap": {"type": "mpls",
                         "labels": [22]}})
         .commit())
        print(ipdb.routes["1.2.3.0/24"])

Multipath MPLS lwtunnel:

    with IPDB() as ipdb:
        (ipdb
         .routes
         .add({"dst": "1.2.3.0/24",
               "table": 200,
               "multipath": [{"oif": ipdb.interfaces["eth0"]["index"],
                              "gateway": "10.0.0.2",
                              "encap": {"type": "mpls",
                                        "labels": [200, 300]}},
                             {"oif": ipdb.interfaces["eth1"]["index"],
                              "gateway": "172.16.0.2",
                              "encap": {"type": "mpls",
                                        "labels": [200, 300]}}]})
         .commit())
        print(ipdb.routes.tables[200]["1.2.3.0/24"])