ryu.app.rest_vtep

This sample application performs as VTEP for EVPN VXLAN and constructs a Single Subnet per EVI corresponding to the VLAN Based service in [RFC7432].

Note

This app will invoke OVSDB request to the switches. Please set the manager address before calling the API of this app.

$ sudo ovs-vsctl set-manager ptcp:6640
$ sudo ovs-vsctl show
    ...(snip)
    Manager "ptcp:6640"
    ...(snip)

Usage Example

Environment

This example supposes the following environment:

 Host A (172.17.0.1)                      Host B (172.17.0.2)
+--------------------+                   +--------------------+
|   Ryu1             | --- BGP(EVPN) --- |   Ryu2             |
+--------------------+                   +--------------------+
        |                                       |
+--------------------+                   +--------------------+
|   s1 (OVS)         | ===== vxlan ===== |   s2 (OVS)         |
+--------------------+                   +--------------------+
(s1-eth1)    (s1-eth2)                   (s2-eth1)    (s2-eth2)
   |            |                           |            |
+--------+  +--------+                   +--------+  +--------+
| s1h1   |  | s1h2   |                   | s2h1   |  | s2h2   |
+--------+  +--------+                   +--------+  +--------+

Configuration steps

  1. Creates a new BGPSpeaker instance on each host.

    On Host A:

    (Host A)$ curl -X POST -d '{
     "dpid": 1,
     "as_number": 65000,
     "router_id": "172.17.0.1"
     }' http://localhost:8080/vtep/speakers | python -m json.tool
    

    On Host B:

    (Host B)$ curl -X POST -d '{
     "dpid": 1,
     "as_number": 65000,
     "router_id": "172.17.0.2"
     }' http://localhost:8080/vtep/speakers | python -m json.tool
    
  2. Registers the neighbor for the speakers on each host.

    On Host A:

    (Host A)$ curl -X POST -d '{
     "address": "172.17.0.2",
     "remote_as": 65000
     }' http://localhost:8080/vtep/neighbors |
     python -m json.tool
    

    On Host B:

    (Host B)$ curl -X POST -d '{
     "address": "172.17.0.1",
     "remote_as": 65000
     }' http://localhost:8080/vtep/neighbors |
     python -m json.tool
    
  3. Defines a new VXLAN network(VNI=10) on the Host A/B.

    On Host A:

    (Host A)$ curl -X POST -d '{
     "vni": 10
     }' http://localhost:8080/vtep/networks | python -m json.tool
    

    On Host B:

    (Host B)$ curl -X POST -d '{
     "vni": 10
     }' http://localhost:8080/vtep/networks | python -m json.tool
    
  4. Registers the clients to the VXLAN network.

    For “s1h1”(ip=”10.0.0.11”, mac=”aa:bb:cc:00:00:11”) on Host A:

    (Host A)$ curl -X POST -d '{
     "port": "s1-eth1",
     "mac": "aa:bb:cc:00:00:11",
     "ip": "10.0.0.11"
     } ' http://localhost:8080/vtep/networks/10/clients |
     python -m json.tool
    

    For “s2h1”(ip=”10.0.0.21”, mac=”aa:bb:cc:00:00:21”) on Host B:

    (Host B)$ curl -X POST -d '{
     "port": "s2-eth1",
     "mac": "aa:bb:cc:00:00:21",
     "ip": "10.0.0.21"
     } ' http://localhost:8080/vtep/networks/10/clients |
     python -m json.tool
    

Testing

If BGP (EVPN) connection between Ryu1 and Ryu2 has been established, pings between the client s1h1 and s2h1 should work.

(s1h1)$ ping 10.0.0.21

Troubleshooting

If connectivity between s1h1 and s2h1 isn’t working, please check the followings.

  1. Make sure that Host A and Host B have full network connectivity.

    (Host A)$ ping 172.17.0.2
    
  2. Make sure that BGP(EVPN) connection has been established.

    (Host A)$ curl -X GET http://localhost:8080/vtep/neighbors |
     python -m json.tool
    
    ...
    {
        "172.17.0.2": {
            "EvpnNeighbor": {
                "address": "172.17.0.2",
                "remote_as": 65000,
                "state": "up"  # "up" shows the connection established
            }
        }
    }
    
  3. Make sure that BGP(EVPN) routes have been advertised.

    (Host A)$ curl -X GET http://localhost:8080/vtep/networks |
     python -m json.tool
    
     ...
    {
        "10": {
            "EvpnNetwork": {
                "clients": {
                    "aa:bb:cc:00:00:11": {
                        "EvpnClient": {
                            "ip": "10.0.0.11",
                            "mac": "aa:bb:cc:00:00:11",
                            "next_hop": "172.17.0.1",
                            "port": 1
                        }
                    },
                    "aa:bb:cc:00:00:21": {  # route for "s2h1" on Host B
                        "EvpnClient": {
                            "ip": "10.0.0.21",
                            "mac": "aa:bb:cc:00:00:21",
                            "next_hop": "172.17.0.2",
                            "port": 3
                        }
                    }
                },
                "ethernet_tag_id": 0,
                "route_dist": "65000:10",
                "vni": 10
            }
        }
    }
    

