blob: dae0cf4774c6f297586f623e280564e58fb12457 [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;
Pankaj Berde38646d62013-06-21 11:34:04 -070017import 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
yoshitomob292c622013-11-23 14:35:58 -080039 protected DBOperation dbHandler;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080040
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070041
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070042 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070043 * Default constructor.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070044 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070045 public TopologyManager() {
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080046 }
47
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070048 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070049 * Constructor for given database configuration file.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070050 *
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070051 * @param config the database configuration file to use for
52 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070053 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070054 public TopologyManager(String config) {
yoshitomob292c622013-11-23 14:35:58 -080055 this.init("",config);
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080056 }
57
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070058 /**
Pavlin Radoslavov0367d352013-10-19 11:04:43 -070059 * Constructor for a given database operation handler.
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070060 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070061 * @param dbHandler the database operation handler to use for the
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070062 * initialization.
63 */
yoshitomob292c622013-11-23 14:35:58 -080064 public TopologyManager(DBOperation dbHandler) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070065 this.dbHandler = dbHandler;
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070066 }
67
68 /**
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070069 * Init the module.
yoshitomob292c622013-11-23 14:35:58 -080070 * @param
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070071 * @param config the database configuration file to use for
72 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070073 */
yoshitomob292c622013-11-23 14:35:58 -080074 public void init(final String dbStore, String config) {
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070075 try {
yoshitomob292c622013-11-23 14:35:58 -080076 dbHandler = GraphDBManager.getDBOperation(dbStore, config);
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070077 } catch (Exception e) {
78 log.error(e.getMessage());
79 }
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080080 }
81
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070082 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070083 * Shutdown the Topology Manager operation.
84 */
85 public void finalize() {
86 close();
87 }
88
89 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070090 * Close the service. It will close the corresponding database connection.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070091 */
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070092 public void close() {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070093 dbHandler.close();
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080094 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080095
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070096 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070097 * Get the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070098 *
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070099 * @return the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -0700100 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700101 @Override
102 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
103 Collection<Class<? extends IFloodlightService>> l =
104 new ArrayList<Class<? extends IFloodlightService>>();
105 l.add(ITopologyNetService.class);
106 return l;
107 }
108
109 /**
110 * Get the collection of implemented services.
111 *
112 * @return the collection of implemented services.
113 */
114 @Override
115 public Map<Class<? extends IFloodlightService>, IFloodlightService>
116 getServiceImpls() {
117 Map<Class<? extends IFloodlightService>,
118 IFloodlightService> m =
119 new HashMap<Class<? extends IFloodlightService>,
120 IFloodlightService>();
121 m.put(ITopologyNetService.class, this);
122 return m;
123 }
124
125 /**
126 * Get the collection of modules this module depends on.
127 *
128 * @return the collection of modules this module depends on.
129 */
130 @Override
131 public Collection<Class<? extends IFloodlightService>>
132 getModuleDependencies() {
133 Collection<Class<? extends IFloodlightService>> l =
134 new ArrayList<Class<? extends IFloodlightService>>();
135 l.add(IFloodlightProviderService.class);
136 l.add(INetworkGraphService.class);
137 l.add(IDatagridService.class);
138 return l;
139 }
140
141 /**
142 * Initialize the module.
143 *
144 * @param context the module context to use for the initialization.
145 */
146 @Override
147 public void init(FloodlightModuleContext context)
148 throws FloodlightModuleException {
149 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
150
151 String conf = "";
yoshitomob292c622013-11-23 14:35:58 -0800152 this.init("",conf);
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700153 }
154
155 /**
156 * Startup module operation.
157 *
158 * @param context the module context to use for the startup.
159 */
160 @Override
161 public void startUp(FloodlightModuleContext context) {
162
Pavlin Radoslavovcec899a2013-06-27 15:47:50 -0700163 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800164
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700165 /**
166 * Fetch the Switch and Ports info from the Titan Graph
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000167 * and return it for fast access during the shortest path
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700168 * computation.
169 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700170 * After fetching the state, method @ref getTopologyShortestPath()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700171 * can be used for fast shortest path computation.
172 *
173 * Note: There is certain cost to fetch the state, hence it should
174 * be used only when there is a large number of shortest path
175 * computations that need to be done on the same topology.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700176 * Typically, a single call to @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700177 * should be followed by a large number of calls to
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700178 * method @ref getTopologyShortestPath().
179 * After the last @ref getTopologyShortestPath() call,
180 * method @ref dropTopology() should be used to release
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700181 * the internal state that is not needed anymore:
182 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700183 * Topology topology = topologyManager.newDatabaseTopology();
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700184 * for (int i = 0; i < 10000; i++) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700185 * dataPath = topologyManager.getTopologyShortestPath(topology, ...);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700186 * ...
187 * }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700188 * topologyManager.dropTopology(shortestPathTopo);
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000189 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700190 * @return the allocated topology handler.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700191 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700192 public Topology newDatabaseTopology() {
193 Topology topology = new Topology();
194 topology.readFromDatabase(dbHandler);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700195
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700196 return topology;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700197 }
198
199 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700200 * Release the topology that was populated by
201 * method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700202 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700203 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700204 * for additional information and usage.
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000205 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700206 * @param topology the topology to release.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700207 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700208 public void dropTopology(Topology topology) {
209 topology = null;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700210 }
211
212 /**
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700213 * Compute the network path for a Flow.
214 *
215 * @param topology the topology handler to use.
216 * @param flowPath the Flow to compute the network path for.
217 * @return the data path with the computed path if found, otherwise null.
218 */
219 public static DataPath computeNetworkPath(Topology topology,
220 FlowPath flowPath) {
221 //
222 // Compute the network path based on the desired Flow Path type
223 //
224 switch (flowPath.flowPathType()) {
225 case FP_TYPE_SHORTEST_PATH: {
226 SwitchPort src = flowPath.dataPath().srcPort();
227 SwitchPort dest = flowPath.dataPath().dstPort();
228 return ShortestPath.getTopologyShortestPath(topology, src, dest);
229 }
230 case FP_TYPE_EXPLICIT_PATH:
231 return flowPath.dataPath();
232 }
233
234 return null;
235 }
236
237 /**
238 * Test whether two Flow Entries represent same points in a data path.
239 *
240 * NOTE: Two Flow Entries represent same points in a data path if
241 * the Switch DPID, incoming port and outgoing port are same.
242 *
243 * NOTE: This method is specialized for shortest-path unicast paths,
244 * and probably should be moved somewhere else.
245 *
246 * @param oldFlowEntry the first Flow Entry to compare.
247 * @param newFlowEntry the second Flow Entry to compare.
248 * @return true if the two Flow Entries represent same points in a
249 * data path, otherwise false.
250 */
251 public static boolean isSameFlowEntryDataPath(FlowEntry oldFlowEntry,
252 FlowEntry newFlowEntry) {
253 // Test the DPID
254 if (oldFlowEntry.dpid().value() != newFlowEntry.dpid().value())
255 return false;
256
257 // Test the inPort
258 do {
259 Port oldPort = oldFlowEntry.inPort();
260 Port newPort = newFlowEntry.inPort();
261 if ((oldPort != null) && (newPort != null) &&
262 (oldPort.value() == newPort.value())) {
263 break;
264 }
265 if ((oldPort == null) && (newPort == null))
266 break;
267 return false; // inPort is different
268 } while (false);
269
270 // Test the outPort
271 do {
272 Port oldPort = oldFlowEntry.outPort();
273 Port newPort = newFlowEntry.outPort();
274 if ((oldPort != null) && (newPort != null) &&
275 (oldPort.value() == newPort.value())) {
276 break;
277 }
278 if ((oldPort == null) && (newPort == null))
279 break;
280 return false; // outPort is different
281 } while (false);
282
283 return true;
284 }
285
286 /**
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700287 * Get the shortest path from a source to a destination by
288 * using the pre-populated local topology state prepared
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700289 * by method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700290 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700291 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700292 * for additional information and usage.
293 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700294 * @param topology the topology handler to use.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700295 * @param src the source in the shortest path computation.
296 * @param dest the destination in the shortest path computation.
297 * @return the data path with the computed shortest path if
298 * found, otherwise null.
299 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700300 public DataPath getTopologyShortestPath(Topology topology,
301 SwitchPort src, SwitchPort dest) {
302 return ShortestPath.getTopologyShortestPath(topology, src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700303 }
304
305 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700306 * Get the shortest path from a source to a destination by using
307 * the underlying database.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700308 *
309 * @param src the source in the shortest path computation.
310 * @param dest the destination in the shortest path computation.
311 * @return the data path with the computed shortest path if
312 * found, otherwise null.
313 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800314 @Override
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700315 public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
316 return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800317 }
318
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700319 /**
320 * Test whether a route exists from a source to a destination.
321 *
322 * @param src the source node for the test.
323 * @param dest the destination node for the test.
324 * @return true if a route exists, otherwise false.
325 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800326 @Override
Pavlin Radoslavovf83aa442013-02-26 14:09:01 -0800327 public Boolean routeExists(SwitchPort src, SwitchPort dest) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700328 DataPath dataPath = getDatabaseShortestPath(src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700329 return (dataPath != null);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800330 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800331}