OpenDayLight (ODL) SDN Crash Course - LAB Guide

KNET Solutions (Online Training Centre),

http://knetsolutions.in

knetsolutions2@gmail.com

Phone/WhatsApp: +919445042007

Online Training, Consulting & Academic SDN Project assistance.


ODL Book Cover

1. Introduction

This Book is (RYU SDN CRASH COURSE Course book), prepared by KNET Solutions. This Book is used as Course material for UDEMY SDN Crash Course.

This Book is (OPENDAYLIGHT SDN CRASH COURSE Course book), prepared by KNET Solutions. This Book is used as Course material for UDEMY OPENDAYLIGHT SDN Crash Course.

The Course is available in UDEMY. The Course link is UDEMY OPENDAYLIGHT COURSE

This Course covers SDN Basics, OPENDAYLIGHT Basics, RESTCONF, OpenFlow Theory, Mininet Basics, ODL OPENFLOW PLUGIN APIs, Demos, Openvswitch, OVSDB, OVS Commands, ODL OVSDB Plugin, BGP Test bed, ODL BGP Plugin and Demo, etc.

Some book contents (IMAGE/Text) are copied from Freely available resources from internet / RFCs/ Opensource materials. Thanks to the original authors.

This Book is free to use.


2. Installation

Preferred System requirements:

Configuration: 2 Core + 8GB RAM (preferably)

OS:

prefer Linux Ubuntu Version.

Ubuntu versions : Ubuntu 18.04
Java - 8+ version

JAVA Installation

sudo apt-get install default-jdk

ODL Installation

OpenDayLight Version : SODIUM - SR1

wget https://nexus.opendaylight.org/content/repositories/public/org/opendaylight/integration/opendaylight/0.11.1/opendaylight-0.11.1.tar.gz

tar xvzf opendaylight-0.11.1.tar.gz

cd opendaylight-0.11.1/

./bin/karaf

you will see the karaf shell


3. Console Commands

Feature command

Manage the features/plugins

feature:list

Lists all existing features available from the defined repositories.

feature:list -i

List only installed features

feature:list -i | grep name

List the installed features and grep with specific name.

Example

feature:list -i | grep restconf

feature:install name

Installs a feature with the specified name and version.

Example

feature:install odl-restconf

feature:uninstall name

Uninstalls a feature with the specified name and version

feature:uninstall odl-restconf
feature:info odl-restconf

Log command

log:display

Displays log entries.

log:get

Shows the currently set log level

log:set

Sets the log level.

The log level to set (TRACE, DEBUG, INFO, WARN, ERROR) or DEFAULT to unset

Log file is located in data/log/karaf.log

Exit Command

shutdown, logout


4. RESTConf

Standard mechanisms to allow Web applications to access the configuration data, state data, data-model-specific Remote Procedure Call (RPC) operations, and event notifications within a networking device, in a modular and extensible manner.

RESTCONF uses HTTP methods to provide CRUD operations on a conceptual datastore containing YANG-defined data, which is compatible with a server that implements NETCONF datastores.

Methods

The RESTCONF protocol uses HTTP methods to identify the CRUD operations requested for a particular resource.

Following are the widely used methods

GET:

The GET method is sent by the client to retrieve data and metadata for a resource. It is supported for all resource types, except operation resources.

If the user is not authorized to read the target resource, an error response containing a "401 Unauthorized" status-line SHOULD be returned.

PUT:

The PUT method is sent by the client to create or replace the target data resource. A request message-body MUST be present, representing the new data resource.

The "insert" and "point" query parameters MUST be supported by the PUT method for data resources.

if the PUT request creates a new resource, a "201 Created" status-line is returned. If an existing resource is modified, a "204 No Content" status-line is returned.

DELETE:

The DELETE method is used to delete the target resource. If the DELETE request succeeds, a "204 No Content" status-line is returned. If the user is not authorized to delete the target resource, then an error response containing a "403 Forbidden" status-line SHOULD be returned.

POST

The POST method is sent by the client to create a data resource or invoke an operation resource.


REST Clients

  1. POSTMAN

GUI Based.

To install, follow this link

  1. curl Quick to use. Command line interface. Little hard to understand the flags/options
