blob: e4af36d47d443410e66a49062aa4ca17d2518480 [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;
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070017import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070018import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070019import net.onrc.onos.ofcontroller.util.FlowEntry;
20import net.onrc.onos.ofcontroller.util.FlowPath;
21import net.onrc.onos.ofcontroller.util.Port;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070022import net.onrc.onos.ofcontroller.util.SwitchPort;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080023
Pankaj Berde15193092013-03-21 17:30:14 -070024import org.slf4j.Logger;
25import org.slf4j.LoggerFactory;
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080026
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -070027/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070028 * A class for obtaining Topology Snapshot
29 * and PathComputation.
30 *
31 * TODO: PathComputation part should be refactored out to separate class.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070032 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070033public class TopologyManager implements IFloodlightModule,
34 ITopologyNetService {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070035 private final static Logger log = LoggerFactory.getLogger(TopologyManager.class);
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070036 protected IFloodlightProviderService floodlightProvider;
37
yoshitomob292c622013-11-23 14:35:58 -080038 protected DBOperation dbHandler;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080039
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070040
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070041 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070042 * Default constructor.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070043 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070044 public TopologyManager() {
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080045 }
46
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070047 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070048 * Constructor for given database configuration file.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070049 *
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070050 * @param config the database configuration file to use for
51 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070052 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070053 public TopologyManager(String config) {
yoshitomob292c622013-11-23 14:35:58 -080054 this.init("",config);
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080055 }
56
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070057 /**
Pavlin Radoslavov0367d352013-10-19 11:04:43 -070058 * Constructor for a given database operation handler.
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070059 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070060 * @param dbHandler the database operation handler to use for the
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070061 * initialization.
62 */
yoshitomob292c622013-11-23 14:35:58 -080063 public TopologyManager(DBOperation dbHandler) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070064 this.dbHandler = dbHandler;
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070065 }
66
67 /**
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070068 * Init the module.
yoshitomob292c622013-11-23 14:35:58 -080069 * @param
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070070 * @param config the database configuration file to use for
71 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070072 */
yoshitomob292c622013-11-23 14:35:58 -080073 public void init(final String dbStore, String config) {
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070074 try {
yoshitomob292c622013-11-23 14:35:58 -080075 dbHandler = GraphDBManager.getDBOperation(dbStore, config);
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070076 } catch (Exception e) {
77 log.error(e.getMessage());
78 }
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080079 }
80
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070081 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070082 * Shutdown the Topology Manager operation.
83 */
84 public void finalize() {
85 close();
86 }
87
88 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070089 * Close the service. It will close the corresponding database connection.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070090 */
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070091 public void close() {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070092 dbHandler.close();
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080093 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080094
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070095 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070096 * Get the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070097 *
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070098 * @return the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070099 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700100 @Override
101 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
102 Collection<Class<? extends IFloodlightService>> l =
103 new ArrayList<Class<? extends IFloodlightService>>();
104 l.add(ITopologyNetService.class);
105 return l;
106 }
107
108 /**
109 * Get the collection of implemented services.
110 *
111 * @return the collection of implemented services.
112 */
113 @Override
114 public Map<Class<? extends IFloodlightService>, IFloodlightService>
115 getServiceImpls() {
116 Map<Class<? extends IFloodlightService>,
117 IFloodlightService> m =
118 new HashMap<Class<? extends IFloodlightService>,
119 IFloodlightService>();
120 m.put(ITopologyNetService.class, this);
121 return m;
122 }
123
124 /**
125 * Get the collection of modules this module depends on.
126 *
127 * @return the collection of modules this module depends on.
128 */
129 @Override
130 public Collection<Class<? extends IFloodlightService>>
131 getModuleDependencies() {
132 Collection<Class<? extends IFloodlightService>> l =
133 new ArrayList<Class<? extends IFloodlightService>>();
134 l.add(IFloodlightProviderService.class);
135 l.add(INetworkGraphService.class);
136 l.add(IDatagridService.class);
137 return l;
138 }
139
140 /**
141 * Initialize the module.
142 *
143 * @param context the module context to use for the initialization.
144 */
145 @Override
146 public void init(FloodlightModuleContext context)
147 throws FloodlightModuleException {
148 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
149
150 String conf = "";
yoshitomob292c622013-11-23 14:35:58 -0800151 this.init("",conf);
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -0700152 }
153
154 /**
155 * Startup module operation.
156 *
157 * @param context the module context to use for the startup.
158 */
159 @Override
160 public void startUp(FloodlightModuleContext context) {
161
Pavlin Radoslavovcec899a2013-06-27 15:47:50 -0700162 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800163
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700164 /**
165 * Fetch the Switch and Ports info from the Titan Graph
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000166 * and return it for fast access during the shortest path
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700167 * computation.
168 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700169 * After fetching the state, method @ref getTopologyShortestPath()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700170 * can be used for fast shortest path computation.
171 *
172 * Note: There is certain cost to fetch the state, hence it should
173 * be used only when there is a large number of shortest path
174 * computations that need to be done on the same topology.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700175 * Typically, a single call to @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700176 * should be followed by a large number of calls to
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700177 * method @ref getTopologyShortestPath().
178 * After the last @ref getTopologyShortestPath() call,
179 * method @ref dropTopology() should be used to release
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700180 * the internal state that is not needed anymore:
181 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700182 * Topology topology = topologyManager.newDatabaseTopology();
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700183 * for (int i = 0; i < 10000; i++) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700184 * dataPath = topologyManager.getTopologyShortestPath(topology, ...);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700185 * ...
186 * }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700187 * topologyManager.dropTopology(shortestPathTopo);
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000188 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700189 * @return the allocated topology handler.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700190 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700191 public Topology newDatabaseTopology() {
192 Topology topology = new Topology();
193 topology.readFromDatabase(dbHandler);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700194
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700195 return topology;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700196 }
197
198 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700199 * Release the topology that was populated by
200 * method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700201 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700202 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700203 * for additional information and usage.
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000204 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700205 * @param topology the topology to release.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700206 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700207 public void dropTopology(Topology topology) {
208 topology = null;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700209 }
210
211 /**
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700212 * Compute the network path for a Flow.
213 *
214 * @param topology the topology handler to use.
215 * @param flowPath the Flow to compute the network path for.
216 * @return the data path with the computed path if found, otherwise null.
217 */
218 public static DataPath computeNetworkPath(Topology topology,
219 FlowPath flowPath) {
220 //
221 // Compute the network path based on the desired Flow Path type
222 //
223 switch (flowPath.flowPathType()) {
224 case FP_TYPE_SHORTEST_PATH: {
225 SwitchPort src = flowPath.dataPath().srcPort();
226 SwitchPort dest = flowPath.dataPath().dstPort();
227 return ShortestPath.getTopologyShortestPath(topology, src, dest);
228 }
229 case FP_TYPE_EXPLICIT_PATH:
230 return flowPath.dataPath();
231 }
232
233 return null;
234 }
235
236 /**
237 * Test whether two Flow Entries represent same points in a data path.
238 *
239 * NOTE: Two Flow Entries represent same points in a data path if
240 * the Switch DPID, incoming port and outgoing port are same.
241 *
242 * NOTE: This method is specialized for shortest-path unicast paths,
243 * and probably should be moved somewhere else.
244 *
245 * @param oldFlowEntry the first Flow Entry to compare.
246 * @param newFlowEntry the second Flow Entry to compare.
247 * @return true if the two Flow Entries represent same points in a
248 * data path, otherwise false.
249 */
250 public static boolean isSameFlowEntryDataPath(FlowEntry oldFlowEntry,
251 FlowEntry newFlowEntry) {
252 // Test the DPID
253 if (oldFlowEntry.dpid().value() != newFlowEntry.dpid().value())
254 return false;
255
256 // Test the inPort
257 do {
258 Port oldPort = oldFlowEntry.inPort();
259 Port newPort = newFlowEntry.inPort();
260 if ((oldPort != null) && (newPort != null) &&
261 (oldPort.value() == newPort.value())) {
262 break;
263 }
264 if ((oldPort == null) && (newPort == null))
265 break;
266 return false; // inPort is different
267 } while (false);
268
269 // Test the outPort
270 do {
271 Port oldPort = oldFlowEntry.outPort();
272 Port newPort = newFlowEntry.outPort();
273 if ((oldPort != null) && (newPort != null) &&
274 (oldPort.value() == newPort.value())) {
275 break;
276 }
277 if ((oldPort == null) && (newPort == null))
278 break;
279 return false; // outPort is different
280 } while (false);
281
282 return true;
283 }
284
285 /**
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700286 * Get the shortest path from a source to a destination by
287 * using the pre-populated local topology state prepared
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700288 * by method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700289 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700290 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700291 * for additional information and usage.
292 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700293 * @param topology the topology handler to use.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700294 * @param src the source in the shortest path computation.
295 * @param dest the destination in the shortest path computation.
296 * @return the data path with the computed shortest path if
297 * found, otherwise null.
298 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700299 public DataPath getTopologyShortestPath(Topology topology,
300 SwitchPort src, SwitchPort dest) {
301 return ShortestPath.getTopologyShortestPath(topology, src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700302 }
303
304 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700305 * Get the shortest path from a source to a destination by using
306 * the underlying database.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700307 *
308 * @param src the source in the shortest path computation.
309 * @param dest the destination in the shortest path computation.
310 * @return the data path with the computed shortest path if
311 * found, otherwise null.
312 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800313 @Override
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700314 public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
315 return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800316 }
317
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700318 /**
319 * Test whether a route exists from a source to a destination.
320 *
321 * @param src the source node for the test.
322 * @param dest the destination node for the test.
323 * @return true if a route exists, otherwise false.
324 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800325 @Override
Pavlin Radoslavovf83aa442013-02-26 14:09:01 -0800326 public Boolean routeExists(SwitchPort src, SwitchPort dest) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700327 DataPath dataPath = getDatabaseShortestPath(src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700328 return (dataPath != null);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800329 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800330}