4. Make sure that the IPv6 is enabled on your environment. Some Ryu BGP features require the IPv6 connectivity to bind sockets. Mininet seems to disable IPv6 on its installation.

For example:

$ sysctl net.ipv6.conf.all.disable_ipv6
net.ipv6.conf.all.disable_ipv6 = 0  # should NOT be enabled

$ grep GRUB_CMDLINE_LINUX_DEFAULT /etc/default/grub
# please remove "ipv6.disable=1" and reboot
GRUB_CMDLINE_LINUX_DEFAULT="ipv6.disable=1 quiet splash"

5. Make sure that your switch using the OpenFlow version 1.3. This application supports only the OpenFlow version 1.3.

For example:

$ ovs-vsctl get Bridge s1 protocols
["OpenFlow13"]

Note

At the time of this writing, we use the the following version of Ryu, Open vSwitch and Mininet.

$ ryu --version
ryu 4.19

$ ovs-vsctl --version
ovs-vsctl (Open vSwitch) 2.5.2  # APT packaged version of Ubuntu 16.04
Compiled Oct 17 2017 16:38:57
DB Schema 7.12.1

$ mn --version
2.2.1  # APT packaged version of Ubuntu 16.04

REST API

class ryu.app.rest_vtep.RestVtepController(req, link, data, **config)
add_speaker(req, **kwargs)

Creates a new BGPSpeaker instance.

Usage:

Method URI
POST /vtep/speakers

Request parameters:

Attribute Description
dpid ID of Datapath binding to speaker. (e.g. 1)
as_number AS number. (e.g. 65000)
router_id Router ID. (e.g. “172.17.0.1”)

Example:

$ curl -X POST -d '{
 "dpid": 1,
 "as_number": 65000,
 "router_id": "172.17.0.1"
 }' http://localhost:8080/vtep/speakers | python -m json.tool
{
    "172.17.0.1": {
        "EvpnSpeaker": {
            "as_number": 65000,
            "dpid": 1,
            "neighbors": {},
            "router_id": "172.17.0.1"
        }
    }
}
get_speakers(_, **kwargs)

Gets the info of BGPSpeaker instance.

Usage:

Method URI
GET /vtep/speakers

Example:

$ curl -X GET http://localhost:8080/vtep/speakers |
 python -m json.tool
{
    "172.17.0.1": {
        "EvpnSpeaker": {
            "as_number": 65000,
            "dpid": 1,
            "neighbors": {
                "172.17.0.2": {
                    "EvpnNeighbor": {
                        "address": "172.17.0.2",
                        "remote_as": 65000,
                        "state": "up"
                    }
                }
            },
            "router_id": "172.17.0.1"
        }
    }
}
del_speaker(_, **kwargs)

Shutdowns BGPSpeaker instance.

Usage:

Method URI
DELETE /vtep/speakers

Example:

$ curl -X DELETE http://localhost:8080/vtep/speakers |
 python -m json.tool
{
    "172.17.0.1": {
        "EvpnSpeaker": {
            "as_number": 65000,
            "dpid": 1,
            "neighbors": {},
            "router_id": "172.17.0.1"
        }
    }
}
add_neighbor(req, **kwargs)

Registers a new neighbor to the speaker.

Usage:

Method URI
POST /vtep/neighbors

Request parameters:

Attribute Description
address IP address of neighbor. (e.g. “172.17.0.2”)
remote_as AS number of neighbor. (e.g. 65000)

Example:

$ curl -X POST -d '{
 "address": "172.17.0.2",
 "remote_as": 65000
 }' http://localhost:8080/vtep/neighbors |
 python -m json.tool
{
    "172.17.0.2": {
        "EvpnNeighbor": {
            "address": "172.17.0.2",
            "remote_as": 65000,
            "state": "down"
        }
    }
}
get_neighbors(_, **kwargs)

Gets a list of all neighbors.

Usage:

Method URI
GET /vtep/neighbors

Example:

$ curl -X GET http://localhost:8080/vtep/neighbors |
 python -m json.tool
{
    "172.17.0.2": {
        "EvpnNeighbor": {
            "address": "172.17.0.2",
            "remote_as": 65000,
            "state": "up"
        }
    }
}
get_neighbor(_, **kwargs)

Gets the neighbor for the specified address.

Usage:

Method URI
GET /vtep/neighbors/{address}

Request parameters:

Attribute Description
address IP address of neighbor. (e.g. “172.17.0.2”)

Example:

$ curl -X GET http://localhost:8080/vtep/neighbors/172.17.0.2 |
 python -m json.tool
{
    "172.17.0.2": {
        "EvpnNeighbor": {
            "address": "172.17.0.2",
            "remote_as": 65000,
            "state": "up"
        }
    }
}
del_neighbor(_, **kwargs)