sudo apt-get install curl

Plugin Installation

Install ODL as per previous session, and start the ODL KARAF shell

./bin/karaf

Install the restconf and Openflow plugins

feature:install odl-restconf
feature:install odl-openflowplugin-flow-services-rest

Default ODL username/password : admin/admin

ODL IP&Port: http://192.168.122.219:8181

GET http://192.168.122.219:8181restconf/operational/network-topology:network-topology/

DataModel: XML


Accessing with CURL

GET Method:

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://192.168.122.227:8181/restconf/operational/network-topology:network-topology/

Accessing with POSTMAN

  1. URL
http://192.168.122.227:8181/restconf/operational/network-topology:network-topology/
  1. Base Headers:

In the Authorization TAB, Select,

Type: Basic Auth
Fill username and password as mentioned above

and click Preview Request,

  1. In the Header TAB,

you could see "Authorization" Header and value "Basic xxxxxxxxxxxx" could have been populated automatically.

Add "Content-Type" and "Accept" header with Value is "application/xml" for both.

  1. Method: GET and Query

5. OpenFlow Plugin

Mininet

Installation

Open the terminal, and execute the below commands,

sudo apt-get update
sudo apt-get install -y openvswitch-switch
sudo apt-get install -y mininet
sudo apt-get install libxml2-utils

verify the installation

sudo mn --version
sudo ovs-vsctl show

To clean up the existing ovs bridges and namespaces

Note: sometime we mistakenly closed the mininet shell, or mininet crashed. But the topology components will continue to exists. To clean such stuff, cleanup command is used.

mn -c

Our First Topology (Single)

Topology with Single Switch and 4 Nodes.

Alt text

sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --switch=ovsk,protocols=OpenFlow13 --topo=single,4
optionsDescription
--controllertype of controller local/remote and remote controller ip.
--macmac address starts with 00:00:00:00:00:01
-iIP Subnets for the Topology
--switchSwitch type (ovsk - openvswitch kernel module), and openflow version.
--topotopology type(linear,minimal,reversed,single,torus,tree) and params.

Basic Openvswitch commands

sudo ovs-vsctl show
sudo ovs-ofctl -O OpenFlow13 dump-flows s1
sudo ovs-ofctl -O OpenFlow13 dump-ports s1
sudo ovs-ofctl -O OpenFlow13 show s1

Add flow for normal(traditional switch behavior)

sudo ovs-ofctl -O OpenFlow13 add-flow s1 actions=NORMAL

Once you are done, make sure "exit" the mininet shell,

exit

Example:

mininet> exit
*** Stopping 1 controllers
c0
*** Stopping 4 links
....
*** Stopping 1 switches
s1
*** Stopping 4 hosts
h1 h2 h3 h4
*** Done
completed in 2.604 seconds
suresh@suresh-vm:~$

Mininet Basic Shell Commands

Informative commands

help
dump
net
links

Action commands

pingall

Execute the commands in HOST/Node:

Option1:

we can login to each host using 'xterm' command

xterm h1

mininet>xterm h1

It will open a xterm terminal for the host. Now we can execute the command inside that terminal

Option2:

we can directly execute from the mininet shell.

mininet><hostname> command

Example:

mininet>h1 ifconfig
mininet>h1 ping h2
mininet>h1 ip route

we can use either method to run the Traffic tests or executing the commands.

Linear Topology

linear topology (where each switch has one host, and all switches connect in a line)

Alt text

sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --switch=ovsk,protocols=OpenFlow13 --topo=linear,4

install normal flows

sudo ovs-ofctl -O OpenFlow13 add-flow s1 actions=NORMAL
sudo ovs-ofctl -O OpenFlow13 add-flow s2 actions=NORMAL
sudo ovs-ofctl -O OpenFlow13 add-flow s3 actions=NORMAL
sudo ovs-ofctl -O OpenFlow13 add-flow s4 actions=NORMAL

Tree Topology

Alt text

sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --topo=tree,depth=2,fanout=3

fanout : each switch is connected to these many childs depth : depth of the tree


Running TCP/UDP Traffic Tests

