blob: 2c50d29d73fac5ec938f8ddba73ca4677cbe8dea [file] [log] [blame]
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -08001package net.floodlightcontroller.routing;
2
3import java.util.ArrayList;
4import java.util.Iterator;
5import java.util.List;
6
7import net.floodlightcontroller.core.internal.SwitchStorageImpl;
8import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
9import net.floodlightcontroller.topology.NodePortTuple;
10
11import org.openflow.util.HexString;
12
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080013import com.thinkaurelius.titan.core.TitanGraph;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080014import com.tinkerpop.blueprints.Vertex;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080015
16import javax.script.ScriptContext;
17import javax.script.ScriptEngine;
18import javax.script.ScriptException;
19import com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
20
21public class TopoRouteService implements ITopoRouteService {
22
23 ThreadLocal<SwitchStorageImpl> store = new ThreadLocal<SwitchStorageImpl>() {
24 @Override
25 protected SwitchStorageImpl initialValue() {
26 SwitchStorageImpl swStore = new SwitchStorageImpl();
27 // NOTE: This is the file path from global properties
28 swStore.init("/tmp/cassandra.titan");
29 return swStore;
30 }
31 };
32
33 SwitchStorageImpl swStore = store.get();
34
35 @Override
Pankaj Berde1cde50b2013-02-19 20:16:06 -080036 public List<NodePortTuple> getShortestPath(NodePortTuple src,
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080037 NodePortTuple dest) {
38 List<NodePortTuple> result_list = new ArrayList<NodePortTuple>();
39
40 TitanGraph titanGraph = swStore.graph;
41
42 String dpid_src = HexString.toHexString(src.getNodeId());
43 String dpid_dest = HexString.toHexString(dest.getNodeId());
44
45 //
46 // Implement the Shortest Path between two vertices by using
Pavlin Radoslavov50951972013-02-13 10:14:08 -080047 // the following Gremlin CLI code:
48 // v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path(){it.dpid}{it.number}{it.number}
49 // The equivalent code used here is:
50 // results = []; v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path().fill(results)
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080051 //
52
Ubuntud8577652013-02-08 18:54:46 +000053 String gremlin = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid}.path().fill(results)";
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080054
55 // Get the source vertex
56 Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
57 if (! iter.hasNext())
58 return null; // Source vertex not found
59 Vertex v_src = iter.next();
60
61 // Get the destination vertex
62 iter = titanGraph.getVertices("dpid", dpid_dest).iterator();
63 if (! iter.hasNext())
64 return null; // Destination vertex not found
65 Vertex v_dest = iter.next();
Pavlin Radoslavov2f686c52013-02-13 11:27:13 -080066
67 //
68 // Test whether we are computing a path from/to the same DPID.
69 // If "yes", then just list the "src" and "dest" in the return
70 // result.
Pavlin Radoslavov4d5dfc52013-02-13 11:30:32 -080071 // NOTE: The return value will change in the future to return
72 // a single hop/entry instead of two. Currently, we need
73 // both entries to capture the source and destination ports.
Pavlin Radoslavov2f686c52013-02-13 11:27:13 -080074 //
75 if (dpid_src.equals(dpid_dest)) {
76 result_list.add(new NodePortTuple(src));
77 result_list.add(new NodePortTuple(dest));
78 return result_list;
79 }
80
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080081 //
82 // Implement the Gremlin script and run it
83 //
84 ScriptEngine engine = new GremlinGroovyScriptEngine();
85
86 ArrayList<ArrayList<Vertex>> results = new ArrayList<ArrayList<Vertex>>();
87 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("g", titanGraph);
88 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_src", v_src);
89 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_dest", v_dest);
90 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("results", results);
91
92 try {
93 engine.eval(gremlin);
94 } catch (ScriptException e) {
95 System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
96 return null;
97 }
98
99 //
100 // Loop through the result and return the list
101 // of <dpid, port> tuples.
102 //
103 long nodeId = 0;
104 short portId = 0;
105 for (ArrayList<Vertex> lv : results) {
106 int idx = 0;
107 for (Vertex v: lv) {
108 String type = v.getProperty("type").toString();
109 System.out.println("type: " + type);
110 if (type.equals("port")) {
111 String number = v.getProperty("number").toString();
112 System.out.println("number: " + number);
113
114 Object obj = v.getProperty("number");
115 // String class_str = obj.getClass().toString();
116 if (obj instanceof Short) {
117 portId = (Short)obj;
118 } else if (obj instanceof Integer) {
119 Integer int_nodeId = (Integer)obj;
120 portId = int_nodeId.shortValue();
121 // int int_nodeId = (Integer)obj;
122 // portId = (short)int_nodeId.;
123 }
124 } else if (type.equals("switch")) {
125 String dpid = v.getProperty("dpid").toString();
126 nodeId = HexString.toLong(dpid);
127
128 System.out.println("dpid: " + dpid);
129 }
130 if (idx == 0) {
131 idx++;
132 continue;
133 }
134 int mod = (idx - 1) % 3;
135 if ((mod == 0) || (mod == 2)) {
136 result_list.add(new NodePortTuple(nodeId, portId));
137 }
138 idx++;
139 }
140 }
141 if (result_list.size() > 0)
142 return result_list;
143
144 return null;
145 }
146
147 @Override
Pankaj Berde1cde50b2013-02-19 20:16:06 -0800148 public Boolean routeExists(NodePortTuple src, NodePortTuple dest) {
149 List<NodePortTuple> route = getShortestPath(src, dest);
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800150 if (route != null)
151 return true;
152 return false;
153 }
154}