blob: 02e0ffba6877a595c55673631a8513cd87976b8a [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;
Pankaj Berde38646d62013-06-21 11:34:04 -070015import net.onrc.onos.graph.GraphDBOperation;
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070016import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070017import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070018import net.onrc.onos.ofcontroller.util.FlowEntry;
19import net.onrc.onos.ofcontroller.util.FlowPath;
20import net.onrc.onos.ofcontroller.util.Port;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070021import net.onrc.onos.ofcontroller.util.SwitchPort;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080022
Pankaj Berde15193092013-03-21 17:30:14 -070023import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080025
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -070026/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070027 * A class for obtaining Topology Snapshot
28 * and PathComputation.
29 *
30 * TODO: PathComputation part should be refactored out to separate class.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070031 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070032public class TopologyManager implements IFloodlightModule,
33 ITopologyNetService {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070034 private final static Logger log = LoggerFactory.getLogger(TopologyManager.class);
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070035 protected IFloodlightProviderService floodlightProvider;
36
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070037 protected GraphDBOperation dbHandler;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080038
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070039
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070040 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070041 * Default constructor.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070042 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070043 public TopologyManager() {
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080044 }
45
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070046 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070047 * Constructor for given database configuration file.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070048 *
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070049 * @param config the database configuration file to use for
50 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070051 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070052 public TopologyManager(String config) {
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070053 this.init(config);
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080054 }
55
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070056 /**
Pavlin Radoslavov0367d352013-10-19 11:04:43 -070057 * Constructor for a given database operation handler.
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070058 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070059 * @param dbHandler the database operation handler to use for the
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070060 * initialization.
61 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070062 public TopologyManager(GraphDBOperation dbHandler) {
63 this.dbHandler = dbHandler;
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070064 }
65
66 /**
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070067 * Init the module.
68 *
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070069 * @param config the database configuration file to use for
70 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070071 */
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070072 public void init(String config) {
73 try {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070074 dbHandler = new GraphDBOperation(config);
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070075 } catch (Exception e) {
76 log.error(e.getMessage());
77 }
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080078 }
79
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070080 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070081 * Shutdown the Topology Manager operation.
82 */
83 public void finalize() {
84 close();
85 }
86
87 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070088 * Close the service. It will close the corresponding database connection.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070089 */
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070090 public void close() {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070091 dbHandler.close();
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080092 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080093
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070094 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070095 * Get the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070096 *
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070097 * @return the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070098 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070099 @Override
100 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
101 Collection<Class<? extends IFloodlightService>> l =
102 new ArrayList<Class<? extends IFloodlightService>>();
103 l.add(ITopologyNetService.class);
104 return l;
105 }
106
107 /**
108 * Get the collection of implemented services.
109 *
110 * @return the collection of implemented services.
111 */
112 @Override
113 public Map<Class<? extends IFloodlightService>, IFloodlightService>
114 getServiceImpls() {
115 Map<Class<? extends IFloodlightService>,
116 IFloodlightService> m =
117 new HashMap<Class<? extends IFloodlightService>,
118 IFloodlightService>();
119 m.put(ITopologyNetService.class, this);
120 return m;
121 }
122
123 /**
124 * Get the collection of modules this module depends on.
125 *
126 * @return the collection of modules this module depends on.
127 */
128 @Override
129 public Collection<Class<? extends IFloodlightService>>
130 getModuleDependencies() {
131 Collection<Class<? extends IFloodlightService>> l =
132 new ArrayList<Class<? extends IFloodlightService>>();
133 l.add(IFloodlightProviderService.class);
134 l.add(INetworkGraphService.class);
135 l.add(IDatagridService.class);
136 return l;
137 }
138
139 /**
140 * Initialize the module.
141 *
142 * @param context the module context to use for the initialization.
143 */
144 @Override
145 public void init(FloodlightModuleContext context)
146 throws FloodlightModuleException {
147 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
148
149 String conf = "";
150 this.init(conf);
151 }
152
153 /**
154 * Startup module operation.
155 *
156 * @param context the module context to use for the startup.
157 */
158 @Override
159 public void startUp(FloodlightModuleContext context) {
160
Pavlin Radoslavovcec899a2013-06-27 15:47:50 -0700161 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800162
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700163 /**
164 * Fetch the Switch and Ports info from the Titan Graph
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000165 * and return it for fast access during the shortest path
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700166 * computation.
167 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700168 * After fetching the state, method @ref getTopologyShortestPath()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700169 * can be used for fast shortest path computation.
170 *
171 * Note: There is certain cost to fetch the state, hence it should
172 * be used only when there is a large number of shortest path
173 * computations that need to be done on the same topology.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700174 * Typically, a single call to @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700175 * should be followed by a large number of calls to
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700176 * method @ref getTopologyShortestPath().
177 * After the last @ref getTopologyShortestPath() call,
178 * method @ref dropTopology() should be used to release
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700179 * the internal state that is not needed anymore:
180 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700181 * Topology topology = topologyManager.newDatabaseTopology();
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700182 * for (int i = 0; i < 10000; i++) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700183 * dataPath = topologyManager.getTopologyShortestPath(topology, ...);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700184 * ...
185 * }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700186 * topologyManager.dropTopology(shortestPathTopo);
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000187 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700188 * @return the allocated topology handler.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700189 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700190 public Topology newDatabaseTopology() {
191 Topology topology = new Topology();
192 topology.readFromDatabase(dbHandler);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700193
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700194 return topology;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700195 }
196
197 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700198 * Release the topology that was populated by
199 * method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700200 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700201 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700202 * for additional information and usage.
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000203 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700204 * @param topology the topology to release.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700205 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700206 public void dropTopology(Topology topology) {
207 topology = null;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700208 }
209
210 /**
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700211 * Compute the network path for a Flow.
212 *
213 * @param topology the topology handler to use.
214 * @param flowPath the Flow to compute the network path for.
215 * @return the data path with the computed path if found, otherwise null.
216 */
217 public static DataPath computeNetworkPath(Topology topology,
218 FlowPath flowPath) {
219 //
220 // Compute the network path based on the desired Flow Path type
221 //
222 switch (flowPath.flowPathType()) {
223 case FP_TYPE_SHORTEST_PATH: {
224 SwitchPort src = flowPath.dataPath().srcPort();
225 SwitchPort dest = flowPath.dataPath().dstPort();
226 return ShortestPath.getTopologyShortestPath(topology, src, dest);
227 }
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800228
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700229 case FP_TYPE_EXPLICIT_PATH:
230 return flowPath.dataPath();
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800231
232 case FP_TYPE_UNKNOWN:
233 return null;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700234 }
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800235
236 return null;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700237 }
238
239 /**
240 * Test whether two Flow Entries represent same points in a data path.
241 *
242 * NOTE: Two Flow Entries represent same points in a data path if
243 * the Switch DPID, incoming port and outgoing port are same.
244 *
245 * NOTE: This method is specialized for shortest-path unicast paths,
246 * and probably should be moved somewhere else.
247 *
248 * @param oldFlowEntry the first Flow Entry to compare.
249 * @param newFlowEntry the second Flow Entry to compare.
250 * @return true if the two Flow Entries represent same points in a
251 * data path, otherwise false.
252 */
253 public static boolean isSameFlowEntryDataPath(FlowEntry oldFlowEntry,
254 FlowEntry newFlowEntry) {
255 // Test the DPID
256 if (oldFlowEntry.dpid().value() != newFlowEntry.dpid().value())
257 return false;
258
259 // Test the inPort
260 do {
261 Port oldPort = oldFlowEntry.inPort();
262 Port newPort = newFlowEntry.inPort();
263 if ((oldPort != null) && (newPort != null) &&
264 (oldPort.value() == newPort.value())) {
265 break;
266 }
267 if ((oldPort == null) && (newPort == null))
268 break;
269 return false; // inPort is different
270 } while (false);
271
272 // Test the outPort
273 do {
274 Port oldPort = oldFlowEntry.outPort();
275 Port newPort = newFlowEntry.outPort();
276 if ((oldPort != null) && (newPort != null) &&
277 (oldPort.value() == newPort.value())) {
278 break;
279 }
280 if ((oldPort == null) && (newPort == null))
281 break;
282 return false; // outPort is different
283 } while (false);
284
285 return true;
286 }
287
288 /**
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700289 * Get the shortest path from a source to a destination by
290 * using the pre-populated local topology state prepared
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700291 * by method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700292 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700293 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700294 * for additional information and usage.
295 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700296 * @param topology the topology handler to use.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700297 * @param src the source in the shortest path computation.
298 * @param dest the destination in the shortest path computation.
299 * @return the data path with the computed shortest path if
300 * found, otherwise null.
301 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700302 public DataPath getTopologyShortestPath(Topology topology,
303 SwitchPort src, SwitchPort dest) {
304 return ShortestPath.getTopologyShortestPath(topology, src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700305 }
306
307 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700308 * Get the shortest path from a source to a destination by using
309 * the underlying database.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700310 *
311 * @param src the source in the shortest path computation.
312 * @param dest the destination in the shortest path computation.
313 * @return the data path with the computed shortest path if
314 * found, otherwise null.
315 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800316 @Override
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700317 public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
318 return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800319 }
320
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700321 /**
322 * Test whether a route exists from a source to a destination.
323 *
324 * @param src the source node for the test.
325 * @param dest the destination node for the test.
326 * @return true if a route exists, otherwise false.
327 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800328 @Override
Pavlin Radoslavovf83aa442013-02-26 14:09:01 -0800329 public Boolean routeExists(SwitchPort src, SwitchPort dest) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700330 DataPath dataPath = getDatabaseShortestPath(src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700331 return (dataPath != null);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800332 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800333}