a. Setup the Topology with xterms options (open terminal for each Node)

Alt text

sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --switch=ovsk,protocols=OpenFlow13 --topo=linear,4 -x

install normal flows

sudo ovs-ofctl -O OpenFlow13 add-flow s1 actions=NORMAL
sudo ovs-ofctl -O OpenFlow13 add-flow s2 actions=NORMAL
sudo ovs-ofctl -O OpenFlow13 add-flow s3 actions=NORMAL
sudo ovs-ofctl -O OpenFlow13 add-flow s4 actions=NORMAL

TCP Traffic Test between h1 to h4

Run IPERF TCP Server in h4

iperf -s

-s means server mode

RUN IPERF TCP Client in h1

iperf -c 10.1.1.4 -i 10 -t 30
iperf -c 10.1.1.4 -i 10 -b 10m -t 30
iperf -c 10.1.1.4 -i 10 -P 10 -t 30

-c means client mode.

-i means reporting interval

-t means test duration in seconds

-b means bandwidth 10m means 10Mbps

-P means parallel connections

UDP Traffic Test between h1 to h4

Run IPERF UDP Server in h4

iperf -u -s

-u means udp

RUN IPERF UDP Client in h1

iperf -u -c 10.1.1.4 -b 10m -i 10 -t 30
iperf -u -c 10.1.1.4 -b 10m -i 10 -P 10 -t 30

-b means bandwidth 10m means 10Mbps


Openflow Plugin Installation

OpenDayLight Version : SODIUM - SR1

wget https://nexus.opendaylight.org/content/repositories/public/org/opendaylight/integration/opendaylight/0.11.1/opendaylight-0.11.1.tar.gz

tar xvzf opendaylight-0.11.1.tar.gz

cd opendaylight-0.11.1/

./bin/karaf

you will see the karaf shell

Install the Openflow Plugin:

feature:install odl-restconf feature:install odl-openflowplugin-flow-services-rest

optional plugins:

feature:install odl-openflowplugin-app-lldp-speaker feature:install odl-openflowplugin-app-table-miss-enforcer

Components

The OpenFlow Plugin provides the following RESTCONF APIs:

  • OpenFlow Topology
  • OpenFlow Statistics
  • OpenFlow Programming

#### OpenFlow Topology

Retriving the topology details

http://localhost:8181/restconf/operational/network-topology:network-topology/

API : /restconf/operational/network-topology:network-topology/topology/flow:1

curl --user "admin":"admin" -X GET http://127.0.0.1:8181/restconf/operational/network-topology:network-topology/topology/flow:1 | jq .

It returns switch,port details

Here openflow:1 is switch dpid.

The output can be compared to

sudo ovs-ofctl -O OpenFlow13 show s1

OpenFlow Statistics

Inventory data:

http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/ http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:4

curl --user "admin":"admin" -X GET http://172.17.0.2:8181/restconf/operational/opendaylight-inventory:nodes/ | jq .

Collect the Switch Hardware details such as make, version Port description details - mac-address of the port, port speed, state, admin status, Port statistics - tx, rx bytes trasfered group statistcis flow statistics, etc.

Port stats

http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:4/node-connector/openflow:4:1

Flow stats

http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:4/table/0

Group stats

/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/group/2

#### OpenFlow Programming

The controller provides interfaces that can be used to program the connected OpenFlow devices. These interfaces interact with the OpenFlow southbound plugin that uses OpenFlow modification messages to program flows, groups and meters in the switch.

The controller provides the following RESTCONF interfaces:

Configuration Datastore:

RPC Operations:

configuration datastore:

PUT

http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1

Demonstration

http://localhost:8181/restconf/operational/network-topology:network-topology/topology/flow:1


HUB Exercise

sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --switch=ovsk,protocols=OpenFlow13 --topo=single,4

To add a flood flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1 -d @hub.xml
sudo ovs-ofctl -O OpenFlow13 dump-flows s1

To remove this flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1


L2 Switch Exercise

1. Create a Single topology

sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --switch=ovsk,protocols=OpenFlow13 --topo=single,4

Alt text

2. Make sure ODL is running and openflow plugin is installed

