[lighty.io] OVSDB & OpenFlow Controller

OVSDB and OpenFlow controller based on lighty.io

PANTHEON.tech has recently published an example application of an SDN controller, using RESTCONF Northbound module and OVSDB + OpenFlow Southbound modules.

In this blog we are going to describe, how to use the SDN controller with an Open vSwitch instance running in OpenStack.

Open vSwitch, OVSDB & OpenFlow

Open vSwitch is open source virtual switch which uses OVSDB (Open vSwitch Database) and OVSDB management protocol for management of virtual OpenFlow switches referred to as bridges.

The bridges are configurable by OpenFlow protocol according to OpenFlow switch specification.

We have already written a blog about OpenFlow protocol and its support by lighty.io. There’s also example SDN controller application called lighty-community-restconf-ofp-app. It utilizes RESTCONF northbound module and OpenFlow southbound module only. You can find it at our GitHub repository.

Connecting to Open vSwitch of OpenStack

In this blog, we will show you some example setup and sequence of requests using both OVSDB and OpenFlow protocols implemented as SB modules in lighty.io.

We have published an example SDN controller called lighty-community-restconf-ovsdb-app, which utilizes RESTCONF northbound module and OVSDB southbound module only. You can check its README.md file and Postman collection for more details.

As we have already mentioned, Open vSwitch used in the testing setup is running in OpenStack. Here is a picture and description of the setup:

OpenStack Environment with lighty.io - Scheme

image2019 3 7 19 25 56

The SDN controller is running on a machine with IP address 10.14.0.160 with RESTCONF NB plugin & opening Port 8888.

  • Postman or curl requests are submitted from the same machine where SDN controller is running, so URLs use localhost address (127.0.0.1)
  • Open vSwitch instance is running on a machine with IP address 10.14.0.103 (the same address used in ovs-vsctl command explained above) The tested instance has been set up by DevStack scripts but it can be any Open vSwitch instance running in OpenStack Network node, compute node or outside of OpenStack.
  • TCP port used for OVSDB server(s) is 6640
  • TCP port used by OpenFlow server(s) is 6633

Example workflow

Subsequent requests can be found in the repository at GitHub, in the form of Postman collection. In the README.md & in this blog, we are using a curl command to send the RESTCONF requests. We are also using the Python module json.tool for printing of JSON responses.

1. Configure OVSDB manager of Open vSwitch

The following piece of the ovsvsctl show command output shows the initial configuration of the Open vSwitch and its state, where we can see that the Neutron service is connected as OVSDB manager (Manager “ptcp:6640:127.0.0.1”). The Neutron service is also configured as OpenFlow controller for the bridge br-tun (Controller “tcp:127.0.0.1:6633”) and br-tun is connected to the controller.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo ovs-vsctl show
729321e6-991d-4ae5-a4f9-96b1e2919596
Manager "ptcp:6640:127.0.0.1"
is_connected: true
Bridge br-tun
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port br-tun
Interface br-tun
type: internal
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
sudo ovs-vsctl show 729321e6-991d-4ae5-a4f9-96b1e2919596 Manager "ptcp:6640:127.0.0.1" is_connected: true Bridge br-tun Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port br-tun Interface br-tun type: internal Port patch-int Interface patch-int type: patch options: {peer=patch-tun}
sudo ovs-vsctl show
729321e6-991d-4ae5-a4f9-96b1e2919596
    Manager "ptcp:6640:127.0.0.1"
        is_connected: true
    Bridge br-tun
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-tun
            Interface br-tun
                type: internal
        Port patch-int
            Interface patch-int
                type: patch
                options: {peer=patch-tun}

Using this ovs-vsctl command we set up Open vSwitch to listen to second OVSDB manager connection at TCP port 6640 and an interface with IP address 10.14.0.103. The command keeps the configuration for Neutron service as OVSDB manager (ptcp:6640:127.0.0.1).

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo ovs-vsctl set-manager ptcp:6640:127.0.0.1 ptcp:6640:10.14.0.103
sudo ovs-vsctl set-manager ptcp:6640:127.0.0.1 ptcp:6640:10.14.0.103
sudo ovs-vsctl set-manager ptcp:6640:127.0.0.1 ptcp:6640:10.14.0.103

