Adding flows in OpenDaylight Using JAVA

Continuing my blog about getting the topology of OpenDaylight using Java, in this blog I have tried to give you ready to use java code to deploy a flow on OpenDaylight. As with the previous blog, you will need two jars in your classpath which are:

  1. Apache Codec for encoding the password in Base64.
  2. Jettison to use the JSONObject format for request/response.

Now, once you have this in place, below code can be used to install a flow at the supplied OpenDaylight Controller.

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.codec.binary.Base64;
import org.codehaus.jettison.json.JSONObject;

public class OpenDaylightHelper {

    public static boolean installFlow(JSONObject postData, String user,
            String password, String baseURL) {

        StringBuffer result = new StringBuffer();
        try {

            if (!baseURL.contains("http")) {
                baseURL = "http://" + baseURL;
            }
            baseURL = baseURL
                    + "/controller/nb/v2/flowprogrammer/default/node/OF/"
                    + postData.getJSONObject("node").get("id") + "/staticFlow/"
                    + postData.get("name");

            // Create URL = base URL + container
            URL url = new URL(baseURL);

            // Create authentication string and encode it to Base64
            String authStr = user + ":" + password;
            String encodedAuthStr = Base64.encodeBase64String(authStr
                    .getBytes());

            // Create Http connection
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();

            // Set connection properties
            connection.setRequestMethod("PUT");
            connection.setRequestProperty("Authorization", "Basic "
                    + encodedAuthStr);
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);

            // Set Post Data
            OutputStream os = connection.getOutputStream();
            os.write(postData.toString().getBytes());
            os.close();

            // Get the response from connection's inputStream
            InputStream content = (InputStream) connection.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    content));
            String line = "";
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        if ("success".equalsIgnoreCase(result.toString())) {
            return true;
        } else {
            return false;
        }
    }
}

Here is a snippet for invoking/calling the above code.

public static void main(String[] args) throws JSONException {
        //Sample post data.
        JSONObject postData = new JSONObject();
        postData.put("name", "SaurabhTestFlow");
        postData.put("nwSrc", "192.168.1.10");
        postData.put("nwDst", "192.168.1.11");
        postData.put("installInHw", "true");
        postData.put("priority", "500");
        postData.put("etherType", "0x800");
        postData.put("actions", new JSONArray().put("ENQEUE=2"));

        //Node on which this flow should be installed
        JSONObject node = new JSONObject();
        node.put("id", "00:00:00:76:54:54");
        node.put("type", "OF");
        postData.put("node", node);
        
        //Actual flow install
        boolean result = OpenDaylightHelper.installFlow(postData, "admin", "admin", "localhost:8080");
        
        if(result){
            System.out.println("Flow installed Successfully");
        }else{
            System.err.println("Failed to install flow!");
        }

    }

You can add as many parameters needed in the right format to above postData to install the correct flows in OpenDaylight. Find more details on parameters supported & all the REST api’s at http://opendaylight.nbi.sdngeeks.com.

A more detailed example with source code is available here.

Advertisements

Using JAVA to call OpenDaylight REST NBI to fetch all nodes

As with my previous post where I have noted about how to call OpenDaylight’s REST NBI using JQuery, here, I give a snippet of code to call the same service using JAVA which many people use to write apps on top of SDN Controllers.

You will need two additional jar’s to do this.

  1. Apache Codec for encoding the password in Base64.
  2. Jettison to use the JSONObject format for request/response.

Once you have included the above two jars in your classpath, here something you will have to do to get all ODL nodes:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.codec.binary.Base64;
import org.codehaus.jettison.json.JSONObject;

public class OpenDaylightHelper {

    public static JSONObject getNodes(String user, String password,
            String baseURL) {

        StringBuffer result = new StringBuffer();
        try {

            if (!baseURL.contains("http")) {
                baseURL = "http://" + baseURL;
            }
            baseURL = baseURL + "/controller/nb/v2/switchmanager/default/nodes";

            // Create URL = base URL + container
            URL url = new URL(baseURL);

            // Create authentication string and encode it to Base64
            String authStr = user + ":" + password;
            String encodedAuthStr = Base64.encodeBase64String(authStr
                    .getBytes());

            // Create Http connection
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();

            // Set connection properties
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Authorization", "Basic "
                    + encodedAuthStr);
            connection.setRequestProperty("Accept", "application/json");

            // Get the response from connection's inputStream
            InputStream content = (InputStream) connection.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    content));
            String line = "";
            while ((line = in.readLine()) != null) {
                result.append(line);
            }

            JSONObject nodes = new JSONObject(result.toString());
            return nodes;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

This call should fetch you all the nodes discovered in the topology of OpenDaylight.

More details about ODL NBI can be found on their Wiki.

Using JQuery to call OpenDaylight REST NBI to fetch all nodes

As more and more apps become available on using SDN Controller NBI’s, I thought it might be a good idea to know how easily we can access these using some standard JS frameworks available.

I generally use JQuery for calling SDN Controllers NBI’s directly from the HTML files.

Here is a sample code to find all the nodes discovered by OpenDaylight SDN Controller

 //ODL NBI Endpoint
 var nbiLoc = "/controller/nb/v2/switchmanager/default/nodes";
 //ODL Server Location
 var sdnServer = "http://192.168.1.1:8080";
//Calling the function
console.log(findAllNodes(sdnServer, nbiLoc));
function findAllNodes(sdnServer, nbiLoc) {
 var nodes;
 var url = sdnServer + nbiLoc;
 console.log(url);
 $.ajax({
   url : url,
   type : "GET",
   async : false,
   contentType : "application/json",
   success : function(data, textStatus, jqXHR) {
     console.log(data);
     if (data) {
       nodes = data;
     }
   },
   error : function(jqXHR, textStatus, errorThrown) {
     console.log("Failure", errorThrown);
   },
   beforeSend : function(xhr) {
     //Default Base64 Encoding for (admin/admin)
     xhr.setRequestHeader("Authorization", "Basic YWRtaW46YWRtaW4=");
   }
 });

This call should fetch you all the nodes discovered in the topology of OpenDaylight.

More details about ODL NBI can be found on their Wiki.

Example message exchange sequence between OpenFlow & SDN Controller

Further to understanding the OpenFlow messages that are exchanged between hardware and a SDN Controller in Understanding OpenFlow Communication Channel, I thought it will be nice to know the sequence in which these messages are exchanged.

Based on my understanding using wireshark, a OpenFlow switch and OpenDaylight, below is a visual sequence diagram explaining major message exchanges I could see.

OF Message Exchange Sequence

 

Understanding Openflow Communication Channel

The OpenFlow protocol (1.0.0) describes message exchanges that take place between an OpenFlow controller and an OpenFlow device. Typically, the protocol is implemented on top of SSL or Transport Layer Security (TLS), providing a secure OpenFlow channel.

The OpenFlow protocol enables the controller to perform add, update, and delete actions to the flow entries in the flow tables. It supports three types of messages:

  1. Controller-to-Device: These messages are initiated by the controller and, in some cases, require a response from the device.
  2. Asynchronous: These types of messages are sent without solicitation from the controller.
  3. Symmetric: These messages are sent without solicitation from either the controller or the device. They are simple yet helpful.

Below is the list of complete OpenFlow messages that any implementation needs to support.

OF Communication Messages