In the karaf shell,

feature:list -i |grep openflow

And in the terminal, verify the OPENFLOW port is listening mode,

sudo netstat -i | grep 6653

3. Check the switches are connected to the ODL Controller

sudo ovs-vsctl show

4. Add a ARP flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1 -d @arp.xml

5. Add a h1(00:00:00:00:00:01) to h2(00:00:00:00:00:02) flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/2 -d @l2match1.xml

6. Add a h2(00:00:00:00:00:02) to h1(00:00:00:00:00:01) flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/3 -d @l2match2.xml

7. Verify the flows in OVS

sudo ovs-ofctl -O OpenFlow13 dump-flows s1

8. Verify the flows in ODL Datastore

Specific flow:

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1 | xmllint --format -
curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/2 | xmllint --format -
curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/3 | xmllint --format -

9. Try ping from mininet shell

h1 ping h2

10. Delete the flows from ODL

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1
curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/2
curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/3

11. exit from mininet

exit

L3 Switch Exercise

1. Create a Single topology

sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --switch=ovsk,protocols=OpenFlow13 --topo=single,4

Alt text

2. Make sure ODL is running and openflow plugin is installed

In the karaf shell,

feature:list -i |grep openflow

And in the terminal, verify the OPENFLOW port is listening mode,

sudo netstat -i | grep 6653

3. Check the switches are connected to the ODL Controller

sudo ovs-vsctl show

4. Add a ARP flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1 -d @arp.xml

5. Add a h1(10.1.1.1) to h2(10.1.1.2) flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/2 -d @l3match1.xml

6. Add a h2(10.1.1.2) to h1(10.1.1.1) flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/3 -d @l3match2.xml

7. Verify the flows in OVS

sudo ovs-ofctl -O OpenFlow13 dump-flows s1

8. Try ping from mininet shell

h1 ping h2

9. Delete the flows from ODL

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1
curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/2
curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/3

10. exit from mininet

exit

L4 Match switch

Allow only TCP Traffic between h1 and h2

Create a Single topology

sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --switch=ovsk,protocols=OpenFlow13 --topo=single,4

Alt text

Make sure ODL is running and openflow plugin is installed

In the karaf shell,

feature:list -i |grep openflow

And in the terminal, verify the OPENFLOW port is listening mode,

sudo netstat -i | grep 6653

Check the switches are connected to the ODL Controller

sudo ovs-vsctl show

Add a ARP flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1 -d @arp.xml

Add a h1(10.1.1.1) to h2(10.1.1.2) TCP flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/2 -d @l4match1.xml

7. Add a h2(10.1.1.2) to h1(10.1.1.1) TCP flow

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X PUT http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/3 -d @l4match2.xml

8. Verify the flows in OVS

sudo ovs-ofctl -O OpenFlow13 dump-flows s1

9. Try TCP traffic in mininet shell

h1 iperf -s &
h2 iperf -c h1

10. Delete the flows from ODL

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1
curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/2
curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/3

11. exit from mininet

exit

6. OVSDB

Openvswitch

1. Openvswitch installation

sudo apt-get install openvswitch-switch

2. verify openvswitch is installed

in the terminal,

sudo ovs-vsctl show

3. verify openvswitch process

in the terminal,

sudo ps -ef | grep ovs
sudo lsmod | grep openvswitch

4. verify OVSDB Port is in listening mode

sudo netstat -a | grep 6640

5. Sample Management commands

sudo ovs-vsctl add-br s1
sudo ovs-vsctl show
sudo ovs-vsctl add-port s1 veth0
sudo ovs-vsctl show
sudo ovs-vsctl add-port s1 veth1
sudo ovs-vsctl show
sudo ovs-vsctl del-port s1 veth0
sudo ovs-vsctl set-controller s1 tcp:192.168.56.101:6633
sudo ovs-vsctl set-controller s2 tcp:192.168.56.101:6633
sudo ovs-vsctl del-br s1

Note:

sudo ip link add veth0 type veth peer name veth1
sudo ifconfig veth0 up
sudo ifconfig veth1 up
sudo ip link delete veth0