The output of “ovs-vsctl show” command must be changed, as a result of the command above. There should be two managers configured, but only one of them is connected. The connected one is Neutron service and we have to start and configure the SDN controller, in order to initiate OVSDB connection from the controller’s side.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo ovs-vsctl show
729321e6-991d-4ae5-a4f9-96b1e2919596
Manager "ptcp:6640:127.0.0.1"
is_connected: true
Manager "ptcp:6640:10.14.0.103"
Bridge br-tun
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port br-tun
Interface br-tun
type: internal
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
sudo ovs-vsctl show 729321e6-991d-4ae5-a4f9-96b1e2919596 Manager "ptcp:6640:127.0.0.1" is_connected: true Manager "ptcp:6640:10.14.0.103" Bridge br-tun Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port br-tun Interface br-tun type: internal Port patch-int Interface patch-int type: patch options: {peer=patch-tun}
sudo ovs-vsctl show
729321e6-991d-4ae5-a4f9-96b1e2919596
    Manager "ptcp:6640:127.0.0.1"
        is_connected: true
    Manager "ptcp:6640:10.14.0.103"
    Bridge br-tun
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-tun
            Interface br-tun
                type: internal
        Port patch-int
            Interface patch-int
                type: patch
                options: {peer=patch-tun}

2. Setup OVSDB connection

This RESTCONF request results in OVSDB session initiation to the pre-configured OVSDB server in the Open vSwitch.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request PUT \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Content-Type: application/json' \
--data '{
"network-topology:node": [
{
"node-id": "ovsdb://HOST1",
"connection-info": {
"ovsdb:remote-port": "6640",
"ovsdb:remote-ip": "10.14.0.103"
}
}
]
}'
curl -v --request PUT \ --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Content-Type: application/json' \ --data '{ "network-topology:node": [ { "node-id": "ovsdb://HOST1", "connection-info": { "ovsdb:remote-port": "6640", "ovsdb:remote-ip": "10.14.0.103" } } ] }'
curl -v --request PUT \
  --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \
  --header 'Authorization: Basic YWRtaW46YWRtaW4=' \
  --header 'Content-Type: application/json' \
  --data '{
        "network-topology:node": [
          {
            "node-id": "ovsdb://HOST1",
            "connection-info": {
              "ovsdb:remote-port": "6640",
              "ovsdb:remote-ip": "10.14.0.103"
            }
          }
        ]
      }'

You can check whether the session has been established using the “ovs-vsctl” show command. Both OVSDB managers should be connected now. You can also use the next RESTCONF request.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo ovs-vsctl show
729321e6-991d-4ae5-a4f9-96b1e2919596
Manager "ptcp:6640:127.0.0.1"
is_connected: true
Manager "ptcp:6640:10.14.0.103"
is_connected: true
Bridge br-tun
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port br-tun
Interface br-tun
type: internal
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
sudo ovs-vsctl show 729321e6-991d-4ae5-a4f9-96b1e2919596 Manager "ptcp:6640:127.0.0.1" is_connected: true Manager "ptcp:6640:10.14.0.103" is_connected: true Bridge br-tun Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port br-tun Interface br-tun type: internal Port patch-int Interface patch-int type: patch options: {peer=patch-tun}
sudo ovs-vsctl show
729321e6-991d-4ae5-a4f9-96b1e2919596
    Manager "ptcp:6640:127.0.0.1"
        is_connected: true
    Manager "ptcp:6640:10.14.0.103"
        is_connected: true
    Bridge br-tun
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-tun
            Interface br-tun
                type: internal
        Port patch-int
            Interface patch-int
                type: patch
                options: {peer=patch-tun}

3. Retrieve OVSDB network topology data (all nodes)

