blob: ba3c2efe0602e0aef9427b19583253b7c2856de0 [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
77 ThreadLocal<SwitchStorageImpl> store = new ThreadLocal<SwitchStorageImpl>() {
78 @Override
79 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 };
86
87 SwitchStorageImpl swStore = store.get();
88
89 @Override
Pankaj Berde1cde50b2013-02-19 20:16:06 -080090 public List<NodePortTuple> getShortestPath(NodePortTuple src,
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080091 NodePortTuple dest) {
92 List<NodePortTuple> result_list = new ArrayList<NodePortTuple>();
93
94 TitanGraph titanGraph = swStore.graph;
95
96 String dpid_src = HexString.toHexString(src.getNodeId());
97 String dpid_dest = HexString.toHexString(dest.getNodeId());
98
99 //
100 // Implement the Shortest Path between two vertices by using
Pavlin Radoslavov50951972013-02-13 10:14:08 -0800101 // 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)
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800105 //
106
Ubuntud8577652013-02-08 18:54:46 +0000107 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 -0800108
109 // 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();
114
115 // 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 Radoslavov2f686c52013-02-13 11:27:13 -0800120
121 //
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.
Pavlin Radoslavov4d5dfc52013-02-13 11:30:32 -0800125 // 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.
Pavlin Radoslavov2f686c52013-02-13 11:27:13 -0800128 //
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 }
134
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800135 //
136 // Implement the Gremlin script and run it
137 //
138 ScriptEngine engine = new GremlinGroovyScriptEngine();
139
140 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);
145
146 try {
147 engine.eval(gremlin);
148 } catch (ScriptException e) {
149 System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
150 return null;
151 }
152
153 //
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 }
194 }
195 if (result_list.size() > 0)
196 return result_list;
197
198 return null;
199 }
200
201 @Override
Pankaj Berde1cde50b2013-02-19 20:16:06 -0800202 public Boolean routeExists(NodePortTuple src, NodePortTuple dest) {
203 List<NodePortTuple> route = getShortestPath(src, dest);
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800204 if (route != null)
205 return true;
206 return false;
207 }
208}