6. Example Usecase

Two hosts(created using netns) are ready. we want to create a switch "s1" and connect these two hosts. Add "NORMAL" flow, and Verify ping traffic between the hosts.

Topology diagram without switch:

Now, we create two hosts using netns as below.

Alt text

#create host named red
sudo ip netns add red
sudo ip link add red-veth0 type veth peer name red-veth1
sudo ip link set red-veth1 netns red
sudo ip netns exec red ip addr add 10.10.20.1/24 dev red-veth1
sudo ip netns exec red ip link set red-veth1 up
#create host named blue
sudo ip netns add blue
sudo ip link add blue-veth0 type veth peer name blue-veth1
sudo ip link set blue-veth1 netns blue
sudo ip netns exec blue ip addr add 10.10.20.2/24 dev blue-veth1
sudo ip netns exec blue ip link set blue-veth1 up
sudo ifconfig red-veth0 up
sudo ifconfig blue-veth0 up

Create switch and associate the ports

Now, we create the switch and associate as below using ovs-vsctl (using OVSDB interface)

Alt text

sudo ovs-vsctl add-br s1
sudo ovs-vsctl add-port s1 red-veth0
sudo ovs-vsctl add-port s1 blue-veth0

Adding a Normal flow

sudo ovs-ofctl -O OpenFlow13 add-flow s1 actions=NORMAL

Testing

sudo ip netns exec blue ping 10.10.20.1

Destory the setup

#delete
sudo ip netns delete red
sudo ip netns delete blue
sudo ovs-vsctl del-br s1

OVSDB Plugin

OVSDB(OVS Management Interface) implementation in ODL. This plugin can communicate with Openvswitch and perform the configuration and management operations.

ODL exposing the Northbound REST APIs are for OVSDB.

Example:

http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/

Using these APIs, user/app can perform the OVSDB operations to the manage the Openvswitch , such as,

  1. Create a bridge,
  2. Create a Qos
  3. Delete a bridge
  4. Add a port to the bridge etc.

Installation

OpenDayLight Version : SODIUM - SR1

JAVA Installation

sudo apt-get install default-jdk

sudo apt-get install openvswitch-switch jq

ODL Installation

wget https://nexus.opendaylight.org/content/repositories/public/org/opendaylight/integration/opendaylight/0.11.1/opendaylight-0.11.1.tar.gz

tar xvzf opendaylight-0.11.1.tar.gz

cd opendaylight-0.11.1/

./bin/karaf

you will see the karaf shell

Install the Openflow Plugin:

feature:install odl-mdsal-apidocs

feature:install odl-restconf

feature:install odl-ovsdb-southbound-impl-ui

Once installed, Check the OVSDB Topology will get created. This can be verified in API DOCS or RESTAPI "network-topology" endpoint,

GET http://localhost:8181/restconf/operational/network-topology:network-topology/

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost:8181/restconf/operational/network-topology:network-topology/ | jq .

Response

{
"network-topology": {
"topology": [
{
"topology-id": "ovsdb:1"
}
]
}
}

Workflow in Detail

  • create a OVSDB Host
  • Perform operations(add switch, delete switch, etc) on that OVSDB HOST
  • Delete OVSDB Host(if you want)

Before connect to ODL, check ovs tables:

sudo ovs-vsctl list open_vswitch
  1. Configure the ODL to talk to the OVSDB host

ACTIVE CONNECTION Mode:

API: http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1

METHOD : PUT

DATA:

{
"network-topology:node": [
{
"node-id": "ovsdb:HOST1",
"connection-info": {
"ovsdb:remote-port": "6640",
"ovsdb:remote-ip": "127.0.0.1"
}
}
]
}

Examples:

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1 -d @ovsdb_host.json

Verify the OVSDB Port Connections in HOST1 VM

suresh@sdn:~$ sudo netstat -a | grep 6640
tcp 0 0 0.0.0.0:6640 0.0.0.0:* LISTEN
tcp 0 0 localhost:6640 localhost:59296 ESTABLISHED
tcp6 0 0 localhost:59296 localhost:6640 ESTABLISHED
suresh@sdn:~$
  1. GET OVSDB host details (config and operational)