Now, we are going to ask lighty.io (meaning the SDN controller) about the state of OVS. In this step, we are going to access the SDN controller through a RESTCONF request. The controller will then create a request via the OVSDB protocol and OVS will create the same request, as shown in OVS-VSCTL show.

This RPC request returns the same data as an output of the ovs-vsctl show command. But the show command returns text output. In case of RPC request, the output is formatted as JSON or XML (depending on the Accept header) what is more appropriate for API between software layers of SDN solutions (i.e.: RPCs returning JSON or XML formatted output of commands are SDN ready).

NOTE: In this state, the OVSDB connection between SDN controller and Open vSwitch is established. There’s also another connection which is used by Neutron service. You can check this in the output of ovs-vsctl show:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Manager "ptcp:6640:127.0.0.1"
is_connected: true
Manager "ptcp:6640:10.14.0.103"
is_connected: true
Manager "ptcp:6640:127.0.0.1" is_connected: true Manager "ptcp:6640:10.14.0.103" is_connected: true
Manager "ptcp:6640:127.0.0.1"
    is_connected: true
Manager "ptcp:6640:10.14.0.103"
    is_connected: true

… and also in the output of RESTCONF request:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"ovsdb:manager-entry": [
{
"target": "ptcp:6640:127.0.0.1",
"connected": true,
"number_of_connections": 5
},
{
"target": "ptcp:6640:10.14.0.103",
"connected": true,
"number_of_connections": 1
}
]
"ovsdb:manager-entry": [ { "target": "ptcp:6640:127.0.0.1", "connected": true, "number_of_connections": 5 }, { "target": "ptcp:6640:10.14.0.103", "connected": true, "number_of_connections": 1 } ]
"ovsdb:manager-entry": [
    {
        "target": "ptcp:6640:127.0.0.1",
        "connected": true,
        "number_of_connections": 5
    },
    {
        "target": "ptcp:6640:10.14.0.103",
        "connected": true,
        "number_of_connections": 1
    }
]

The only OpenFlow connection(s) in this state are used by Neutron service, you can see it in the output of ovs-vsctl show:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Bridge br-int
Controller "tcp:127.0.0.1:6633"
is_connected: true
Bridge br-ex
Controller "tcp:127.0.0.1:6633"
is_connected: true
... and the same for other bridges
Bridge br-int Controller "tcp:127.0.0.1:6633" is_connected: true Bridge br-ex Controller "tcp:127.0.0.1:6633" is_connected: true ... and the same for other bridges
    Bridge br-int
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
    Bridge br-ex
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
... and the same for other bridges

… and also in the output of RESTCONF request:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
... all bridges should have:
"ovsdb:controller-entry": [
{
"target": "tcp:127.0.0.1:6633",
"controller-uuid": "de378546-d727-4631-8d46-fa57d78737d9",
"is-connected": true
}
],
... all bridges should have: "ovsdb:controller-entry": [ { "target": "tcp:127.0.0.1:6633", "controller-uuid": "de378546-d727-4631-8d46-fa57d78737d9", "is-connected": true } ],
... all bridges should have:
                    "ovsdb:controller-entry": [
                        {
                            "target": "tcp:127.0.0.1:6633",
                            "controller-uuid": "de378546-d727-4631-8d46-fa57d78737d9",
                            "is-connected": true
                        }
                    ],

