blob: bc82bc0583edd5844a65bbe45b10af56f6f84f3f [file] [log] [blame]
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -07001package net.onrc.onos.ofcontroller.topology;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -08002
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -07003import java.util.ArrayList;
4import java.util.Collection;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -08005import java.util.HashMap;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -08006import java.util.Map;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -08007
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -07008import net.floodlightcontroller.core.IFloodlightProviderService;
9import net.floodlightcontroller.core.module.FloodlightModuleContext;
10import net.floodlightcontroller.core.module.FloodlightModuleException;
11import net.floodlightcontroller.core.module.IFloodlightModule;
12import net.floodlightcontroller.core.module.IFloodlightService;
13
14import net.onrc.onos.datagrid.IDatagridService;
yoshitomob292c622013-11-23 14:35:58 -080015import net.onrc.onos.graph.DBOperation;
16import net.onrc.onos.graph.GraphDBManager;
yoshif7424e42013-11-25 22:07:40 -080017import net.onrc.onos.graph.GraphDBOperation;
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070018import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070019import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070020import net.onrc.onos.ofcontroller.util.FlowEntry;
21import net.onrc.onos.ofcontroller.util.FlowPath;
22import net.onrc.onos.ofcontroller.util.Port;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070023import net.onrc.onos.ofcontroller.util.SwitchPort;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080024
Pankaj Berde15193092013-03-21 17:30:14 -070025import org.slf4j.Logger;
26import org.slf4j.LoggerFactory;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080027
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -070028/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070029 * A class for obtaining Topology Snapshot
30 * and PathComputation.
31 *
32 * TODO: PathComputation part should be refactored out to separate class.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070033 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070034public class TopologyManager implements IFloodlightModule,
35 ITopologyNetService {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070036 private final static Logger log = LoggerFactory.getLogger(TopologyManager.class);
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070037 protected IFloodlightProviderService floodlightProvider;
38
yoshif7424e42013-11-25 22:07:40 -080039 protected static final String DBConfigFile = "dbconf";
40 protected static final String GraphDBStore = "graph_db_store";
41
yoshitomob292c622013-11-23 14:35:58 -080042 protected DBOperation dbHandler;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080043
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070044
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070045 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070046 * Default constructor.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070047 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070048 public TopologyManager() {
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080049 }
50
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070051 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070052 * Constructor for given database configuration file.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070053 *
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070054 * @param config the database configuration file to use for
55 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070056 */
yoshif7424e42013-11-25 22:07:40 -080057 public TopologyManager(FloodlightModuleContext context) {
58 Map<String, String> configMap = context.getConfigParams(this);
59 String conf = configMap.get(DBConfigFile);
60 String dbStore = configMap.get(GraphDBStore);
61 this.init(dbStore,conf);
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080062 }
63
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070064 /**
Pavlin Radoslavov0367d352013-10-19 11:04:43 -070065 * Constructor for a given database operation handler.
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070066 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070067 * @param dbHandler the database operation handler to use for the
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070068 * initialization.
69 */
yoshitomob292c622013-11-23 14:35:58 -080070 public TopologyManager(DBOperation dbHandler) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070071 this.dbHandler = dbHandler;
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070072 }
73
74 /**
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070075 * Init the module.
yoshitomob292c622013-11-23 14:35:58 -080076 * @param
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070077 * @param config the database configuration file to use for
78 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070079 */
yoshitomob292c622013-11-23 14:35:58 -080080 public void init(final String dbStore, String config) {
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070081 try {
yoshid38cd312013-12-02 19:54:44 -080082 dbHandler = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloudconf");
83 //dbHandler = GraphDBManager.getDBOperation(dbStore, config);
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070084 } catch (Exception e) {
85 log.error(e.getMessage());
86 }
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080087 }
88
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070089 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070090 * Shutdown the Topology Manager operation.
91 */
92 public void finalize() {
93 close();
94 }
95
96 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070097 * Close the service. It will close the corresponding database connection.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070098 */
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070099 public void close() {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700100 dbHandler.close();
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -0800101 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800102
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -0700103 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700104 * Get the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -0700105 *
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700106 * @return the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -0700107 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700108 @Override
109 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
110 Collection<Class<? extends IFloodlightService>> l =
111 new ArrayList<Class<? extends IFloodlightService>>();
112 l.add(ITopologyNetService.class);
113 return l;
114 }
115
116 /**
117 * Get the collection of implemented services.
118 *
119 * @return the collection of implemented services.
120 */
121 @Override
122 public Map<Class<? extends IFloodlightService>, IFloodlightService>
123 getServiceImpls() {
124 Map<Class<? extends IFloodlightService>,
125 IFloodlightService> m =
126 new HashMap<Class<? extends IFloodlightService>,
127 IFloodlightService>();
128 m.put(ITopologyNetService.class, this);
129 return m;
130 }
131
132 /**
133 * Get the collection of modules this module depends on.
134 *
135 * @return the collection of modules this module depends on.
136 */
137 @Override
138 public Collection<Class<? extends IFloodlightService>>
139 getModuleDependencies() {
140 Collection<Class<? extends IFloodlightService>> l =
141 new ArrayList<Class<? extends IFloodlightService>>();
142 l.add(IFloodlightProviderService.class);
143 l.add(INetworkGraphService.class);
144 l.add(IDatagridService.class);
145 return l;
146 }
147
148 /**
149 * Initialize the module.
150 *
151 * @param context the module context to use for the initialization.
152 */
153 @Override
154 public void init(FloodlightModuleContext context)
155 throws FloodlightModuleException {
156 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
yoshif7424e42013-11-25 22:07:40 -0800157 Map<String, String> configMap = context.getConfigParams(this);
158 String conf = configMap.get(DBConfigFile);
159 String dbStore = configMap.get(GraphDBStore);
160 this.init(dbStore, conf);
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700161 }
162
163 /**
164 * Startup module operation.
165 *
166 * @param context the module context to use for the startup.
167 */
168 @Override
169 public void startUp(FloodlightModuleContext context) {
170
Pavlin Radoslavovcec899a2013-06-27 15:47:50 -0700171 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800172
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700173 /**
174 * Fetch the Switch and Ports info from the Titan Graph
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000175 * and return it for fast access during the shortest path
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700176 * computation.
177 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700178 * After fetching the state, method @ref getTopologyShortestPath()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700179 * can be used for fast shortest path computation.
180 *
181 * Note: There is certain cost to fetch the state, hence it should
182 * be used only when there is a large number of shortest path
183 * computations that need to be done on the same topology.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700184 * Typically, a single call to @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700185 * should be followed by a large number of calls to
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700186 * method @ref getTopologyShortestPath().
187 * After the last @ref getTopologyShortestPath() call,
188 * method @ref dropTopology() should be used to release
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700189 * the internal state that is not needed anymore:
190 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700191 * Topology topology = topologyManager.newDatabaseTopology();
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700192 * for (int i = 0; i < 10000; i++) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700193 * dataPath = topologyManager.getTopologyShortestPath(topology, ...);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700194 * ...
195 * }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700196 * topologyManager.dropTopology(shortestPathTopo);
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000197 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700198 * @return the allocated topology handler.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700199 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700200 public Topology newDatabaseTopology() {
201 Topology topology = new Topology();
202 topology.readFromDatabase(dbHandler);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700203
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700204 return topology;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700205 }
206
207 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700208 * Release the topology that was populated by
209 * method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700210 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700211 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700212 * for additional information and usage.
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000213 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700214 * @param topology the topology to release.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700215 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700216 public void dropTopology(Topology topology) {
217 topology = null;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700218 }
219
220 /**
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700221 * Compute the network path for a Flow.
222 *
223 * @param topology the topology handler to use.
224 * @param flowPath the Flow to compute the network path for.
225 * @return the data path with the computed path if found, otherwise null.
226 */
227 public static DataPath computeNetworkPath(Topology topology,
228 FlowPath flowPath) {
229 //
230 // Compute the network path based on the desired Flow Path type
231 //
232 switch (flowPath.flowPathType()) {
233 case FP_TYPE_SHORTEST_PATH: {
234 SwitchPort src = flowPath.dataPath().srcPort();
235 SwitchPort dest = flowPath.dataPath().dstPort();
236 return ShortestPath.getTopologyShortestPath(topology, src, dest);
237 }
238 case FP_TYPE_EXPLICIT_PATH:
239 return flowPath.dataPath();
240 }
241
242 return null;
243 }
244
245 /**
246 * Test whether two Flow Entries represent same points in a data path.
247 *
248 * NOTE: Two Flow Entries represent same points in a data path if
249 * the Switch DPID, incoming port and outgoing port are same.
250 *
251 * NOTE: This method is specialized for shortest-path unicast paths,
252 * and probably should be moved somewhere else.
253 *
254 * @param oldFlowEntry the first Flow Entry to compare.
255 * @param newFlowEntry the second Flow Entry to compare.
256 * @return true if the two Flow Entries represent same points in a
257 * data path, otherwise false.
258 */
259 public static boolean isSameFlowEntryDataPath(FlowEntry oldFlowEntry,
260 FlowEntry newFlowEntry) {
261 // Test the DPID
262 if (oldFlowEntry.dpid().value() != newFlowEntry.dpid().value())
263 return false;
264
265 // Test the inPort
266 do {
267 Port oldPort = oldFlowEntry.inPort();
268 Port newPort = newFlowEntry.inPort();
269 if ((oldPort != null) && (newPort != null) &&
270 (oldPort.value() == newPort.value())) {
271 break;
272 }
273 if ((oldPort == null) && (newPort == null))
274 break;
275 return false; // inPort is different
276 } while (false);
277
278 // Test the outPort
279 do {
280 Port oldPort = oldFlowEntry.outPort();
281 Port newPort = newFlowEntry.outPort();
282 if ((oldPort != null) && (newPort != null) &&
283 (oldPort.value() == newPort.value())) {
284 break;
285 }
286 if ((oldPort == null) && (newPort == null))
287 break;
288 return false; // outPort is different
289 } while (false);
290
291 return true;
292 }
293
294 /**
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700295 * Get the shortest path from a source to a destination by
296 * using the pre-populated local topology state prepared
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700297 * by method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700298 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700299 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700300 * for additional information and usage.
301 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700302 * @param topology the topology handler to use.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700303 * @param src the source in the shortest path computation.
304 * @param dest the destination in the shortest path computation.
305 * @return the data path with the computed shortest path if
306 * found, otherwise null.
307 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700308 public DataPath getTopologyShortestPath(Topology topology,
309 SwitchPort src, SwitchPort dest) {
310 return ShortestPath.getTopologyShortestPath(topology, src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700311 }
312
313 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700314 * Get the shortest path from a source to a destination by using
315 * the underlying database.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700316 *
317 * @param src the source in the shortest path computation.
318 * @param dest the destination in the shortest path computation.
319 * @return the data path with the computed shortest path if
320 * found, otherwise null.
321 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800322 @Override
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700323 public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
324 return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800325 }
326
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700327 /**
328 * Test whether a route exists from a source to a destination.
329 *
330 * @param src the source node for the test.
331 * @param dest the destination node for the test.
332 * @return true if a route exists, otherwise false.
333 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800334 @Override
Pavlin Radoslavovf83aa442013-02-26 14:09:01 -0800335 public Boolean routeExists(SwitchPort src, SwitchPort dest) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700336 DataPath dataPath = getDatabaseShortestPath(src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700337 return (dataPath != null);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800338 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800339}