GET

http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1

GET

http://localhost:8181/restconf/operational/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1

Examples:

suresh@sdn:~$ curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost:8181/restconf/operational/network-topology:network-topology/ | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1417 100 1417 0 0 64409 0 --:--:-- --:--:-- --:--:-- 64409
{
"network-topology": {
"topology": [
{
"topology-id": "ovsdb:1",
"node": [
{
"node-id": "ovsdb:HOST1",
"ovsdb:datapath-type-entry": [
{
"datapath-type": "ovsdb:datapath-type-netdev"
},
{
"datapath-type": "ovsdb:datapath-type-system"
}
],
"ovsdb:ovs-version": "2.9.5",
"ovsdb:connection-info": {
"local-ip": "127.0.0.1",
"remote-port": 6640,
"remote-ip": "127.0.0.1",
"local-port": 59296
},
"ovsdb:openvswitch-external-ids": [
{
"external-id-key": "hostname",
"external-id-value": "sdn"
},
{
"external-id-key": "opendaylight-iid",
"external-id-value": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']"
},
{
"external-id-key": "system-id",
"external-id-value": "f1c3af1d-1bff-4d71-a00b-42cbb4134391"
},
{
"external-id-key": "rundir",
"external-id-value": "/var/run/openvswitch"
}
],
"ovsdb:db-version": "7.15.1",
"ovsdb:interface-type-entry": [
{
"interface-type": "ovsdb:interface-type-lisp"
},
{
"interface-type": "ovsdb:interface-type-geneve"
},
{
"interface-type": "ovsdb:interface-type-gre"
},
{
"interface-type": "ovsdb:interface-type-system"
},
{
"interface-type": "ovsdb:interface-type-vxlan"
},
{
"interface-type": "ovsdb:interface-type-internal"
},
{
"interface-type": "ovsdb:interface-type-stt"
},
{
"interface-type": "ovsdb:interface-type-tap"
},
{
"interface-type": "ovsdb:interface-type-patch"
}
],
"ovsdb:manager-entry": [
{
"target": "ptcp:6640",
"connected": true,
"number_of_connections": 1
}
]
}
]
}
]
}
}
suresh@sdn:~$
suresh@sdn:~$ curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost:8181/restconf/config/network-topology:network-topology/ | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 165 100 165 0 0 8250 0 --:--:-- --:--:-- --:--:-- 8250
{
"network-topology": {
"topology": [
{
"topology-id": "ovsdb:1",
"node": [
{
"node-id": "ovsdb:HOST1",
"ovsdb:connection-info": {
"remote-ip": "127.0.0.1",
"remote-port": 6640
}
}
]
}
]
}
}
suresh@sdn:~$

Exercise add a another OVS HOST (HOST2)/and check

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST2 -d @ovsdb_host2.json

and check it.

Operations - Add a new Bridge

This example shows how to add a bridge("s1") to the OVSDB node ovsdb:HOST1.

PUT

http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1

BODY

{
"network-topology:node": [
{
"node-id": "ovsdb:HOST1/bridge/s1",
"ovsdb:bridge-name": "s1",
"ovsdb:protocol-entry": [
{
"protocol": "ovsdb:ovsdb-bridge-protocol-openflow-13"
}
],
"ovsdb:managed-by": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']"
}
]
}

Example:

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1 -d @s1.json

verify with cli

sudo ovs-vsctl show

Notice that the ovsdb:managed-by attribute is specified in the command. This indicates the association of the new bridge node with its OVSDB node.

Verify it as below,