Here is an example of complete ovs-vsctl show command output:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo ovs-vsctl show
729321e6-991d-4ae5-a4f9-96b1e2919596
Manager "ptcp:6640:127.0.0.1"
is_connected: true
Manager "ptcp:6640:10.14.0.103"
is_connected: true
Bridge br-tun
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port br-tun
Interface br-tun
type: internal
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
Bridge br-int
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port "tap2f509846-a3"
tag: 4
Interface "tap2f509846-a3"
type: internal
Port "qr-40a33ce6-dd"
tag: 6
Interface "qr-40a33ce6-dd"
type: internal
Port "tape9302402-e4"
tag: 1
Interface "tape9302402-e4"
type: internal
Port "tap63c483cb-87"
tag: 6
Interface "tap63c483cb-87"
type: internal
Port "tap960bd59d-2e"
tag: 5
Interface "tap960bd59d-2e"
type: internal
Port "tap74a59f96-94"
tag: 3
Interface "tap74a59f96-94"
type: internal
Port "qg-9285bad8-81"
tag: 2
Interface "qg-9285bad8-81"
type: internal
Port "tap3792b4af-27"
tag: 7
Interface "tap3792b4af-27"
type: internal
Port int-br-infra
Interface int-br-infra
type: patch
options: {peer=phy-br-infra}
Port "qr-9da1a177-1a"
tag: 7
Interface "qr-9da1a177-1a"
type: internal
Port "qg-7f8467e0-a4"
tag: 2
Interface "qg-7f8467e0-a4"
type: internal
Port "qr-7da2c452-59"
tag: 1
Interface "qr-7da2c452-59"
type: internal
Port "qg-5a4bd0e5-a0"
tag: 2
Interface "qg-5a4bd0e5-a0"
type: internal
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port int-br-ex
Interface int-br-ex
type: patch
options: {peer=phy-br-ex}
Port "qr-91d9970c-ef"
tag: 1
Interface "qr-91d9970c-ef"
type: internal
Port br-int
Interface br-int
type: internal
Bridge br-ex
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port br-ex
Interface br-ex
type: internal
Port phy-br-ex
Interface phy-br-ex
type: patch
options: {peer=int-br-ex}
Bridge br-infra
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port br-infra
Interface br-infra
type: internal
Port phy-br-infra
Interface phy-br-infra
type: patch
options: {peer=int-br-infra}
ovs_version: "2.9.2"
sudo ovs-vsctl show 729321e6-991d-4ae5-a4f9-96b1e2919596 Manager "ptcp:6640:127.0.0.1" is_connected: true Manager "ptcp:6640:10.14.0.103" is_connected: true Bridge br-tun Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port br-tun Interface br-tun type: internal Port patch-int Interface patch-int type: patch options: {peer=patch-tun} Bridge br-int Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port "tap2f509846-a3" tag: 4 Interface "tap2f509846-a3" type: internal Port "qr-40a33ce6-dd" tag: 6 Interface "qr-40a33ce6-dd" type: internal Port "tape9302402-e4" tag: 1 Interface "tape9302402-e4" type: internal Port "tap63c483cb-87" tag: 6 Interface "tap63c483cb-87" type: internal Port "tap960bd59d-2e" tag: 5 Interface "tap960bd59d-2e" type: internal Port "tap74a59f96-94" tag: 3 Interface "tap74a59f96-94" type: internal Port "qg-9285bad8-81" tag: 2 Interface "qg-9285bad8-81" type: internal Port "tap3792b4af-27" tag: 7 Interface "tap3792b4af-27" type: internal Port int-br-infra Interface int-br-infra type: patch options: {peer=phy-br-infra} Port "qr-9da1a177-1a" tag: 7 Interface "qr-9da1a177-1a" type: internal Port "qg-7f8467e0-a4" tag: 2 Interface "qg-7f8467e0-a4" type: internal Port "qr-7da2c452-59" tag: 1 Interface "qr-7da2c452-59" type: internal Port "qg-5a4bd0e5-a0" tag: 2 Interface "qg-5a4bd0e5-a0" type: internal Port patch-tun Interface patch-tun type: patch options: {peer=patch-int} Port int-br-ex Interface int-br-ex type: patch options: {peer=phy-br-ex} Port "qr-91d9970c-ef" tag: 1 Interface "qr-91d9970c-ef" type: internal Port br-int Interface br-int type: internal Bridge br-ex Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port br-ex Interface br-ex type: internal Port phy-br-ex Interface phy-br-ex type: patch options: {peer=int-br-ex} Bridge br-infra Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port br-infra Interface br-infra type: internal Port phy-br-infra Interface phy-br-infra type: patch options: {peer=int-br-infra} ovs_version: "2.9.2"
sudo ovs-vsctl show
729321e6-991d-4ae5-a4f9-96b1e2919596
    Manager "ptcp:6640:127.0.0.1"
        is_connected: true
    Manager "ptcp:6640:10.14.0.103"
        is_connected: true
    Bridge br-tun
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-tun
            Interface br-tun
                type: internal
        Port patch-int
            Interface patch-int
                type: patch
                options: {peer=patch-tun}
    Bridge br-int
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port "tap2f509846-a3"
            tag: 4
            Interface "tap2f509846-a3"
                type: internal
        Port "qr-40a33ce6-dd"
            tag: 6
            Interface "qr-40a33ce6-dd"
                type: internal
        Port "tape9302402-e4"
            tag: 1
            Interface "tape9302402-e4"
                type: internal
        Port "tap63c483cb-87"
            tag: 6
            Interface "tap63c483cb-87"
                type: internal
        Port "tap960bd59d-2e"
            tag: 5
            Interface "tap960bd59d-2e"
                type: internal
        Port "tap74a59f96-94"
            tag: 3
            Interface "tap74a59f96-94"
                type: internal
        Port "qg-9285bad8-81"
            tag: 2
            Interface "qg-9285bad8-81"
                type: internal
        Port "tap3792b4af-27"
            tag: 7
            Interface "tap3792b4af-27"
                type: internal
        Port int-br-infra
            Interface int-br-infra
                type: patch
                options: {peer=phy-br-infra}
        Port "qr-9da1a177-1a"
            tag: 7
            Interface "qr-9da1a177-1a"
                type: internal
        Port "qg-7f8467e0-a4"
            tag: 2
            Interface "qg-7f8467e0-a4"
                type: internal
        Port "qr-7da2c452-59"
            tag: 1
            Interface "qr-7da2c452-59"
                type: internal
        Port "qg-5a4bd0e5-a0"
            tag: 2
            Interface "qg-5a4bd0e5-a0"
                type: internal
        Port patch-tun
            Interface patch-tun
                type: patch
                options: {peer=patch-int}
        Port int-br-ex
            Interface int-br-ex
                type: patch
                options: {peer=phy-br-ex}
        Port "qr-91d9970c-ef"
            tag: 1
            Interface "qr-91d9970c-ef"
                type: internal
        Port br-int
            Interface br-int
                type: internal
    Bridge br-ex
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-ex
            Interface br-ex
                type: internal
        Port phy-br-ex
            Interface phy-br-ex
                type: patch
                options: {peer=int-br-ex}
    Bridge br-infra
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-infra
            Interface br-infra
                type: internal
        Port phy-br-infra
            Interface phy-br-infra
                type: patch
                options: {peer=int-br-infra}
    ovs_version: "2.9.2"