Unregister the specified neighbor from the speaker.

Usage:

Method URI
DELETE /vtep/speaker/neighbors/{address}

Request parameters:

Attribute Description
address IP address of neighbor. (e.g. “172.17.0.2”)

Example:

$ curl -X DELETE http://localhost:8080/vtep/speaker/neighbors/172.17.0.2 |
 python -m json.tool
{
    "172.17.0.2": {
        "EvpnNeighbor": {
            "address": "172.17.0.2",
            "remote_as": 65000,
            "state": "up"
        }
    }
}
add_network(req, **kwargs)

Defines a new network.

Usage:

Method URI
POST /vtep/networks

Request parameters:

Attribute Description
vni Virtual Network Identifier. (e.g. 10)

Example:

$ curl -X POST -d '{
 "vni": 10
 }' http://localhost:8080/vtep/networks | python -m json.tool
{
    "10": {
        "EvpnNetwork": {
            "clients": {},
            "ethernet_tag_id": 0,
            "route_dist": "65000:10",
            "vni": 10
        }
    }
}
get_networks(_, **kwargs)

Gets a list of all networks.

Usage:

Method URI
GET /vtep/networks

Example:

$ curl -X GET http://localhost:8080/vtep/networks |
 python -m json.tool
{
    "10": {
        "EvpnNetwork": {
            "clients": {
                "aa:bb:cc:dd:ee:ff": {
                    "EvpnClient": {
                        "ip": "10.0.0.1",
                        "mac": "aa:bb:cc:dd:ee:ff",
                        "next_hop": "172.17.0.1",
                        "port": 1
                    }
                }
            },
            "ethernet_tag_id": 0,
            "route_dist": "65000:10",
            "vni": 10
        }
    }
}
get_network(_, **kwargs)

Gets the network for the specified VNI.

Usage:

Method URI
GET /vtep/networks/{vni}

Request parameters:

Attribute Description
vni Virtual Network Identifier. (e.g. 10)

Example:

$ curl -X GET http://localhost:8080/vtep/networks/10 |
 python -m json.tool
{
    "10": {
        "EvpnNetwork": {
            "clients": {
                "aa:bb:cc:dd:ee:ff": {
                    "EvpnClient": {
                        "ip": "10.0.0.1",
                        "mac": "aa:bb:cc:dd:ee:ff",
                        "next_hop": "172.17.0.1",
                        "port": 1
                    }
                }
            },
            "ethernet_tag_id": 0,
            "route_dist": "65000:10",
            "vni": 10
        }
    }
}
del_network(_, **kwargs)

Deletes the network for the specified VNI.

Usage:

Method URI
DELETE /vtep/networks/{vni}

Request parameters:

Attribute Description
vni Virtual Network Identifier. (e.g. 10)

Example:

$ curl -X DELETE http://localhost:8080/vtep/networks/10 |
 python -m json.tool
{
    "10": {
        "EvpnNetwork": {
            "ethernet_tag_id": 10,
            "clients": [
                {
                    "EvpnClient": {
                        "ip": "10.0.0.11",
                        "mac": "e2:b1:0c:ba:42:ed",
                        "port": 1
                    }
                }
            ],
            "route_dist": "65000:100",
            "vni": 10
        }
    }
}
add_client(req, **kwargs)

Registers a new client to the specified network.

Usage:

Method URI
POST /vtep/networks/{vni}/clients

Request parameters:

Attribute Description
vni Virtual Network Identifier. (e.g. 10)
port Port number to connect client. For convenience, port name can be specified and automatically translated to port number. (e.g. “s1-eth1” or 1)
mac Client MAC address to register. (e.g. “aa:bb:cc:dd:ee:ff”)
ip Client IP address. (e.g. “10.0.0.1”)

Example:

$ curl -X POST -d '{
 "port": "s1-eth1",
 "mac": "aa:bb:cc:dd:ee:ff",
 "ip": "10.0.0.1"
 }' http://localhost:8080/vtep/networks/10/clients |
 python -m json.tool
{
    "10": {
        "EvpnClient": {
            "ip": "10.0.0.1",
            "mac": "aa:bb:cc:dd:ee:ff",
            "next_hop": "172.17.0.1",
            "port": 1
        }
    }
}
del_client(_, **kwargs)

Registers a new client to the specified network.

Usage:

Method URI
DELETE /vtep/networks/{vni}/clients/{mac}

Request parameters:

Attribute Description
vni Virtual Network Identifier. (e.g. 10)
mac Client MAC address to register.

Example:

$ curl -X DELETE http://localhost:8080/vtep/networks/10/clients/aa:bb:cc:dd:ee:ff |
 python -m json.tool
{
    "10": {
        "EvpnClient": {
            "ip": "10.0.0.1",
            "mac": "aa:bb:cc:dd:ee:ff",
            "next_hop": "172.17.0.1",
            "port": 1
        }
    }
}