Moved bgproute package to onos namespace
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
new file mode 100644
index 0000000..16cb90b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
@@ -0,0 +1,609 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.devicemanager.IDeviceService;
+import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
+import net.floodlightcontroller.packet.Ethernet;
+import net.floodlightcontroller.restserver.IRestApiService;
+import net.floodlightcontroller.topology.ITopologyListener;
+import net.floodlightcontroller.topology.ITopologyService;
+import net.floodlightcontroller.util.DataPath;
+import net.floodlightcontroller.util.Dpid;
+import net.floodlightcontroller.util.FlowEntry;
+import net.floodlightcontroller.util.IPv4;
+import net.floodlightcontroller.util.MACAddress;
+import net.floodlightcontroller.util.Port;
+import net.floodlightcontroller.util.SwitchPort;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import net.sf.json.JSONSerializer;
+
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionDataLayerDestination;
+import org.openflow.protocol.action.OFActionOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.net.InetAddresses;
+
+public class BgpRoute implements IFloodlightModule, IBgpRouteService, ITopologyListener {
+	
+	protected static Logger log = LoggerFactory.getLogger(BgpRoute.class);
+
+	protected IFloodlightProviderService floodlightProvider;
+	protected ITopologyService topology;
+	protected ITopoRouteService topoRouteService;
+	protected IDeviceService devices;
+	protected IRestApiService restApi;
+	
+	protected static Ptree ptree;
+	protected String bgpdRestIp;
+	protected String routerId;
+	
+	protected Set<InetAddress> routerIpAddresses;
+	
+	//We need to identify our flows somehow. But like it says in LearningSwitch.java,
+	//the controller/OS should hand out cookie IDs to prevent conflicts.
+	protected final long APP_COOKIE = 0xa0000000000000L;
+	//Cookie for flows that do L2 forwarding within SDN domain to egress routers
+	protected final long L2_FWD_COOKIE = APP_COOKIE + 1;
+	//Cookie for flows in ingress switches that rewrite the MAC address
+	protected final long MAC_RW_COOKIE = APP_COOKIE + 2;
+	//Forwarding uses priority 0, and the mac rewrite entries in ingress switches
+	//need to be higher priority than this otherwise the rewrite may not get done
+	protected final short SDNIP_PRIORITY = 10;
+	
+	//TODO temporary
+	protected List<GatewayRouter> gatewayRouters;
+	
+	private void initGateways(){
+		gatewayRouters = new ArrayList<GatewayRouter>();
+		//00:00:00:00:00:00:0s0:a3 port 1
+		gatewayRouters.add(
+				new GatewayRouter(new SwitchPort(new Dpid(163L), new Port((short)1)),
+				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x02, 0x01}),
+				new IPv4("192.168.10.1"),
+				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}),
+				new IPv4("192.168.10.101")));
+		//00:00:00:00:00:00:00:a5 port 1
+		//gatewayRouters.add(new SwitchPort(new Dpid(165L), new Port((short)1)));
+		gatewayRouters.add(
+				new GatewayRouter(new SwitchPort(new Dpid(165L), new Port((short)1)),
+				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x02, 0x02}),
+				new IPv4("192.168.20.1"),
+				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}),
+				new IPv4("192.168.20.101")));
+		//00:00:00:00:00:00:00:a2 port 1
+		//gatewayRouters.add(new SwitchPort(new Dpid(162L), new Port((short)1)));
+		gatewayRouters.add(
+				new GatewayRouter(new SwitchPort(new Dpid(162L), new Port((short)1)),
+				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x03, 0x01}),
+				new IPv4("192.168.30.1"),
+				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}),
+				new IPv4("192.168.30.101")));
+		//00:00:00:00:00:00:00:a6
+		//gatewayRouters.add(new SwitchPort(new Dpid(166L), new Port((short)1)));
+		gatewayRouters.add(
+				new GatewayRouter(new SwitchPort(new Dpid(166L), new Port((short)1)),
+				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x04, 0x01}),
+				new IPv4("192.168.40.1"),
+				new MACAddress(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x04}),
+				new IPv4("192.168.40.101")));
+		
+	}
+	
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+		Collection<Class<? extends IFloodlightService>> l 
+			= new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IBgpRouteService.class);
+		return l;
+	}
+
+	@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);
+		return m;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+		Collection<Class<? extends IFloodlightService>> l 
+			= new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IFloodlightProviderService.class);
+		l.add(ITopologyService.class);
+		l.add(ITopoRouteService.class);
+		l.add(IDeviceService.class);
+		l.add(IRestApiService.class);
+		return l;
+	}
+	
+	@Override
+	public void init(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+	    
+		initGateways();
+		
+	    ptree = new Ptree(32);
+	    
+	    routerIpAddresses = new HashSet<InetAddress>();
+		
+		// Register floodlight provider and REST handler.
+		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+		topology = context.getServiceImpl(ITopologyService.class);
+		topoRouteService = context.getServiceImpl(ITopoRouteService.class);
+		devices = context.getServiceImpl(IDeviceService.class);
+		restApi = context.getServiceImpl(IRestApiService.class);		
+		
+		//Read in config values
+		bgpdRestIp = context.getConfigParams(this).get("BgpdRestIp");
+		if (bgpdRestIp == null){
+			log.error("BgpdRestIp property not found in config file");
+			System.exit(1);
+		}
+		else {
+			log.info("BgpdRestIp set to {}", bgpdRestIp);
+		}
+		
+		routerId = context.getConfigParams(this).get("RouterId");
+		if (routerId == null){
+			log.error("RouterId property not found in config file");
+			System.exit(1);
+		}
+		else {
+			log.info("RouterId set to {}", routerId);
+		}
+		// 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) {
+		if (ptree == null) {
+		    log.debug("lookupRib: ptree null");
+		    return null;
+		}
+		
+		PtreeNode node = ptree.match(dest, 32);
+		if (node == null) {
+            log.debug("lookupRib: ptree node null");
+			return null;
+		}
+		
+		if (node.rib == null) {
+            log.debug("lookupRib: ptree rib null");
+			return null;
+		}
+		
+		ptree.delReference(node);
+		
+		return node.rib;
+	}
+	
+	//TODO looks like this should be a unit test
+	@SuppressWarnings("unused")
+    private void test() throws UnknownHostException {
+		System.out.println("Here it is");
+		Prefix p = new Prefix("128.0.0.0", 8);
+		Prefix q = new Prefix("8.0.0.0", 8);
+		Prefix r = new Prefix("10.0.0.0", 24);
+		Prefix a = new Prefix("10.0.0.1", 32);
+	
+		ptree.acquire(p.getAddress(), p.masklen);
+		ptree.acquire(q.getAddress(), q.masklen);
+		ptree.acquire(r.getAddress(), r.masklen);
+	
+		System.out.println("Traverse start");
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+			Prefix p_result = new Prefix(node.key, node.keyBits);
+		}
+	
+		PtreeNode n = ptree.match(a.getAddress(), a.masklen);
+		if (n != null) {
+			System.out.println("Matched prefix for 10.0.0.1:");
+			Prefix x = new Prefix(n.key, n.keyBits);
+			ptree.delReference(n);
+		}
+		
+		n = ptree.lookup(p.getAddress(), p.masklen);
+		if (n != null) {
+			ptree.delReference(n);
+			ptree.delReference(n);
+		}
+		System.out.println("Traverse start");
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+			Prefix p_result = new Prefix(node.key, node.keyBits);
+		}
+		
+		n = ptree.lookup(q.getAddress(), q.masklen);
+		if (n != null) {
+			ptree.delReference(n);
+			ptree.delReference(n);
+		}
+		System.out.println("Traverse start");
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+			Prefix p_result = new Prefix(node.key, node.keyBits);
+		}
+		
+		n = ptree.lookup(r.getAddress(), r.masklen);
+		if (n != null) {
+			ptree.delReference(n);
+			ptree.delReference(n);
+		}
+		System.out.println("Traverse start");
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+			Prefix p_result = new Prefix(node.key, node.keyBits);
+		}
+
+	}
+	
+	private void retrieveRib(){
+		String url = "http://" + bgpdRestIp + "/wm/bgp/" + routerId;
+		String response = RestClient.get(url);
+		
+		if (response.equals("")){
+			return;
+		}
+		
+		response = response.replaceAll("\"", "'");
+		JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(response);  
+		JSONArray rib_json_array = jsonObj.getJSONArray("rib");
+		String router_id = jsonObj.getString("router-id");
+
+		int size = rib_json_array.size();
+
+		log.info("Retrived RIB of {} entries from BGPd", size);
+		
+		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;
+			try {
+				p = new Prefix(prefix1, Integer.valueOf(mask1));
+			} catch (NumberFormatException e) {
+				log.warn("Wrong mask format in RIB JSON: {}", mask1);
+				continue;
+			} catch (UnknownHostException e1) {
+				log.warn("Wrong prefix format in RIB JSON: {}", prefix1);
+				continue;
+			}
+			
+			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;
+			
+			prefixAdded(node);
+		} 
+	}
+	
+	public void prefixAdded(PtreeNode node) {
+		//Add a flow to rewrite mac for this prefix to all border switches
+		GatewayRouter thisRouter = null;
+		for (GatewayRouter router : gatewayRouters){	
+			if (router.getRouterIp().value() == 
+					InetAddresses.coerceToInteger(node.rib.nextHop)){
+				thisRouter = router;
+				break;
+			}
+		}
+		
+		if (thisRouter == null){
+			//TODO local router isn't in gateway list so this will get thrown
+			//Need to work out what to do about local prefixes with next hop 0.0.0.0.
+			log.error("Couldn't find next hop router in router {} in config"
+					, node.rib.nextHop.toString());
+			return; //just quit out here? This is probably a configuration error
+		}
+
+		for (GatewayRouter ingressRouter : gatewayRouters){
+			if (ingressRouter == thisRouter) {
+				continue;
+			}
+			
+			DataPath shortestPath = topoRouteService.getShortestPath(
+					ingressRouter.getAttachmentPoint(), 
+					thisRouter.getAttachmentPoint());
+			
+			if (shortestPath == null){
+				log.debug("Shortest path between {} and {} not found",
+						ingressRouter.getAttachmentPoint(), 
+						thisRouter.getAttachmentPoint());
+				return; // just quit here?
+			}
+			
+			//TODO check the shortest path against the cached version we
+			//calculated before. If they don't match up that's a problem
+			
+			//Set up the flow mod
+			OFFlowMod fm =
+	                (OFFlowMod) floodlightProvider.getOFMessageFactory()
+	                                              .getMessage(OFType.FLOW_MOD);
+			
+	        fm.setIdleTimeout((short)0)
+	        .setHardTimeout((short)0)
+	        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+	        .setCookie(MAC_RW_COOKIE)
+	        .setCommand(OFFlowMod.OFPFC_ADD)
+	        //.setMatch(match)
+	        //.setActions(actions)
+	        .setPriority(SDNIP_PRIORITY)
+	        .setLengthU(OFFlowMod.MINIMUM_LENGTH
+	        		+ OFActionDataLayerDestination.MINIMUM_LENGTH
+	        		+ OFActionOutput.MINIMUM_LENGTH);
+	        
+	        OFMatch match = new OFMatch();
+	        match.setDataLayerType(Ethernet.TYPE_IPv4);
+	        match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+	        
+	        match.setDataLayerSource(ingressRouter.getRouterMac().toBytes());
+	        match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
+	        
+	        //match.setDataLayerDestination(ingressRouter.getSdnRouterMac().toBytes());
+	        //match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
+
+	        InetAddress address = null;
+	        try {
+				address = InetAddress.getByAddress(node.key);
+			} catch (UnknownHostException e1) {
+				//Should never happen is the reverse conversion has already been done
+				log.error("Malformed IP address");
+				return;
+			}
+	        
+	        match.setFromCIDR(address.getHostAddress() + "/" + node.rib.masklen, OFMatch.STR_NW_DST);
+	        fm.setMatch(match);
+	        
+	        //Set up MAC rewrite action
+	        OFActionDataLayerDestination macRewriteAction = new OFActionDataLayerDestination();
+	        macRewriteAction.setDataLayerAddress(thisRouter.getRouterMac().toBytes());
+	        
+	        //Set up output action
+	        OFActionOutput outputAction = new OFActionOutput();
+	        outputAction.setMaxLength((short)0xffff); //TODO check what this is (and if needed for mac rewrite)
+	        
+	        Port outputPort = shortestPath.flowEntries().get(0).outPort();
+	        outputAction.setPort(outputPort.value());
+	        
+	        List<OFAction> actions = new ArrayList<OFAction>();
+	        actions.add(macRewriteAction);
+	        actions.add(outputAction);
+	        fm.setActions(actions);
+	        
+	        //Write to switch
+	        IOFSwitch sw = floodlightProvider.getSwitches()
+	        		.get(ingressRouter.getAttachmentPoint().dpid().value());
+	        
+            if (sw == null){
+            	log.warn("Switch not found when pushing flow mod");
+            	continue;
+            }
+            
+            List<OFMessage> msglist = new ArrayList<OFMessage>();
+            msglist.add(fm);
+            try {
+				sw.write(msglist, null);
+				sw.flush();
+			} catch (IOException e) {
+				log.error("Failure writing flow mod", e);
+			}
+		}
+	}
+	
+	public void prefixDeleted(PtreeNode node) {
+		//Remove MAC rewriting flows from other border switches
+		
+	}
+	
+	/*
+	 * On startup we need to calculate a full mesh of paths between all gateway
+	 * switches
+	 */
+	private void calculateFullMesh(){
+		Map<IOFSwitch, SwitchPort> gatewaySwitches = new HashMap<IOFSwitch, SwitchPort>();
+		
+		//have to account for switches not being there, paths not being found.
+		
+		//for (SwitchPort switchPort : gatewayRouters){
+		for (GatewayRouter router : gatewayRouters){
+			SwitchPort switchPort = router.getAttachmentPoint();
+			
+			IOFSwitch sw = floodlightProvider.getSwitches().get(switchPort.dpid().value());
+			
+			if (sw == null){
+				log.debug("Gateway switch {} not here yet", switchPort.dpid().value());
+				return; // just quit here?
+			}
+			
+			//Only need to know 1 external-facing port from each gateway switch
+			//which we can feed into shortest path calculation
+			if (!gatewaySwitches.containsKey(sw)){
+				gatewaySwitches.put(sw, switchPort);
+			}
+			
+		}
+		log.debug("size {}", gatewaySwitches.size());
+		
+		//For each border router, calculate and install a path from every other
+		//border switch to said border router. However, don't install the entry
+		//in to the first hop switch, as we need to install an entry to rewrite
+		//for each prefix received. This will be done later when prefixes have 
+		//actually been received.
+		
+		for (GatewayRouter dstRouter : gatewayRouters){
+			SwitchPort routerAttachmentPoint = dstRouter.getAttachmentPoint();
+			for (Map.Entry<IOFSwitch, SwitchPort> src : gatewaySwitches.entrySet()) {
+		
+				if (routerAttachmentPoint.dpid().value() == 
+						src.getKey().getId()){
+					continue;
+				}
+				
+				DataPath shortestPath = topoRouteService.getShortestPath(
+						src.getValue(), routerAttachmentPoint);
+				
+				if (shortestPath == null){
+					log.debug("Shortest path between {} and {} not found",
+							src.getValue(), routerAttachmentPoint);
+					return; // just quit here?
+				}
+				
+				//install flows
+				installPath(shortestPath.flowEntries(), dstRouter);
+			}
+		}
+	}
+	
+	private void installPath(List<FlowEntry> flowEntries, GatewayRouter router){
+
+		//Set up the flow mod
+		OFFlowMod fm =
+                (OFFlowMod) floodlightProvider.getOFMessageFactory()
+                                              .getMessage(OFType.FLOW_MOD);
+		
+        OFActionOutput action = new OFActionOutput();
+        action.setMaxLength((short)0xffff);
+        List<OFAction> actions = new ArrayList<OFAction>();
+        actions.add(action);
+        
+        fm.setIdleTimeout((short)0)
+        .setHardTimeout((short)0)
+        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+        .setCookie(L2_FWD_COOKIE)
+        .setCommand(OFFlowMod.OFPFC_ADD)
+        //.setMatch(match)
+        .setActions(actions)
+        .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+        
+        //Don't push the first flow entry. We need to push entries in the
+		//first switch based on IP prefix which we don't know yet.
+        for (int i = 1; i < flowEntries.size(); i++){        	
+        	FlowEntry flowEntry = flowEntries.get(i);
+           
+            OFMatch match = new OFMatch();
+            match.setDataLayerDestination(router.getRouterMac().toBytes());
+            match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
+            ((OFActionOutput) fm.getActions().get(0)).setPort(flowEntry.outPort().value());
+            
+            fm.setMatch(match);
+            
+            IOFSwitch sw = floodlightProvider.getSwitches().get(flowEntry.dpid().value());
+            
+            if (sw == null){
+            	log.warn("Switch not found when pushing flow mod");
+            	continue;
+            }
+            
+            List<OFMessage> msglist = new ArrayList<OFMessage>();
+            msglist.add(fm);
+            try {
+				sw.write(msglist, null);
+				sw.flush();
+			} catch (IOException e) {
+				log.error("Failure writing flow mod", e);
+			}
+            
+            try {
+                fm = fm.clone();
+            } catch (CloneNotSupportedException e1) {
+                log.error("Failure cloning flow mod", e1);
+            }
+		}
+	}
+	
+	@Override
+	public void startUp(FloodlightModuleContext context) {
+		restApi.addRestletRoutable(new BgpRouteWebRoutable());
+		topology.addListener(this);
+		
+		//Retrieve the RIB from BGPd during startup
+		retrieveRib();
+		
+		//Don't have to do this as we'll never have switches connected here
+		//calculateFullMesh();
+	}
+
+	@Override
+	public void topologyChanged() {
+		//Probably need to look at all changes, not just port changes
+		/*
+		boolean change = false;
+		String changelog = "";
+		
+		for (LDUpdate ldu : topology.getLastLinkUpdates()) {
+			if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.PORT_DOWN)) {
+				change = true;
+				changelog = changelog + " down ";
+			} else if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.PORT_UP)) {
+				change = true;
+				changelog = changelog + " up ";
+			}
+		}
+		log.info ("received topo change" + changelog);
+
+		if (change) {
+			//RestClient.get ("http://localhost:5000/topo_change");
+		}
+		*/
+		
+		for (LDUpdate update : topology.getLastLinkUpdates()){
+			log.debug("{} event causing internal L2 path recalculation",
+					update.getOperation().toString());
+			
+		}
+		calculateFullMesh();
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
new file mode 100644
index 0000000..34c5c43b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
@@ -0,0 +1,212 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.net.UnknownHostException;
+
+import org.restlet.resource.Delete;
+import org.restlet.resource.Get;
+import org.restlet.resource.Post;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpRouteResource extends ServerResource {
+
+	protected static Logger log = LoggerFactory.getLogger(BgpRouteResource.class);
+
+	private String addrToString(byte [] addr) {
+		String str = "";
+
+		for (int i = 0; i < 4; i++) {
+			int val = (addr[i] & 0xff);
+			str += val;
+			if (i != 3)
+				str += ".";
+		}
+
+		return str;
+	}
+
+	//@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) {
+			//TODO Needs to be changed to use the new RestClient.get().
+			
+			
+			//Prefix p;
+			//try {
+			//	p = new Prefix(dest, 32);
+			//} catch (UnknownHostException e) {
+			//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 {
+			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;
+			}
+			//output += "{\"router_id\": \"" + addrToString(node.rib.routerId.getAddress()) +"\"}\n";
+			output += "\n  ]\n}\n";
+		}
+		
+		return output;
+	}
+
+	//unused?
+	/*
+	public static ByteBuffer toByteBuffer(String value) throws UnsupportedEncodingException {
+		return ByteBuffer.wrap(value.getBytes("UTF-8"));
+	}
+	*/
+
+	//unused?
+	/*
+	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();
+
+		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 = "";
+
+		if (capability == null) {
+			// this is a prefix add
+			Prefix p;
+			try {
+				p = new Prefix(prefix, Integer.valueOf(mask));
+			} catch (NumberFormatException e) {
+				reply = "[POST: mask format is wrong]";
+				log.info(reply);
+				return reply + "\n";				
+			} catch (UnknownHostException e1) {
+				reply = "[POST: prefix format is wrong]";
+				log.info(reply);
+				return reply + "\n";
+			}
+			
+			PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
+			Rib rib = new Rib(routerId, nexthop, p.masklen);
+
+			if (node.rib != null) {
+				node.rib = null;
+				ptree.delReference(node);
+			}
+			node.rib = rib;
+
+			bgpRoute.prefixAdded(node);
+			
+			reply = "[POST: " + prefix + "/" + mask + ":" + nexthop + "]";
+			log.info(reply);
+		}
+		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().
+				get(IBgpRouteService.class.getCanonicalName());
+
+		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 = "";
+
+		if (capability == null) {
+			// this is a prefix delete
+			Prefix p;
+			try {
+				p = new Prefix(prefix, Integer.valueOf(mask));
+			} catch (NumberFormatException e) {
+				reply = "[DELE: mask format is wrong]";
+				log.info(reply);
+				return reply + "\n";
+			} catch (UnknownHostException e1) {
+				reply = "[DELE: prefix format is wrong]";
+				log.info(reply);
+				return reply + "\n";
+			}
+
+			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);					
+				}
+			}
+
+			bgpRoute.prefixDeleted(node);
+			
+			reply =reply + "[DELE: " + prefix + "/" + mask + ":" + nextHop + "]";
+		}
+		else {
+			// clear the local rib: Ptree			
+			bgpRoute.clearPtree();
+			reply = "[DELE-capability: " + capability + "; The local Rib is cleared!]\n";
+
+			// to store the number in the top node of the Ptree	
+		}
+		
+		log.info(reply);
+		return reply + "\n";
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResourceSynch.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResourceSynch.java
new file mode 100644
index 0000000..543827d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResourceSynch.java
@@ -0,0 +1,71 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+
+import org.restlet.resource.Post;
+import org.restlet.resource.Delete;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+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/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java
new file mode 100644
index 0000000..669c385
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java
@@ -0,0 +1,25 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+public class BgpRouteWebRoutable implements RestletRoutable {
+	@Override
+	public Restlet getRestlet(Context context) {
+		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}/synch", BgpRouteResourceSynch.class);
+		router.attach("/{routerid}/{capability}", BgpRouteResource.class);
+		return router;
+	}
+	
+	@Override
+	public String basePath() {
+		return "/wm/bgp";
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/GatewayRouter.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/GatewayRouter.java
new file mode 100644
index 0000000..eaa3686
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/GatewayRouter.java
@@ -0,0 +1,46 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import net.floodlightcontroller.util.IPv4;
+import net.floodlightcontroller.util.MACAddress;
+import net.floodlightcontroller.util.SwitchPort;
+
+public class GatewayRouter {
+	private SwitchPort attachmentPoint;
+	private MACAddress routerMac;
+	private IPv4 routerIp;
+	
+	//For now, put in the IP and MAC of the SDN domain's router that this 
+	//gateway will be communicating with
+	private MACAddress sdnRouterMac;
+	private IPv4 sdnRouterIp;
+	
+	public GatewayRouter(SwitchPort attachmentPoint, MACAddress routerMac, 
+			IPv4 routerIp, MACAddress sdnRouterMac, IPv4 sdnRouterIp) {
+		this.attachmentPoint = attachmentPoint;
+		this.routerMac = routerMac;
+		this.routerIp = routerIp;
+		this.sdnRouterIp = sdnRouterIp;
+		this.sdnRouterMac = sdnRouterMac;
+	}
+
+	public SwitchPort getAttachmentPoint() {
+		return attachmentPoint;
+	}
+
+	public MACAddress getRouterMac() {
+		return routerMac;
+	}
+
+	public IPv4 getRouterIp() {
+		return routerIp;
+	}
+	
+	//TODO delete if not needed
+	public MACAddress getSdnRouterMac() {
+		return sdnRouterMac;
+	}
+	
+	public IPv4 getSdnRouterIp() {
+		return sdnRouterIp;
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java
new file mode 100644
index 0000000..c84a415
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java
@@ -0,0 +1,20 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+public interface IBgpRouteService extends IFloodlightService {
+
+	public Rib lookupRib(byte[] dest);
+
+	public Ptree getPtree();
+
+	public String getBGPdRestIp();
+
+	public String getRouterId();
+
+	public void clearPtree();
+	
+	//TODO This functionality should be provided by some sort of Ptree listener framework
+	public void prefixAdded(PtreeNode node);
+	public void prefixDeleted(PtreeNode node);
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
new file mode 100644
index 0000000..c3baa37
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
@@ -0,0 +1,34 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+public class Prefix {
+	public int masklen;
+	protected InetAddress address;
+
+	public Prefix(byte[] addr, int masklen) throws UnknownHostException {
+		//try {
+		address = InetAddress.getByAddress(addr);
+		//} catch (UnknownHostException e) {
+		//	System.out.println("InetAddress exception");
+		//	return;
+		//}
+		this.masklen = masklen;
+		//System.out.println(address.toString() + "/" + masklen);
+	}
+
+	public Prefix(String str, int masklen) throws UnknownHostException {
+		//try {
+		address = InetAddress.getByName(str);
+		//} catch (UnknownHostException e) {
+		//	System.out.println("InetAddress exception");
+		//	return;
+		//}
+		this.masklen = masklen;
+	}
+
+	public byte [] getAddress() {
+		return address.getAddress();
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java
new file mode 100644
index 0000000..6741a41
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java
@@ -0,0 +1,320 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+public class Ptree {
+	int maxKeyBits;
+	int maxKeyOctets;
+	int refCount;
+	PtreeNode top;
+	byte maskBits[] = { (byte)0x00, (byte)0x80, (byte)0xc0, (byte)0xe0, (byte)0xf0, (byte)0xf8, (byte)0xfc, (byte)0xfe, (byte)0xff };
+	
+	// Constructor.
+	Ptree(int max_key_bits) {
+		maxKeyBits = max_key_bits;
+		maxKeyOctets = bit_to_octet(max_key_bits); 
+		refCount = 0;
+	}
+	
+	public PtreeNode acquire(byte [] key) {
+		return acquire(key, maxKeyBits);
+	}
+	
+	public PtreeNode acquire(byte [] key, int key_bits) {
+		if (key_bits > maxKeyBits) {
+			return null;
+		}
+		
+		PtreeNode node = top;
+		PtreeNode match = null;
+		
+		while (node != null
+				&& node.keyBits <= key_bits
+				&& key_match(node.key, node.keyBits, key, key_bits) == true) {
+		    if (node.keyBits == key_bits) {
+				return addReference(node);
+			}
+
+			match = node;
+			
+			if (bit_check(key, node.keyBits) == true) {
+				node = node.right;
+			} else {
+				node = node.left;
+			}
+		}
+
+		PtreeNode add = null;
+		
+		if (node == null) {
+			add = new PtreeNode(key, key_bits, maxKeyOctets);
+			
+			if (match != null) {
+				node_link(match, add);
+			} else {
+				top = add;
+			}
+		} else {
+			add = node_common(node, key, key_bits);
+			if (add == null) {
+				return null;
+			}				
+			
+			if (match != null) {
+				node_link(match, add);
+			} else {
+				top = add;
+			}
+			node_link(add, node);
+			
+			if (add.keyBits != key_bits) {
+				match = add;
+				
+				add = new PtreeNode(key, key_bits, maxKeyOctets);
+				node_link(match, add);
+			}
+		}
+		
+		return addReference(add);
+	}
+
+	public PtreeNode lookup(byte [] key, int key_bits) {
+		if (key_bits > maxKeyBits) {
+			return null;
+		}
+		
+		PtreeNode node = top;
+		
+		while (node != null
+				&& node.keyBits <= key_bits
+				&& key_match(node.key, node.keyBits, key, key_bits) == true) {
+			if (node.keyBits == key_bits) {
+				return addReference(node);
+			}
+			
+			if (bit_check(key, node.keyBits) == true) {
+				node = node.right;
+			} else {
+				node = node.left;
+			}
+		}
+		return null;
+	}
+	
+	public PtreeNode match(byte [] key, int key_bits) {
+		if (key_bits > maxKeyBits) {
+			return null;
+		}
+		PtreeNode node = top;
+		PtreeNode matched = null;
+
+		if(node!=null)
+		
+		while (node != null
+				&& node.keyBits <= key_bits
+				&& key_match(node.key, node.keyBits, key, key_bits) == true) {
+			matched = node;
+			
+			if (bit_check(key, node.keyBits) == true) {
+				node = node.right;
+			} else {
+				node = node.left;
+			}
+		}
+		
+		if (matched != null) {
+			return addReference(matched);
+		}
+		
+		return null;
+	}
+	
+	public PtreeNode begin() {
+		if (top == null) {
+			return null;
+		}
+		return addReference(top);
+	}
+	
+	public PtreeNode next(PtreeNode node) {
+		PtreeNode next;
+		
+		if (node.left != null) {
+			next = node.left;
+			addReference(next);
+			delReference(node);
+			return next;
+		}
+		if (node.right != null) {
+			next = node.right;
+			addReference(next);
+			delReference(node);
+			return next;
+		}
+		
+		PtreeNode start = node;
+		while (node.parent != null) {
+			if (node.parent.left == node && node.parent.right != null) {
+				next = node.parent.right;
+				addReference(next);
+				delReference(start);
+				return next;
+			}
+			node = node.parent;
+		}
+		
+		delReference(start);
+		
+		return null;
+	}
+
+	static public int bit_to_octet(int key_bits) {
+		return Math.max((key_bits + 7) / 8, 1);
+	}
+
+	private PtreeNode addReference(PtreeNode node) {
+		node.refCount++;
+		return node;
+	}
+	
+	public void delReference(PtreeNode node) {
+		if (node.refCount > 0) {
+			node.refCount--;
+		}
+		if (node.refCount == 0) {
+			node_remove(node);
+		}
+	}
+	
+	private boolean key_match(byte [] key1, int key1_len, byte [] key2, int key2_len) {
+		int offset;
+		int shift;
+		
+		if (key1_len > key2_len) {
+			return false;
+		}
+		
+		offset = (Math.min(key1_len, key2_len)) / 8;
+		shift = (Math.min(key1_len, key2_len)) % 8;
+		
+		if (shift != 0) {
+			if ((maskBits[shift] & (key1[offset] ^ key2[offset])) != 0) {
+				return false;
+			}
+		}
+		
+		while (offset != 0) {
+			offset--;
+			if (key1[offset] != key2[offset]) {
+				return false;
+			}
+		}
+		return true;
+	}
+	
+	private boolean bit_check(byte [] key, int key_bits) {
+		int offset = key_bits / 8;
+		int shift = 7 - (key_bits % 8);
+		int bit = key[offset] & 0xff;
+
+		bit >>= shift;
+		
+		if ((bit & 1) == 1) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+	
+	private void node_link(PtreeNode node, PtreeNode add) {
+		boolean bit = bit_check(add.key, node.keyBits);
+		
+		if (bit == true) {
+			node.right = add;
+		} else {
+			node.left = add;
+		}
+		add.parent = node;
+	}
+	
+	@SuppressWarnings("unused")
+    private PtreeNode node_common(PtreeNode node, byte [] key, int key_bits) {
+		int i;
+		int limit = Math.min(node.keyBits, key_bits) / 8;
+
+		for (i = 0; i < limit; i++) {
+			if (node.key[i] != key[i]) {
+				break;
+			}
+		}
+		
+		int common_len = i * 8;
+		int boundary = 0;
+
+		if (common_len != key_bits) {
+			byte diff = (byte)(node.key[i] ^ key[i]);
+			byte mask = (byte)0x80;
+			int shift_mask = 0;
+			
+			while (common_len < key_bits && ((mask & diff) == 0)) {
+				boundary = 1;
+
+				shift_mask = (mask & 0xff);
+				shift_mask >>= 1;
+				mask = (byte)shift_mask;
+
+				common_len++;
+			}
+		}
+		
+		PtreeNode add = new PtreeNode(null, common_len, maxKeyOctets);
+		if (add == null)
+			return null;
+		
+		int j;
+		for (j = 0; j < i; j++)
+			add.key[j] = node.key[j];
+
+		if (boundary != 0)
+			add.key[j] = (byte)(node.key[j] & maskBits[add.keyBits % 8]);
+		
+		return add;
+	}
+	//add by linpp
+	private void clear() {
+	
+	}
+	
+	private void node_remove(PtreeNode node) {
+		PtreeNode child;
+		PtreeNode parent;
+		
+		if (node.left != null && node.right != null) {
+			return;
+		}
+		
+		if (node.left != null) {
+			child = node.left;
+		} else {
+			child = node.right;
+		}
+		
+		parent = node.parent;
+		
+		if (child != null) {
+			child.parent = parent;
+		}
+		
+		if (parent != null) {
+			if (parent.left == node) {
+				parent.left = child;
+			} else {
+				parent.right = child;
+			}
+		} else {
+			top = child;
+		}
+		
+		if (parent != null && parent.refCount == 0) {
+			node_remove(parent);
+		}
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/PtreeNode.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/PtreeNode.java
new file mode 100644
index 0000000..a4d6996
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/PtreeNode.java
@@ -0,0 +1,44 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PtreeNode {
+	public PtreeNode parent;
+	public PtreeNode left;
+	public PtreeNode right;
+	
+	public byte key[];
+	public int keyBits;
+	
+	public int refCount;
+	
+	public Rib rib;
+	protected static Logger log = LoggerFactory.getLogger(BgpRoute.class);
+	
+	PtreeNode(byte [] key, int key_bits, int max_key_octet) {
+		parent = null;
+		left = null;
+		right = null;
+		refCount = 0;
+		rib = null;
+		this.key = new byte[max_key_octet];
+		this.keyBits = key_bits;
+		log.debug("inside Ptreenode constructor key {} bits {}", key, key_bits);
+		
+		int octet = Ptree.bit_to_octet(key_bits);
+		for (int i = 0; i < max_key_octet; i++) {
+			if (i < octet) {
+				if (key != null) {
+				    log.debug(octet + ": filling key[{}] {}", i, key[i]);
+				    this.key[i] = key[i];
+				} else {
+				    log.debug("no filling, null key", i);
+				}
+			} else {
+			    log.debug("filling key {} as 0", i);
+				this.key[i] = 0;
+			}
+		}
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/RestClient.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RestClient.java
new file mode 100644
index 0000000..f6f1a03
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RestClient.java
@@ -0,0 +1,104 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+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 org.apache.commons.httpclient.ConnectTimeoutException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class RestClient {
+	protected static Logger log = LoggerFactory.getLogger(RestClient.class);
+
+	public static String get(String str) {
+		StringBuilder response = new StringBuilder();
+
+		try {
+
+			URL url = new URL(str);
+			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+			conn.setConnectTimeout(2 * 1000); //2 seconds
+			conn.setRequestMethod("GET");
+			conn.setRequestProperty("Accept", "application/json");
+
+			if (conn.getResponseCode() != 200) {
+				throw new RuntimeException("Failed : HTTP error code : "
+						+ conn.getResponseCode());
+			}
+
+			if (!conn.getContentType().equals("application/json")){	
+				log.warn("The content received from {} is not json", str);
+			}		
+
+			BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); 
+			String line;
+			while ((line = br.readLine()) != null) {
+				response.append(line);
+			}
+			
+			br.close();
+			conn.disconnect();
+			
+		} catch (MalformedURLException e) {
+			log.error("Malformed URL for GET request", e);
+		} catch (ConnectTimeoutException e) {
+			log.warn("Couldn't connect remote REST server");
+		} catch (IOException e) {
+			log.warn("Couldn't connect remote REST server");
+		}
+		
+		return response.toString();
+	}
+
+	public static void post (String str) {
+
+		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) {
+			log.error("Malformed URL for GET request", e);
+		} catch (IOException e) {
+			log.warn("Couldn't connect remote REST server");
+		}
+	}
+
+
+	public static void delete (String str) {
+
+		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) {
+			log.error("Malformed URL for GET request", e);
+		} catch (IOException e) {
+			log.warn("Couldn't connect remote REST server");
+		}
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Rib.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Rib.java
new file mode 100644
index 0000000..dc5f71d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Rib.java
@@ -0,0 +1,46 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+public class Rib {
+	protected InetAddress routerId;
+	protected InetAddress nextHop;
+	protected int masklen;
+//	protected int distance;
+	
+	Rib(InetAddress router_id, InetAddress nexthop, int masklen) {
+		this.routerId = router_id;
+		this.nextHop = nexthop;
+		this.masklen = masklen;
+//		this.distance = distance;
+	}
+	
+	Rib(String router_id, String nexthop, int masklen) {
+		try {
+			this.routerId = InetAddress.getByName(router_id);
+		} catch (UnknownHostException e) {
+			System.out.println("InetAddress exception");
+		}
+		try {
+			this.nextHop = InetAddress.getByName(nexthop);
+		} catch (UnknownHostException e) {
+			System.out.println("InetAddress exception");
+		}
+		this.masklen = masklen;
+	}
+	
+	public InetAddress getNextHop() {
+	    return nextHop;
+	}
+	
+	public int getMasklen(){
+	    return masklen;
+	}
+	
+	public boolean equals(Rib r) {
+				
+		return this.routerId.equals(r.routerId) && this.nextHop.equals(r.nextHop)  && this.masklen == r.masklen;
+		
+	}
+}