The related RESTCONF request:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool
curl -v --request GET \ --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1 \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Accept: application/json' \ | python -m json.tool
curl -v --request GET \
  --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1 \
  --header 'Authorization: Basic YWRtaW46YWRtaW4=' \
  --header 'Accept: application/json' \
  | python -m json.tool

The example output of the request can be found here. 

4. Retrieve specific node from OVSDB topology data (node-id: “ovsdb://HOST1”)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool
curl -v --request GET \ --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Accept: application/json' \ | python -m json.tool
curl -v --request GET \
  --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \
  --header 'Authorization: Basic YWRtaW46YWRtaW4=' \
  --header 'Accept: application/json' \
  | python -m json.tool

Since there’s only one OVSDB topology node in the SDN controller, the output contains the same data as in case of the previous request.

5. Retrieve OVSDB data of specific bridge (br-int):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool
curl -v --request GET \ --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Accept: application/json' \ | python -m json.tool
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool

This request returns only a subset of data related to the bridge br-int.

6. Setup SDN controller as OpenFlow controller for bridge br-int:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request PUT \
--url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Content-Type: application/json' \
--data '{
"network-topology:node": [
{
"node-id": "ovsdb://HOST1/bridge/br-int",
"ovsdb:bridge-name": "br-int",
"ovsdb:controller-entry": [
{
"target": "tcp:10.14.0.160:6633"
}
]
}
]
}'
curl -v --request PUT \ --url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Content-Type: application/json' \ --data '{ "network-topology:node": [ { "node-id": "ovsdb://HOST1/bridge/br-int", "ovsdb:bridge-name": "br-int", "ovsdb:controller-entry": [ { "target": "tcp:10.14.0.160:6633" } ] } ] }'
curl -v --request PUT \
  --url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int \
  --header 'Authorization: Basic YWRtaW46YWRtaW4=' \
  --header 'Content-Type: application/json' \
  --data '{
            "network-topology:node": [
                  {
                    "node-id": "ovsdb://HOST1/bridge/br-int",
                       "ovsdb:bridge-name": "br-int",
                        "ovsdb:controller-entry": [
                          {
                            "target": "tcp:10.14.0.160:6633"
                          }
                        ]
                  }
              ]
          }'

 7. Check the state of the connection – retrieve the controller-entry list of br-int:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request GET \