suresh@sdn:~$ curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost:8181/restconf/operational/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1 | jq .
{
"node": [
{
"node-id": "ovsdb:HOST1/bridge/s1",
"ovsdb:bridge-name": "s1",
"ovsdb:bridge-external-ids": [
{
"bridge-external-id-key": "opendaylight-iid",
"bridge-external-id-value": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1/bridge/s1']"
}
],
"ovsdb:stp_enable": false,
"ovsdb:datapath-type": "ovsdb:datapath-type-system",
"ovsdb:datapath-id": "00:00:46:a8:3a:e5:95:45",
"ovsdb:bridge-uuid": "e53aa844-454c-4595-9787-6a5f102269f4",
"ovsdb:protocol-entry": [
{
"protocol": "ovsdb:ovsdb-bridge-protocol-openflow-13"
}
],
"ovsdb:managed-by": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']",
"termination-point": [
{
"tp-id": "s1",
"ovsdb:ingress-policing-rate": 0,
"ovsdb:interface-type": "ovsdb:interface-type-internal",
"ovsdb:interface-uuid": "215bbf31-2631-43ae-9feb-e482ade04075",
"ovsdb:ifindex": 4,
"ovsdb:name": "s1",
"ovsdb:mac-in-use": "46:a8:3a:e5:95:45",
"ovsdb:ingress-policing-burst": 0,
"ovsdb:port-uuid": "d72af941-dab8-4de0-b7dc-47cd5a420ca3",
"ovsdb:ofport": 65534
}
]
}
]
}

verify with cli

sudo ovs-vsctl show

Operations - Update the SDN Controller information in the Bridge

PUT

http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1

BODY

{
"network-topology:node": [
{
"node-id": "ovsdb:HOST1/bridge/s1",
"ovsdb:bridge-name": "s1",
"ovsdb:controller-entry": [
{
"target": "tcp:127.0.0.1:6653"
}
],
"ovsdb:managed-by": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id='ovsdb:HOST1']"
}
]
}

Example:

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1 -d @s1_controller.json

verify with cli

sudo ovs-vsctl show

Operations - Add a port to the switch

API

PUT

http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1/termination-point/port1

{
"network-topology:termination-point": [
{
"ovsdb:name": "port1",
"tp-id": "port1"
}
]
}

Example:

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1/termination-point/port1 -d @port1.json

Verify with cli :

sudo ovs-vsctl show

ADD A PATCH PORT

Prerequisties:

Create veth pair

sudo ip link add veth0 type veth peer name veth1
sudo ifconfig veth0 up
sudo ifconfig veth1 up
{
"network-topology:termination-point": [
{
"ovsdb:name": "patch1",
"tp-id": "patch1",
"ovsdb:interface-type": "ovsdb:interface-type-patch",
"ovsdb:options": [
{
"ovsdb:option": "peer",
"ovsdb:value" : "veth0"
}
]
}
]
}

Example :

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1/termination-point/patch1 -d @patch1.json

ADD A VXLAN PORT

{
"network-topology:termination-point": [
{
"ovsdb:options": [
{
"ovsdb:option": "remote_ip",
"ovsdb:value" : "10.10.14.11"
}
],
"ovsdb:name": "vxlanport1",
"ovsdb:interface-type": "ovsdb:interface-type-vxlan",
"tp-id": "vxlanport1",
"vlan-tag": "1",
"trunks": [
{
"trunk": "5"
}
],
"vlan-mode":"access"
}
]
}

Example :

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1/termination-point/vxlanport1 -d @vxlanport1.json

6. Operations - Delete a Bridge

DELETE

http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2s1

Example

suresh@sdn:~$ curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X DELETE http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1%2Fbridge%2Fs1

verify with cli

sudo ovs-vsctl show

7. DELETE the OVSDB HOST entry

DELETE http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST1

curl --user "admin":"admin" -H "Accept: application/json" -H "Content-Type: application/json" -X DELETE http://localhost:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:HOST2

After removed, check the status again.


7. ODL BGP

Introduction

BGP evolved long time before SDN was born, it plays a significant role in many SDN use-cases. Also, continuous evolution of the protocol brings extensions that are very well suited for SDN. Nowadays, BGP can carry various types of routing information - L3VPN, L2VPN, IP multicast, linkstate, etc. Here is a brief list of software-based/legacy-network technologies where BGP-based SDN solution get into an action:

  • SDN WAN - WAN orchestration and optimization
  • SDN router - Turns switch into an Internet router
  • Virtual Route Reflector - High-performance server-based BGP Route Reflector
  • SDX - A Software Defined Internet Exchange controller
  • Large-Scale Data Centers - BGP Data Center Routing, MPLS/SR in DCs, DC interconnection
  • DDoS mitigation - Traffic Filtering distribution with BGP

