blob: 6d506020c57a6fbc65c0a3c28f58413695d240c3 [file] [log] [blame]
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -08001package net.floodlightcontroller.routing;
2
3import java.util.ArrayList;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -08004import java.util.Collection;
5import java.util.HashMap;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -08006import java.util.Iterator;
7import java.util.List;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -08008import java.util.Map;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -08009
10import net.floodlightcontroller.core.internal.SwitchStorageImpl;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080011import net.floodlightcontroller.core.module.FloodlightModuleContext;
12import net.floodlightcontroller.core.module.FloodlightModuleException;
13import net.floodlightcontroller.core.module.IFloodlightModule;
14import net.floodlightcontroller.core.module.IFloodlightService;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080015import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
16import net.floodlightcontroller.topology.NodePortTuple;
17
18import org.openflow.util.HexString;
19
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080020import com.thinkaurelius.titan.core.TitanGraph;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080021import com.tinkerpop.blueprints.Vertex;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080022
23import javax.script.ScriptContext;
24import javax.script.ScriptEngine;
25import javax.script.ScriptException;
26import com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
27
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080028import org.slf4j.Logger;
29import org.slf4j.LoggerFactory;
30
31public class TopoRouteService implements IFloodlightModule, ITopoRouteService {
32
33 /** The logger. */
34 private static Logger logger =
35 LoggerFactory.getLogger(TopoRouteService.class);
36
37 @Override
38 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
39 Collection<Class<? extends IFloodlightService>> l =
40 new ArrayList<Class<? extends IFloodlightService>>();
41 l.add(ITopoRouteService.class);
42 return l;
43 }
44
45 @Override
46 public Map<Class<? extends IFloodlightService>, IFloodlightService>
47 getServiceImpls() {
48 Map<Class<? extends IFloodlightService>,
49 IFloodlightService> m =
50 new HashMap<Class<? extends IFloodlightService>,
51 IFloodlightService>();
52 m.put(ITopoRouteService.class, this);
53 return m;
54 }
55
56 @Override
57 public Collection<Class<? extends IFloodlightService>>
58 getModuleDependencies() {
59 Collection<Class<? extends IFloodlightService>> l =
60 new ArrayList<Class<? extends IFloodlightService>>();
61 // TODO: Add the appropriate dependencies
62 // l.add(IRestApiService.class);
63 return l;
64 }
65
66 @Override
67 public void init(FloodlightModuleContext context)
68 throws FloodlightModuleException {
69 // TODO: Add the appropriate initialization
70 }
71
72 @Override
73 public void startUp(FloodlightModuleContext context) {
74 // TODO: Add the approprate setup
75 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080076
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -080077 ThreadLocal<SwitchStorageImpl> store = new ThreadLocal<SwitchStorageImpl>() {
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080078 @Override
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -080079 protected SwitchStorageImpl initialValue() {
80 SwitchStorageImpl swStore = new SwitchStorageImpl();
81 // NOTE: This is the file path from global properties
82 swStore.init("/tmp/cassandra.titan");
83 return swStore;
84 }
85 };
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080086
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -080087 SwitchStorageImpl swStore = store.get();
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080088
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -080089 @Override
90 public List<NodePortTuple> getShortestPath(NodePortTuple src,
91 NodePortTuple dest) {
92 List<NodePortTuple> result_list = new ArrayList<NodePortTuple>();
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080093
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -080094 TitanGraph titanGraph = swStore.graph;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080095
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -080096 String dpid_src = HexString.toHexString(src.getNodeId());
97 String dpid_dest = HexString.toHexString(dest.getNodeId());
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080098
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -080099 //
100 // Implement the Shortest Path between two vertices by using
101 // the following Gremlin CLI code:
102 // 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}
103 // The equivalent code used here is:
104 // results = []; v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path().fill(results)
105 //
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800106
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800107 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 Radoslavov2f686c52013-02-13 11:27:13 -0800108
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800109 // Get the source vertex
110 Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
111 if (! iter.hasNext())
112 return null; // Source vertex not found
113 Vertex v_src = iter.next();
Pavlin Radoslavov2f686c52013-02-13 11:27:13 -0800114
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800115 // Get the destination vertex
116 iter = titanGraph.getVertices("dpid", dpid_dest).iterator();
117 if (! iter.hasNext())
118 return null; // Destination vertex not found
119 Vertex v_dest = iter.next();
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800120
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800121 //
122 // Test whether we are computing a path from/to the same DPID.
123 // If "yes", then just list the "src" and "dest" in the return
124 // result.
125 // NOTE: The return value will change in the future to return
126 // a single hop/entry instead of two. Currently, we need
127 // both entries to capture the source and destination ports.
128 //
129 if (dpid_src.equals(dpid_dest)) {
130 result_list.add(new NodePortTuple(src));
131 result_list.add(new NodePortTuple(dest));
132 return result_list;
133 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800134
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800135 //
136 // Implement the Gremlin script and run it
137 //
138 ScriptEngine engine = new GremlinGroovyScriptEngine();
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800139
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800140 ArrayList<ArrayList<Vertex>> results = new ArrayList<ArrayList<Vertex>>();
141 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("g", titanGraph);
142 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_src", v_src);
143 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_dest", v_dest);
144 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("results", results);
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800145
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800146 try {
147 engine.eval(gremlin);
148 } catch (ScriptException e) {
149 System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800150 return null;
151 }
152
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800153 //
154 // Loop through the result and return the list
155 // of <dpid, port> tuples.
156 //
157 long nodeId = 0;
158 short portId = 0;
159 for (ArrayList<Vertex> lv : results) {
160 int idx = 0;
161 for (Vertex v: lv) {
162 String type = v.getProperty("type").toString();
163 System.out.println("type: " + type);
164 if (type.equals("port")) {
165 String number = v.getProperty("number").toString();
166 System.out.println("number: " + number);
167
168 Object obj = v.getProperty("number");
169 // String class_str = obj.getClass().toString();
170 if (obj instanceof Short) {
171 portId = (Short)obj;
172 } else if (obj instanceof Integer) {
173 Integer int_nodeId = (Integer)obj;
174 portId = int_nodeId.shortValue();
175 // int int_nodeId = (Integer)obj;
176 // portId = (short)int_nodeId.;
177 }
178 } else if (type.equals("switch")) {
179 String dpid = v.getProperty("dpid").toString();
180 nodeId = HexString.toLong(dpid);
181
182 System.out.println("dpid: " + dpid);
183 }
184 if (idx == 0) {
185 idx++;
186 continue;
187 }
188 int mod = (idx - 1) % 3;
189 if ((mod == 0) || (mod == 2)) {
190 result_list.add(new NodePortTuple(nodeId, portId));
191 }
192 idx++;
193 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800194 }
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800195 if (result_list.size() > 0)
196 return result_list;
197
198 return null;
199 }
200
201 @Override
202 public Boolean routeExists(NodePortTuple src, NodePortTuple dest) {
203 List<NodePortTuple> route = getShortestPath(src, dest);
204 if (route != null)
205 return true;
206 return false;
207 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800208}