Restful API for bgpd
diff --git a/build.xml b/build.xml
index 657a80d..f986cea 100644
--- a/build.xml
+++ b/build.xml
@@ -70,6 +70,8 @@
<include name="curator-framework-1.3.5-SNAPSHOT.jar"/>
<include name="curator-recipes-1.3.5-SNAPSHOT.jar"/>
<include name="zookeeper-3.4.5.jar"/>
+ <include name="ezmorph-1.0.6.jar"/>
+ <include name="json-lib-2.4-jdk15.jar"/>
</patternset>
<patternset id="titanlib">
diff --git a/src/main/java/net/floodlightcontroller/bgproute/BgpRoute.java b/src/main/java/net/floodlightcontroller/bgproute/BgpRoute.java
index 2819253..47f3d1a 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/BgpRoute.java
+++ b/src/main/java/net/floodlightcontroller/bgproute/BgpRoute.java
@@ -1,5 +1,13 @@
package net.floodlightcontroller.bgproute;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.Collection;
import java.util.Map;
import java.util.ArrayList;
@@ -18,6 +26,9 @@
import net.floodlightcontroller.restclient.RestClient;
import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import net.sf.json.JSONSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,6 +41,10 @@
protected ITopologyService topology;
protected static Ptree ptree;
+ protected static String BGPdRestIp;
+ protected static String RouterId;
+
+
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
@@ -41,7 +56,7 @@
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
- m.put(IBgpRouteService.class, this);
+ m.put(IBgpRouteService.class, this);
return m;
}
@@ -69,11 +84,23 @@
// Test.
//test();
+
}
public Ptree getPtree() {
return ptree;
}
+ public void clearPtree() {
+ ptree = null;
+ ptree = new Ptree(32);
+
+ }
+ public String getBGPdRestIp() {
+ return BGPdRestIp;
+ }
+ public String getRouterId() {
+ return RouterId;
+ }
// Return nexthop address as byte array.
public Rib lookupRib(byte[] dest) {
@@ -154,8 +181,113 @@
@Override
public void startUp(FloodlightModuleContext context) {
- restApi.addRestletRoutable(new BgpRouteWebRoutable());
+ restApi.addRestletRoutable(new BgpRouteWebRoutable());
topology.addListener((ITopologyListener) this);
+
+ // get the BGPdRestIp and RouterId from transit-route-pusher.py
+ File file = new File("/home/ubuntu/sdn/transit-route-pusher.py");
+
+
+ try{
+ BufferedReader input = new BufferedReader (new FileReader(file));
+ String text;
+ int is_BGPdRestIp=0;
+ int is_RouterId=0;
+
+ while((text = input.readLine()) != null && (is_BGPdRestIp == 0) || (is_RouterId == 0) ){
+
+ if(is_BGPdRestIp == 1 && is_RouterId ==1)
+ {break;}
+
+ if(is_BGPdRestIp == 0 && text.contains("BGPdRestIp") ){
+ String[] temp = text.split("\"");
+ BGPdRestIp = temp[1];
+ is_BGPdRestIp = 1;
+
+
+ }else if (is_RouterId == 0 && text.contains("RouterId") ){
+
+ String[] temp = text.split("\"");
+ RouterId = temp[1];
+ is_RouterId = 1;
+
+
+ }
+
+ }
+
+
+ } catch(Exception e){
+ e.printStackTrace();
+ }
+
+
+ // automatically get the rib from bgpd at the ONOS initiation process.
+ String dest=RouterId;
+ String str="http://"+BGPdRestIp+"/wm/bgp/"+dest;
+
+
+ try {
+
+ URL url = new URL(str);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+ conn.setRequestProperty("Accept", "application/json");
+
+ if (conn.getResponseCode() != 200) {
+ throw new RuntimeException("Failed : HTTP error code : "
+ + conn.getResponseCode());
+ }
+
+ BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
+ StringBuffer res = new StringBuffer();
+ String line;
+ while ((line = br.readLine()) != null) {
+ res.append(line);
+ }
+
+ String res2=res.toString().replaceAll("\"", "'");
+ JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(res2);
+ JSONArray rib_json_array = jsonObj.getJSONArray("rib");
+ String router_id = jsonObj.getString("router-id");
+
+ int size = rib_json_array.size();
+ System.out.print("size:"+size+"\n");
+ for (int j = 0; j < size; j++) {
+ JSONObject second_json_object = rib_json_array.getJSONObject(j);
+ String prefix = second_json_object.getString("prefix");
+ String nexthop = second_json_object.getString("nexthop");
+
+ //insert each rib entry into the local rib;
+ String[] substring= prefix.split("/");
+ String prefix1=substring[0];
+ String mask1=substring[1];
+
+ Prefix p = new Prefix(prefix1, Integer.valueOf(mask1));
+ PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
+ Rib rib = new Rib(router_id, nexthop, p.masklen);
+
+ if (node.rib != null) {
+ node.rib = null;
+ ptree.delReference(node);
+ }
+ node.rib = rib;
+
+ }
+ br.close();
+ conn.disconnect();
+
+ } catch (MalformedURLException e) {
+
+ e.printStackTrace();
+
+ } catch (IOException e) {
+
+ e.printStackTrace();
+
+ }
+
+
}
@Override
diff --git a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResource.java b/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResource.java
index d5abb5a..28d9621 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResource.java
+++ b/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResource.java
@@ -7,6 +7,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.floodlightcontroller.restclient.RestClient;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
public class BgpRouteResource extends ServerResource {
@@ -27,60 +29,85 @@
}
@SuppressWarnings("unused")
- @Get
- public String get(String fmJson) {
- String dest = (String) getRequestAttributes().get("dest");
- String output = "";
- IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
- get(IBgpRouteService.class.getCanonicalName());
-
- if (dest != null) {
- Prefix p = new Prefix(dest, 32);
- if (p == null) {
- return "[GET]: dest address format is wrong";
- }
- byte [] nexthop = bgpRoute.lookupRib(p.getAddress()).nextHop.getAddress();
- if (nexthop != null) {
- output += "{\"result\": \"" + addrToString(nexthop) + "\"}\n";
+ @Get
+ public String get(String fmJson) {
+ String linpp=fmJson;
+ String dest = (String) getRequestAttributes().get("dest");
+ String output = "";
+ IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
+ get(IBgpRouteService.class.getCanonicalName());
+
+ if (dest != null) {
+ Prefix p = new Prefix(dest, 32);
+ if (p == null) {
+ return "[GET]: dest address format is wrong";
+ }
+
+ // the dest here refers to router-id
+ //BGPdRestIp includes port number, such as 1.1.1.1:8080
+ String BGPdRestIp = bgpRoute.getBGPdRestIp();
+ String url="http://"+BGPdRestIp+"/wm/bgp/"+dest;
+
+
+
+ RestClient.get(url);
+ output="Get rib from bgpd finished!\n";
+ return output;
+
} else {
- output += "{\"result\": \"Nexthop does not exist\"}\n";
- }
- } else {
- Ptree ptree = bgpRoute.getPtree();
- output += "{\n \"rib\": [\n";
- boolean printed = false;
- for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
- if (node.rib == null) {
- continue;
+ Ptree ptree = bgpRoute.getPtree();
+ output += "{\n \"rib\": [\n";
+ boolean printed = false;
+ for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+ if (node.rib == null) {
+ continue;
+ }
+ if (printed == true) {
+ output += ",\n";
+ }
+ output += " {\"prefix\": \"" + addrToString(node.key) + "/" + node.keyBits +"\", ";
+ output += "\"nexthop\": \"" + addrToString(node.rib.nextHop.getAddress()) +"\"}";
+ printed = true;
}
- if (printed == true) {
- output += ",\n";
- }
- output += " {\"prefix\": \"" + addrToString(node.key) + "/" + node.keyBits +"\", ";
- output += "\"nexthop\": \"" + addrToString(node.rib.nextHop.getAddress()) +"\"}";
- printed = true;
+ //output += "{\"router_id\": \"" + addrToString(node.rib.routerId.getAddress()) +"\"}\n";
+ output += "\n ]\n}\n";
+
}
- //output += "{\"router_id\": \"" + addrToString(node.rib.routerId.getAddress()) +"\"}\n";
- output += "\n ]\n}\n";
+ return output;
}
-
- return output;
- }
+
+ public static ByteBuffer toByteBuffer(String value) throws UnsupportedEncodingException
+ {
+ return ByteBuffer.wrap(value.getBytes("UTF-8"));
+ }
+
+public static String toString(ByteBuffer buffer) throws UnsupportedEncodingException
+ {
+ byte[] bytes = new byte[buffer.remaining()];
+ buffer.get(bytes);
+ return new String(bytes, "UTF-8");
+
+ }
+
+
@Post
public String store(String fmJson) {
IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
get(IBgpRouteService.class.getCanonicalName());
-
- Ptree ptree = bgpRoute.getPtree();
-
+
+ Ptree ptree = bgpRoute.getPtree();
+
String router_id = (String) getRequestAttributes().get("routerid");
String prefix = (String) getRequestAttributes().get("prefix");
String mask = (String) getRequestAttributes().get("mask");
String nexthop = (String) getRequestAttributes().get("nexthop");
String capability = (String) getRequestAttributes().get("capability");
- String reply = null;
+
+
+ String reply = "";
if (capability == null) {
+
// this is a prefix add
Prefix p = new Prefix(prefix, Integer.valueOf(mask));
PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
@@ -94,46 +121,73 @@
reply = "[POST: " + prefix + "/" + mask + ":" + nexthop + "]";
log.info(reply);
+
- RestClient.get("http://localhost:5000/bgp_update");
+ }else if(capability.equals("1")){
+ reply = "[POST-capability: " + capability + "]\n";
+ log.info(reply);
+ // to store the number in the top node of the Ptree
+
+ }else{
+ reply = "[POST-capability: " + capability + "]\n";
+ log.info(reply);
+ // to store the number in the top node of the Ptree
+
}
+
return reply + "\n";
+
+
}
@Delete
public String delete(String fmJson) {
- IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
+ IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
get(IBgpRouteService.class.getCanonicalName());
- Ptree ptree = bgpRoute.getPtree();
-
+ Ptree ptree = bgpRoute.getPtree();
+
String routerId = (String) getRequestAttributes().get("routerid");
String prefix = (String) getRequestAttributes().get("prefix");
String mask = (String) getRequestAttributes().get("mask");
String nextHop = (String) getRequestAttributes().get("nexthop");
String capability = (String) getRequestAttributes().get("capability");
- String reply = null;
+
+ String reply = "";
if (capability == null) {
- // this is a prefix delete
- Prefix p = new Prefix(prefix, Integer.valueOf(mask));
- PtreeNode node = ptree.lookup(p.getAddress(), p.masklen);
- Rib r = new Rib(routerId, nextHop, p.masklen);
-
- if (node != null && node.rib != null) {
- if (r.equals(node.rib)) {
- node.rib = null;
- ptree.delReference(node);
- }
- }
+ // this is a prefix delete
+ Prefix p = new Prefix(prefix, Integer.valueOf(mask));
+
+ PtreeNode node = ptree.lookup(p.getAddress(), p.masklen);
+
+ Rib r = new Rib(routerId, nextHop, p.masklen);
+
+ if (node != null && node.rib != null) {
+
+ if (r.equals(node.rib)) {
+
+ node.rib = null;
+ ptree.delReference(node);
+ }
+ }
+
+
+ reply =reply + "[DELE: " + prefix + "/" + mask + ":" + nextHop + "]";
+
+ }else {
- reply = "[DELE: " + prefix + "/" + mask + ":" + nextHop + "]";
- log.info(reply);
+ // clear the local rib: Ptree
+ bgpRoute.clearPtree();
+ reply = "[DELE-capability: " + capability + "; The local Rib is cleared!]\n";
- RestClient.get("http://localhost:5000/bgp_update");
- }
-
+
+ // to store the number in the top node of the Ptree
+
+ }
+ log.info(reply);
+
return reply + "\n";
}
}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResourceSynch.java b/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResourceSynch.java
new file mode 100644
index 0000000..d0c337a
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResourceSynch.java
@@ -0,0 +1,72 @@
+package net.floodlightcontroller.bgproute;
+
+
+import org.restlet.resource.Post;
+import org.restlet.resource.Delete;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import net.floodlightcontroller.restclient.RestClient;
+
+
+public class BgpRouteResourceSynch extends ServerResource {
+
+ protected static Logger log = LoggerFactory
+ .getLogger(BgpRouteResource.class);
+
+ @Post
+ public String store(String fmJson) {
+
+ IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
+ get(IBgpRouteService.class.getCanonicalName());
+
+ String router_id = (String) getRequestAttributes().get("routerid");
+ String prefix = (String) getRequestAttributes().get("prefix");
+ String mask = (String) getRequestAttributes().get("mask");
+ String nexthop = (String) getRequestAttributes().get("nexthop");
+
+ try{
+
+ String BGPdRestIp = bgpRoute.getBGPdRestIp();
+
+ //BGPdRestIp includes port number, such as 1.1.1.1:8080
+ RestClient.post("http://"+BGPdRestIp+"/wm/bgp/"+router_id+"/"+prefix+"/"+mask+"/"+nexthop);
+ }catch(Exception e)
+ {e.printStackTrace();}
+
+ String reply = "";
+ reply = "[POST: " + prefix + "/" + mask + ":" + nexthop + "/synch]";
+ log.info(reply);
+
+ return reply + "\n";
+
+
+ }
+
+ @Delete
+ public String delete(String fmJson) {
+ IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
+ get(IBgpRouteService.class.getCanonicalName());
+
+ String routerId = (String) getRequestAttributes().get("routerid");
+ String prefix = (String) getRequestAttributes().get("prefix");
+ String mask = (String) getRequestAttributes().get("mask");
+ String nextHop = (String) getRequestAttributes().get("nexthop");
+
+ String reply = "";
+ try{
+ String BGPdRestIp = bgpRoute.getBGPdRestIp();
+
+ RestClient.delete("http://"+BGPdRestIp+"/wm/bgp/"+routerId+"/"+prefix+"/"+mask+"/"+nextHop);
+
+ }catch(Exception e)
+ {e.printStackTrace();}
+
+ reply =reply + "[DELE: " + prefix + "/" + mask + ":" + nextHop + "/synch]";
+
+ log.info(reply);
+
+
+ return reply + "\n";
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteWebRoutable.java b/src/main/java/net/floodlightcontroller/bgproute/BgpRouteWebRoutable.java
index 37d5696..a18c550 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/bgproute/BgpRouteWebRoutable.java
@@ -12,7 +12,8 @@
Router router = new Router(context);
router.attach("/json", BgpRouteResource.class);
router.attach("/rib/{dest}", BgpRouteResource.class);
- router.attach("/{routerid}/{prefix}/{mask}/{nexthop}", BgpRouteResource.class);
+ router.attach("/{routerid}/{prefix}/{mask}/{nexthop}", BgpRouteResource.class);
+ router.attach("/{routerid}/{prefix}/{mask}/{nexthop}/synch", BgpRouteResourceSynch.class);
router.attach("/{routerid}/{capability}", BgpRouteResource.class);
return router;
}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/IBgpRouteService.java b/src/main/java/net/floodlightcontroller/bgproute/IBgpRouteService.java
index 62bdf5e..a6025ef 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/IBgpRouteService.java
+++ b/src/main/java/net/floodlightcontroller/bgproute/IBgpRouteService.java
@@ -8,4 +8,11 @@
public Ptree getPtree();
+ public String getBGPdRestIp();
+
+ public String getRouterId();
+
+ public void clearPtree() ;
+
+
}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/Ptree.java b/src/main/java/net/floodlightcontroller/bgproute/Ptree.java
index d53789e..dcb6e83 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/Ptree.java
+++ b/src/main/java/net/floodlightcontroller/bgproute/Ptree.java
@@ -13,7 +13,7 @@
maxKeyOctets = bit_to_octet(max_key_bits);
refCount = 0;
}
-
+
public PtreeNode acquire(byte [] key) {
return acquire(key, maxKeyBits);
}
@@ -278,6 +278,10 @@
return add;
}
+ //add by linpp
+ private void clear() {
+
+ }
private void node_remove(PtreeNode node) {
PtreeNode child;
diff --git a/src/main/java/net/floodlightcontroller/bgproute/Rib.java b/src/main/java/net/floodlightcontroller/bgproute/Rib.java
index 71868ff..574e820 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/Rib.java
+++ b/src/main/java/net/floodlightcontroller/bgproute/Rib.java
@@ -40,6 +40,7 @@
public boolean equals(Rib r) {
- return this.routerId == r.routerId && this.nextHop == r.nextHop && this.masklen == r.masklen;
+ return this.routerId.equals(r.routerId) && this.nextHop.equals(r.nextHop) && this.masklen == r.masklen;
+
}
}
diff --git a/src/main/java/net/floodlightcontroller/restclient/RestClient.java b/src/main/java/net/floodlightcontroller/restclient/RestClient.java
index 07eab45..541b42d 100644
--- a/src/main/java/net/floodlightcontroller/restclient/RestClient.java
+++ b/src/main/java/net/floodlightcontroller/restclient/RestClient.java
@@ -1,10 +1,17 @@
package net.floodlightcontroller.restclient;
+import java.io.BufferedReader;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import net.sf.json.JSONSerializer;
+
+
public class RestClient {
public static void get (String str) {
@@ -16,7 +23,7 @@
URL url = new URL(str);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
+ conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
@@ -24,18 +31,68 @@
+ conn.getResponseCode());
}
- /* Disable reading the output from the server for now
- *
- BufferedReader br = new BufferedReader(new InputStreamReader(
- (conn.getInputStream())));
-
- String output;
- System.out.println("Output from Server .... \n");
- while ((output = br.readLine()) != null) {
- System.out.println(output);
- }
- */
+ if (conn.getContentType().equals("application/json"))
+ { }else{
+ System.out.print("The content received is not json format!");
+ }
+ BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
+ StringBuffer res = new StringBuffer();
+ String line;
+ while ((line = br.readLine()) != null) {
+ res.append(line);
+ }
+
+ String res2=res.toString().replaceAll("\"", "'");
+ JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(res2);
+ JSONArray rib_json_array = jsonObj.getJSONArray("rib");
+ String router_id = jsonObj.getString("router-id");
+
+ int size = rib_json_array.size();
+ System.out.print("size:"+size+"\n");
+ for (int j = 0; j < size; j++) {
+ JSONObject second_json_object = rib_json_array.getJSONObject(j);
+ String prefix = second_json_object.getString("prefix");
+ String nexthop = second_json_object.getString("nexthop");
+
+ //insert each rib entry into the local rib;
+ RestClient.post("http://127.0.0.1:8090/wm/bgp/"+router_id+"/"+prefix+"/"+nexthop);
+
+
+
+ }
+ br.close();
+ conn.disconnect();
+
+ } catch (MalformedURLException e) {
+
+ e.printStackTrace();
+
+ } catch (IOException e) {
+
+ e.printStackTrace();
+
+ }
+ }
+
+public static void post (String str) {
+
+ if (str == null)
+ return;
+
+ try {
+
+ URL url = new URL(str);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setDoOutput(true);
+ conn.setRequestMethod("POST");
+ conn.setRequestProperty("Content-Type", "application/json");
+
+ if (conn.getResponseCode() != 200) {
+ throw new RuntimeException("Failed : HTTP error code : "
+ + conn.getResponseCode());
+ }
+
conn.disconnect();
} catch (MalformedURLException e) {
@@ -48,4 +105,38 @@
}
}
+
+
+public static void delete (String str) {
+
+ if (str == null)
+ return;
+
+ try {
+
+ URL url = new URL(str);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("DELETE");
+ conn.setRequestProperty("Accept", "application/json");
+
+
+ if (conn.getResponseCode() != 200) {
+ throw new RuntimeException("Failed : HTTP error code : "
+ + conn.getResponseCode());
+ }
+
+ conn.disconnect();
+
+ } catch (MalformedURLException e) {
+
+ e.printStackTrace();
+
+ } catch (IOException e) {
+
+ e.printStackTrace();
+
+ }
+}
+
+
}