GithubHelp home page GithubHelp logo

sdnlab's Introduction

Getting your own Software Defined Networking infrastructure up and running

In general, in order to experiment with Software Defined Networking (SDN) you need: (i) an SDN controller; (ii) a data-plane (hosts, forwarding devices) with SDN-enabled forwarding devices (e.g., switches); and, finally some SDN applications managing the traffic. As an SDN controller we will be using an Onos controller; the data-plane will be simulated with a Mininet (in fact a Containernet, a Mininet fork that uses Docker images for the hosts); and, the SDN applications are those included within the Onos controller, and a web (REST) interface for you to interact with the whole SDN architecture.

Getting the docker images

There are 6 docker images you need for this laboratory. Those are:

  1. The official Onos docker image, to get it, execute:

                docker pull onosproject/onos
            
  2. The official Containernet docker image, to get it, execute:

                docker pull containernet/containernet
            

    For the remainng images, it is easier if you copy the contents of the docker-images found in this repository. You can download via http or git. Change to that directory (cd docker-images).

  3. A modified wordpress image (referred as h2), to get it, execute:

                 docker build -t mywordpress ./mywordpress
            

    For more information on builing docker images see the containers lab.

  4. A modified mysql image (referred as h1) , to get it, execute:

                docker build -t mymysql ./mymysql
            
  5. A modified lab-api image (referred as h3, from the previous lab), to get it, execute:

                docker build -t lab-api ./backend
            
  6. A modified lab-web image (referred as h4, from the previous lab), to get it, execute:

                docker build -t lab-web ./frontend
            

For your knowledge, containernet needs docker images with certain requirements.

Executing the emulated infrastructure

Once the images are pulled, and build you can launch your emulated data-plane and onos controller. To do so, the best way is to create a docker-compose file. Create a file called docker-compose.yml with the following contents (or download it from the repository)

version: '3.3'

services:
  onos:
    image: onosproject/onos:latest
    restart: always
    ports:
      - "8181:8181"
      - "6633:6633"
      - "6653:6653"

  containernet: 
    depends_on: 
      - onos
    image: containernet/containernet:latest
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"      
    privileged: true
    pid: host
    tty: true

After that, execute the docker composition with:

    docker-compose up

You may choose to execute it in detached mode (by adding -d flag to the command) or better, open a new terminal.

After a while both of your images will be running, log in into the containernet image by executing:

        docker exec -it SDNLab_containernet_1 bash

Attention: the name of the image assumes your docker-compose file is executed in a directory called SDNLab. Alternatively, you can get the container ID and replace that name.

Inside the container, to run the intended topology, execute the following commands:

        mn -c;
        curl https://raw.githubusercontent.com/jorgelopezcoronado/SDNLab/master/custom_ctnnet_topology.py > cmnt.py;
        python cmnt.py

Your topology should be up and running, this is the intended topology:

image

Inside the containernet console you can try to check the connectivity between hosts, for instance from h1 to h2, execute:

        h1 ping -c 5 h2

Normally, as there are no data-paths configured in your SDN controller (and therefore switches) you shouldn't be successful. Likewise, if you point to your wordpress installation at http://localhost:8080 you should see a database connection error. For more information on Mininet basic commands, check the basic Mininet walkthrough.

Manipulating SDN components

There are many ways to configure data-paths with an Onos controller, however, an easy way is to do it though the Graphical User Interface (GUI). Newer versions of Onos do not have the GUI enabled by default, therefore we will use a console to enable it first. Log in to your Onos controller via:

        docker exec -it SDNLab_onos_1 bash;

Once logged in, execute the Onos Command Line Interface (CLI) or client console by executing:

        ./apache-karaf-4.2.3/bin/client

Inside the Onos console you can check many things, however, for the moment as there are no connected devices there are few interesting things to to here. For now, we will enable the GUI by executing:

        app activate org.onosproject.gui

You can check the enabled applications with the command:

        apps -s -a

Make sure the output contains the Onos GUI. Now, you can go to your Onos GUI using your browser and going to the address localhost:8181/onos/ui/. The default username / password is onos/rocks. Check the GUI and explore the main menu (bars at the left upper corner).

Go to the main menu -> Applications. Enable the following applications (select and hit the play button near the upper right corner):

  • OpenFlow Base Provider (org.onosproject.openflow-base)

  • Proxy ARP/NDP (org.onosproject.proxyarp), just to avoid taking care of ARP ourselves :)

  • LLDP Link Provider (org.onosproject.lldpprovider)

  • Host Location Provider (org.onosproject.hostprovider)

Indeed, you could have enabled all these applications via the Onos console. Go to your containernet console and execute the command:

        pingall