BGP Testbed (ContainerNet)

1. BGP Testbed(containernet) Installation

Containernet installation

Requires Ubuntu 18.04 LTS and Python3.

sudo apt-get install ansible git aptitude
git clone https://github.com/containernet/containernet.git
cd containernet/ansible
sudo ansible-playbook -i "localhost," -c local install.yml
cd ..

Quick verification

sudo mn --controller=remote,ip=127.0.0.1 --topo=single,2

you should see the "containernet>" prompt

To see the docker stuff

sudo docker images
sudo docker ps -a

2. exercise1 - Traditional EBGP

How to run

i) Run the topology

sudo python3 topo1.py

ii) check the bgp protocol status of Router R1 and R2 in mininet shell

r1 birdc show protocols
r1 birdc show route
r1 ip route

R2

r2 birdc show protocols
r2 birdc show route
r2 ip route

BGP Peers are established between R1 and R2. Routes are synchronized.

Note: if you know docker commands, you can login/execute commands router docker .

Important Docker commands

sudo docker ps -a
sudo docker exec -it mn.r1 sh

birdc important commands

birdc show status
birdc show route
birdc show protocols
birdc show protocols all

Logs can be checked in

tailf /var/log/bird.log

iii) verify the ping traffic from h1 to h2

h1 ping h2

try traceroute also

h1 traceroute h2

ODL BGP Plugin

Installation

OpenDayLight Version : SODIUM - SR1

JAVA Installation

sudo apt-get install default-jdk

sudo apt-get install libxml2-utils

ODL Installation

wget https://nexus.opendaylight.org/content/repositories/public/org/opendaylight/integration/opendaylight/0.11.1/opendaylight-0.11.1.tar.gz

tar xvzf opendaylight-0.11.1.tar.gz

cd opendaylight-0.11.1/

./bin/karaf

you will see the karaf shell

Install the Openflow Plugin:

feature:install odl-mdsal-apidocs

feature:install odl-restconf

feature:install odl-bgpcep-bgp

Verification

In the apidocs, http://localhost:8181/apidoc/explorer/index.html you would see bgp yang models/apis are displaying

REST API Verifications

Create a BGP Instace

curl --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X POST http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/openconfig-network-instance:protocols/ -d @bgp_router.xml
curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/openconfig-network-instance:protocols/ | xmllint --format -

Verify the BGP Instace

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://localhost:8181/restconf/operational/bgp-rib:bgp-rib/ | xmllint --format -

Delete the BGP Instance

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/openconfig-network-instance:protocols/ -d @bgp_router.xml

Demo- ODL as EBGP router

i) Run the topology

sudo python3 topo1.py

ii) check the bgp protocol status on Router R1 and R2

R1

containernet>r1 birdc show protocols
containernet>r1 ip route

R2

containernet>r2 birdc show protocols
containernet>r2 ip route

BGP Peers are established between R1 and R2. Routes are synchronized.

iii) Create the ODL BGP Instance

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X POST http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/openconfig-network-instance:protocols/ -d @bgp_router.xml

iv) verification

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://localhost:8181/restconf/operational/bgp-rib:bgp-rib/ | xmllint --format -

v) create bgp neighbor

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X POST http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/openconfig-network-instance:protocols/protocol/openconfig-policy-types:BGP/bgp-odl-router/bgp/neighbors/ -d @bgp_neighbor.xml

vi) verify bgp neighbor/route details

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://localhost:8181/restconf/operational/bgp-rib:bgp-rib/rib/bgp-odl-router/ | xmllint --format -

vii) verify the bgp ports and neighbor establishment

containernet>r1 birdc show protocols
containernet>r1 ip route
$ netstat -a | grep bgp
tcp 0 0 172.17.0.1:50876 172.17.0.2:bgp ESTABLISHED

vii) Destroy the test

Delete the BGP instance in ODL

curl -v --user "admin":"admin" -H "Accept: application/xml" -H "Content-Type: application/xml" -X DELETE http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/openconfig-network-instance:protocols/ -d @bgp_router.xml

exit from containernet.


8. References