blob: d605fc19354af2841e50208aaf15184a08a2b8fd [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 {
yoshitomob292c622013-11-23 14:35:58 -080082 dbHandler = GraphDBManager.getDBOperation(dbStore, config);
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070083 } catch (Exception e) {
84 log.error(e.getMessage());
85 }
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080086 }
87
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070088 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070089 * Shutdown the Topology Manager operation.
90 */
91 public void finalize() {
92 close();
93 }
94
95 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070096 * Close the service. It will close the corresponding database connection.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070097 */
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070098 public void close() {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070099 dbHandler.close();
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -0800100 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800101
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -0700102 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700103 * Get the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -0700104 *
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700105 * @return the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -0700106 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700107 @Override
108 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
109 Collection<Class<? extends IFloodlightService>> l =
110 new ArrayList<Class<? extends IFloodlightService>>();
111 l.add(ITopologyNetService.class);
112 return l;
113 }
114
115 /**
116 * Get the collection of implemented services.
117 *
118 * @return the collection of implemented services.
119 */
120 @Override
121 public Map<Class<? extends IFloodlightService>, IFloodlightService>
122 getServiceImpls() {
123 Map<Class<? extends IFloodlightService>,
124 IFloodlightService> m =
125 new HashMap<Class<? extends IFloodlightService>,
126 IFloodlightService>();
127 m.put(ITopologyNetService.class, this);
128 return m;
129 }
130
131 /**
132 * Get the collection of modules this module depends on.
133 *
134 * @return the collection of modules this module depends on.
135 */
136 @Override
137 public Collection<Class<? extends IFloodlightService>>
138 getModuleDependencies() {
139 Collection<Class<? extends IFloodlightService>> l =
140 new ArrayList<Class<? extends IFloodlightService>>();
141 l.add(IFloodlightProviderService.class);
142 l.add(INetworkGraphService.class);
143 l.add(IDatagridService.class);
144 return l;
145 }
146
147 /**
148 * Initialize the module.
149 *
150 * @param context the module context to use for the initialization.
151 */
152 @Override
153 public void init(FloodlightModuleContext context)
154 throws FloodlightModuleException {
155 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
yoshif7424e42013-11-25 22:07:40 -0800156 Map<String, String> configMap = context.getConfigParams(this);
157 String conf = configMap.get(DBConfigFile);
158 String dbStore = configMap.get(GraphDBStore);
159 this.init(dbStore, conf);
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700160 }
161
162 /**
163 * Startup module operation.
164 *
165 * @param context the module context to use for the startup.
166 */
167 @Override
168 public void startUp(FloodlightModuleContext context) {
169
Pavlin Radoslavovcec899a2013-06-27 15:47:50 -0700170 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800171
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700172 /**
173 * Fetch the Switch and Ports info from the Titan Graph
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000174 * and return it for fast access during the shortest path
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700175 * computation.
176 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700177 * After fetching the state, method @ref getTopologyShortestPath()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700178 * can be used for fast shortest path computation.
179 *
180 * Note: There is certain cost to fetch the state, hence it should
181 * be used only when there is a large number of shortest path
182 * computations that need to be done on the same topology.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700183 * Typically, a single call to @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700184 * should be followed by a large number of calls to
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700185 * method @ref getTopologyShortestPath().
186 * After the last @ref getTopologyShortestPath() call,
187 * method @ref dropTopology() should be used to release
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700188 * the internal state that is not needed anymore:
189 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700190 * Topology topology = topologyManager.newDatabaseTopology();
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700191 * for (int i = 0; i < 10000; i++) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700192 * dataPath = topologyManager.getTopologyShortestPath(topology, ...);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700193 * ...
194 * }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700195 * topologyManager.dropTopology(shortestPathTopo);
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000196 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700197 * @return the allocated topology handler.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700198 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700199 public Topology newDatabaseTopology() {
200 Topology topology = new Topology();
201 topology.readFromDatabase(dbHandler);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700202
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700203 return topology;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700204 }
205
206 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700207 * Release the topology that was populated by
208 * method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700209 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700210 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700211 * for additional information and usage.
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000212 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700213 * @param topology the topology to release.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700214 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700215 public void dropTopology(Topology topology) {
216 topology = null;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700217 }
218
219 /**
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700220 * Compute the network path for a Flow.
221 *
222 * @param topology the topology handler to use.
223 * @param flowPath the Flow to compute the network path for.
224 * @return the data path with the computed path if found, otherwise null.
225 */
226 public static DataPath computeNetworkPath(Topology topology,
227 FlowPath flowPath) {
228 //
229 // Compute the network path based on the desired Flow Path type
230 //
231 switch (flowPath.flowPathType()) {
232 case FP_TYPE_SHORTEST_PATH: {
233 SwitchPort src = flowPath.dataPath().srcPort();
234 SwitchPort dest = flowPath.dataPath().dstPort();
235 return ShortestPath.getTopologyShortestPath(topology, src, dest);
236 }
237 case FP_TYPE_EXPLICIT_PATH:
238 return flowPath.dataPath();
239 }
240
241 return null;
242 }
243
244 /**
245 * Test whether two Flow Entries represent same points in a data path.
246 *
247 * NOTE: Two Flow Entries represent same points in a data path if
248 * the Switch DPID, incoming port and outgoing port are same.
249 *
250 * NOTE: This method is specialized for shortest-path unicast paths,
251 * and probably should be moved somewhere else.
252 *
253 * @param oldFlowEntry the first Flow Entry to compare.
254 * @param newFlowEntry the second Flow Entry to compare.
255 * @return true if the two Flow Entries represent same points in a
256 * data path, otherwise false.
257 */
258 public static boolean isSameFlowEntryDataPath(FlowEntry oldFlowEntry,
259 FlowEntry newFlowEntry) {
260 // Test the DPID
261 if (oldFlowEntry.dpid().value() != newFlowEntry.dpid().value())
262 return false;
263
264 // Test the inPort
265 do {
266 Port oldPort = oldFlowEntry.inPort();
267 Port newPort = newFlowEntry.inPort();
268 if ((oldPort != null) && (newPort != null) &&
269 (oldPort.value() == newPort.value())) {
270 break;
271 }
272 if ((oldPort == null) && (newPort == null))
273 break;
274 return false; // inPort is different
275 } while (false);
276
277 // Test the outPort
278 do {
279 Port oldPort = oldFlowEntry.outPort();
280 Port newPort = newFlowEntry.outPort();
281 if ((oldPort != null) && (newPort != null) &&
282 (oldPort.value() == newPort.value())) {
283 break;
284 }
285 if ((oldPort == null) && (newPort == null))
286 break;
287 return false; // outPort is different
288 } while (false);
289
290 return true;
291 }
292
293 /**
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700294 * Get the shortest path from a source to a destination by
295 * using the pre-populated local topology state prepared
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700296 * by method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700297 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700298 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700299 * for additional information and usage.
300 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700301 * @param topology the topology handler to use.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700302 * @param src the source in the shortest path computation.
303 * @param dest the destination in the shortest path computation.
304 * @return the data path with the computed shortest path if
305 * found, otherwise null.
306 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700307 public DataPath getTopologyShortestPath(Topology topology,
308 SwitchPort src, SwitchPort dest) {
309 return ShortestPath.getTopologyShortestPath(topology, src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700310 }
311
312 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700313 * Get the shortest path from a source to a destination by using
314 * the underlying database.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700315 *
316 * @param src the source in the shortest path computation.
317 * @param dest the destination in the shortest path computation.
318 * @return the data path with the computed shortest path if
319 * found, otherwise null.
320 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800321 @Override
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700322 public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
323 return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800324 }
325
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700326 /**
327 * Test whether a route exists from a source to a destination.
328 *
329 * @param src the source node for the test.
330 * @param dest the destination node for the test.
331 * @return true if a route exists, otherwise false.
332 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800333 @Override
Pavlin Radoslavovf83aa442013-02-26 14:09:01 -0800334 public Boolean routeExists(SwitchPort src, SwitchPort dest) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700335 DataPath dataPath = getDatabaseShortestPath(src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700336 return (dataPath != null);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800337 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800338}