You should still see no connectivity, but, do not worry, we did that just to make sure our controller recognizes fully our data-plane. Go to the main menu -> Topology, you should be able to see the correct topology (if you do not see the hosts toggle the host visibility by typing h on the GUI or enabling on the display options panel at the left lower corner).

Configuring SDN data-paths

Using SDN routing applications

As previously discussed, there are many ways to configure data-paths. Let us start by the easiest manner. To avoid thinking of such paths and avoiding responsibility is to install an application that decides on how to connect hosts though the data-plane forwarding devices. Go to the applications menu and enable Reactive Forwarding (org.onosproject.fwd). Go to your containernet console and execute the command:

        pingall

The results should be completely different, you should have near to 0% packet loss. You may believe that this is a great tool, however, there is no control over which hosts communicate with each other; simply all hosts are able to communicate using any protocol. This is at least insecure, and most probably not functionally desirable, e.g., assume we need to communicate only h1 with h2 and h3 with h4 (which is the case for our lab, why to communicate the mysql database with the lab-api?). Additionally, our recent study shows that applications may flood the network or install undesired data-paths; in fact, the reactive forwarding application floods the network, sending the intended network packet to all possible output ports until it reaches a host. Therefore, the network packet actually arrives not only to the intended host but, to all of them!

Go to the main menu -> Applications, and disable the reactive forwarding application (or app deactivate org.onosproject.fwd from the Onos console). Verify that the pingall command is not longer working, and that the wordpress (http://localhost:8080/) cannot reach the database.

Using Intents

Instead of supplying rules one by one (for the moment) Onos provides the opportunity to create so called Intents, which is to state a data-path starting at a given host (or switch port) and that finishes at another host (or switch port). The easiest way to use intents is to do it from the GUI. To do so, go to the main menu -> Topology, click h1 (10.0.0.251), while holding shift click h2 (10.0.0.252), and then click the Create Host-To-Host Flow as shown in the picture below.

image

Check that there is both ping connectivity between h1 and h2 and that the wordpress works correctly (i.e., the mysql at h1 can be reached by wordrepss at h2). Go to the main menu -> Topology, click on s1 (the switch with label of:0000000000000001, to see the labels hit the L key on your keyboard), and then click Show Flow View for This Device below the summary panel at the right side. You should understand that the intent is translated to flow rules. In fact, the intent is translated to two flow rules, those are:

  • The flow rule with selector IN_PORT:1, ETH_DST:9A:D8:73:D8:90:6B, ETH_SRC:9A:D8:73:D8:90:6A and output to port 2

  • The flow rule with selector IN_PORT:2, ETH_DST:9A:D8:73:D8:90:6A, ETH_SRC:9A:D8:73:D8:90:6B and output to port 1

The meaning of the rules is pretty straightforward. The first rule says that any packet comming from port 1 (which is connected to h1), coming from the MAC address of h1, going to the MAC address of h2 should be output to port 2 (which is connected to s2). In order to deliver packets from h1 to h2, what is the rule that complements the previous one on s2? Verify that.

Configuring such intents can be insecure, all type of traffic is permitted between hosts. Go to the main menu -> Intents and check that there are installed intents. Remove both intents and check that no connectivity is possible between h1 and h2 (you can also check that the flow rules are deleted).

Using the REST API

Onos provides a REST API to query the controller information and also to configure it. An easy way to interact with the API is through the Onos documentation, accessible via localhost:8181/onos/v1/docs/.

Go to the API URL and check the list of devices. The data exchange format is JSON, a human-readable format. As an example, consider the following device description (of s1):

    {
      "id": "of:0000000000000003",
      "type": "SWITCH",
      "available": true,
      "role": "MASTER",
      "mfr": "Nicira, Inc.",
      "hw": "Open vSwitch",
      "sw": "2.5.5",
      "serial": "None",
      "driver": "ovs",
      "chassisId": "3",
      "lastUpdate": "1554293500780",
      "humanReadableLastUpdate": "connected 3h25m ago",
      "annotations": {
        "channelId": "192.168.0.3:37096",
        "managementAddress": "192.168.0.3",
        "protocol": "OF_13"
      }
    }

As it can be seen, the switch is an Open vSwitch (as provided by containernet), check the other properties and check the list of devices by going to the REST API, /devices and clicking on "Try it out!".

Go for the intents are in the REST API (http://localhost:8181/onos/v1/docs/#/intents). Search for the POST /intents section. Introduce the following text into the stream:

{
  "type": "PointToPointIntent",
  "appId": "org.onosproject.restconf",
  "priority": 55,
  "ingressPoint":
  {
    "device": "of:0000000000000002",
    "port": "1"
  },
  "egressPoint":
  {
    "device": "of:0000000000000001",
    "port": "1"
  },
  "selector": {
    "criteria": [
    {    
      "type": "ETH_TYPE",
      "ethType": "0x800"
    },
    {
      "type": "IPV4_SRC",
      "ip": "10.0.0.252/32"
    },
    {
      "type": "IPV4_DST",
      "ip": "10.0.0.251/32"
    }, 
    {   
      "type": "IP_PROTO",
      "protocol": 6
    },    
    { 
      "type": "TCP_DST",
      "tcpPort": 3306
    }      
    ]
  }  
}

Click on the "Try it out!" button. You should receive a successful response (with code 201). This is how simple is to add an intent though the REST API. Understand that the selector; the selector restricts the matching traffic, being able to specify in a granular manner to which type of traffic the intent corresponds. Observe that in the intent the origin is the port 1 at s2, which corresponds to the host h2; the destination port is 3306 due to the fact that wordpress communicates with a mysql database (that uses port TCP 3306 at the destiny). If you try the wordpress at this moment no database communication should succeed. The reason is that h1 (mysql) cannot reply to the communication. To do so, add the following intent:

{
  "type": "PointToPointIntent",
  "appId": "org.onosproject.restconf",
  "priority": 55,
  "ingressPoint":
  {
    "device": "of:0000000000000001",
    "port": "1"
  },
  "egressPoint":
  {
    "device": "of:0000000000000002",
    "port": "1"
  },
  "selector": {
    "criteria": [
    {    
      "type": "ETH_TYPE",
      "ethType": "0x800"
    },
    {
      "type": "IPV4_SRC",
      "ip": "10.0.0.251/32"
    },
    {
      "type": "IPV4_DST",
      "ip": "10.0.0.252/32"
    }, 
    {   
      "type": "IP_PROTO",
      "protocol": 6
    },    
    { 
      "type": "TCP_SRC",
      "tcpPort": 3306
    }      
    ]
  }  
}

Pay attention that this time the selector has source port 3306! Try ping communication and the wordpress database connection. As you can see, the ping is unsuccessful while the wordpress communication is. This gives a great level of granularity. Further, there are other advantages of using intents, for example, assume that the link between s1 and s2 gets interrupted. Intents automatically monitor changes in the topology and adjust the flow rules to an alternative path (if possible). Observe the flow rules (either by inspecting the GUI or by CLI executing the command flows -s). Try to simulate a link interruption by going to your containernet console and executing the following command:

    link s1 s2 down

Observe the flow rules again and check the alternative route they produced. Bring the link back up (link s1 s2 up) and check the flow rules again. As you can see, the paths do not revert to the original one. Further, the choice of path is not possible!

Installing Flow Rules

In case you are doing your own SDN application or if you want to have a very granular control over the data-paths installed on the data-plane then installing flow rules is solution. Consider that a flow rule defines partial paths at a given switch, which packets match at which port and what is the disposition (output to another port, most commonly).

To exemplify how to configure a data-path using flow rules let us configure the data-path h4->s4->s3->h3 for the traffic matching (i.e., with selector):

    ETH_TYPE=0x800 and IPV4_SRC="10.0.0.254/32" and IPV4_DST=10.0.0.253/32 and IP_PROTO=6 and TCP_DST=5000

Go to the REST API to post flows (http://localhost:8181/onos/v1/docs/#!/flows/post_flows), post the following flow rule (choose any app ID of your choosing, remember it):

{
  "flows": 
  [
    {
      "priority": 40000, 
      "timeout": 0,
      "isPermanent": true,
      "deviceId": "of:0000000000000004",
      "treatment": 
      {
        "instructions": 
        [
          {
            "type": "OUTPUT", 
            "port": "3"
          }
        ]
      },
      "selector": 
      {
          "criteria": 
          [
            {    
              "type": "IN_PORT",
              "port": "1"
            },
            {    
              "type": "ETH_TYPE",
              "ethType": "0x800"
            },
            {
              "type": "IPV4_SRC",
              "ip": "10.0.0.254/32"
            },
            {
              "type": "IPV4_DST",
              "ip": "10.0.0.253/32"
            }, 
            {   
              "type": "IP_PROTO",
              "protocol": 6
            },    
            { 
              "type": "TCP_DST",
              "tcpPort": 5000
            }
        ]
      }
    }
  ]
}

Add the corresponding rules so that h4 can connect to port 5000 at h3. Hint, there are 3 more rules. After adding the rules log in to h4 using:

        docker exec -it mn.h4 bash

Execute the following command:

        curl 10.0.0.253:5000/; echo;

If you see a JSON message you have successfully added the rules. If you see the following message then your rules are wrong:

        curl: (7) Failed to connect to 10.0.0.253 port 8888: Connection refused

If you did not configure the rules properly, an easy way to delete flow rules is to do it via the REST API with an application ID (http://localhost:8181/onos/v1/docs/#!/flows/delete_flows_application_appId).

sdnlab's People

Watchers

James Cloos avatar Jose Reyes avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.