--url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int/controller-entry=tcp%3A10.14.0.160%3A6633 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool
curl -v --request GET \ --url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int/controller-entry=tcp%3A10.14.0.160%3A6633 \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Accept: application/json' \ | python -m json.tool
curl -v --request GET \
  --url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int/controller-entry=tcp%3A10.14.0.160%3A6633 \
  --header 'Authorization: Basic YWRtaW46YWRtaW4=' \
  --header 'Accept: application/json' \
  | python -m json.tool

The GET request above only retrieves OVSDB data of OpenFlow connection between Open vSwitch and SDN controller. The output only contains one entry (if the OpenFlow connection is established then the item “is-connected” is set to true):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"ovsdb:controller-entry": [
{
"controller-uuid": "5bfe55c9-70da-4e3b-b1ff-c6ecc8b6e62c",
"is-connected": true,
"target": "tcp:10.14.0.160:6633"
}
]
}
{ "ovsdb:controller-entry": [ { "controller-uuid": "5bfe55c9-70da-4e3b-b1ff-c6ecc8b6e62c", "is-connected": true, "target": "tcp:10.14.0.160:6633" } ] }
{
    "ovsdb:controller-entry": [
        {
            "controller-uuid": "5bfe55c9-70da-4e3b-b1ff-c6ecc8b6e62c",
            "is-connected": true,
            "target": "tcp:10.14.0.160:6633"
        }
    ]
}

In the output of ovs-vsctl show command or previous get requests to OVSDB, you will also see a connection between Open vSwitch and Neutron service:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"ovsdb:controller-entry": [
{
"target": "tcp:127.0.0.1:6633",
"controller-uuid": "57b4a453-5ee5-40ea-953a-4132319ad1eb",
"is-connected": true
},
{
"target": "tcp:10.14.0.160:6633",
"controller-uuid": "bc0af587-fc76-44d9-ab24-fe926b1099e6",
"is-connected": true
}
],
"ovsdb:controller-entry": [ { "target": "tcp:127.0.0.1:6633", "controller-uuid": "57b4a453-5ee5-40ea-953a-4132319ad1eb", "is-connected": true }, { "target": "tcp:10.14.0.160:6633", "controller-uuid": "bc0af587-fc76-44d9-ab24-fe926b1099e6", "is-connected": true } ],
"ovsdb:controller-entry": [
    {
        "target": "tcp:127.0.0.1:6633",
        "controller-uuid": "57b4a453-5ee5-40ea-953a-4132319ad1eb",
        "is-connected": true
    },
    {
        "target": "tcp:10.14.0.160:6633",
        "controller-uuid": "bc0af587-fc76-44d9-ab24-fe926b1099e6",
        "is-connected": true
    }
],

8. Retrieve network topology:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=flow%3A1 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool
curl -v --request GET \ --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=flow%3A1 \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Accept: application/json' \ | python -m json.tool
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=flow%3A1 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool

Here’s an example of the output, where you can find a node-id of the Open vSwitch instance. This can be used in subsequent requests.

9. Retrieve data of all nodes (reply includes also OpenFlow flow tables):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool
curl -v --request GET \ --url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Accept: application/json' \ | python -m json.tool
curl -v --request GET \
  --url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes \
  --header 'Authorization: Basic YWRtaW46YWRtaW4=' \
  --header 'Accept: application/json' \
  | python -m json.tool

Here’s is the output from our example.

10. Retrieve data of a specific node (reply includes also OpenFlow flow tables):

This request uses node-id in the URL. The node-id can be found in reply to requests 8. and 9.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes/node=openflow%3A143423481343818 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool
curl -v --request GET \ --url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes/node=openflow%3A143423481343818 \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Accept: application/json' \ | python -m json.tool
curl -v --request GET \
  --url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes/node=openflow%3A143423481343818 \
  --header 'Authorization: Basic YWRtaW46YWRtaW4=' \
  --header 'Accept: application/json' \
  | python -m json.tool

11. Retrieve specific OpenFlow table of specific node:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes/node=openflow%3A143423481343818/table=0 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool
curl -v --request GET \ --url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes/node=openflow%3A143423481343818/table=0 \ --header 'Authorization: Basic YWRtaW46YWRtaW4=' \ --header 'Accept: application/json' \ | python -m json.tool
curl -v --request GET \
--url http://127.0.0.1:8888/restconf/data/opendaylight-inventory:nodes/node=openflow%3A143423481343818/table=0 \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/json' \
| python -m json.tool

12. Delete OpenFlow controller connection from Open vSwitch configuration of bridge br-int:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request DELETE \
--url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int/controller-entry=tcp%3A10.14.0.160%3A6633 \
--header 'Authorization: Basic YWRtaW46YWRtaW4='
curl -v --request DELETE \ --url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int/controller-entry=tcp%3A10.14.0.160%3A6633 \ --header 'Authorization: Basic YWRtaW46YWRtaW4='
curl -v --request DELETE \
--url http://localhost:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1%2Fbridge%2Fbr-int/controller-entry=tcp%3A10.14.0.160%3A6633 \
--header 'Authorization: Basic YWRtaW46YWRtaW4='

13. Close OVSDB connection to the Open vSwitch instance:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
curl -v --request DELETE \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \
--header 'Authorization: Basic YWRtaW46YWRtaW4='
curl -v --request DELETE \ --url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \ --header 'Authorization: Basic YWRtaW46YWRtaW4='
curl -v --request DELETE \
--url http://127.0.0.1:8888/restconf/data/network-topology:network-topology/topology=ovsdb%3A1/node=ovsdb%3A%2F%2FHOST1 \
--header 'Authorization: Basic YWRtaW46YWRtaW4='

OpenFlow manager (OFM)

For this setup, you can also use the OFM application, which provides GUI for management of OpenFlow switches. You can connect OFM to the controller and retrieve OpenFlow tables of a specific switch – plus the flows will be graphically displayed. You can also modify existing flows, or add new using OFM. See our blog about OpenFlow integration.

Conclusion

In this blog, we have described the use of an SDN controller with OVSDB and OpenFlow support. It can be used to manage Open vSwitch virtual switches. We have used Open vSwitch running in an OpenStack environment and we described the sequence of requests needed to connect SDN controller to OVSDB and OpenFlow interfaces of Open vSwitch.

This approach can be used to manage Open vSwitch instances, running in OpenStack Network nodes and Compute nodes without breaking the connection between Neutron service and the Open vSwitch instances. But the SDN controller example and described requests can be used with any virtual or physical network device supporting OpenFlow or OVSDB or both protocols.

The usage of RESTCONF SB plugin in the SDN controller means, that any application can implement RESTCONF (HTTP/REST/API) client and communicate with the controller, as we have demonstrated by Postman application and OpenFlow manager (OFM) in the previous blog.