blob: ffe806ad8f881f6624e13fd957a931b0ddac298b [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/**
Pavlin Radoslavov1278ac72013-10-16 04:43:49 -070027 * A class for implementing Topology Network Service.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070028 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070029public class TopologyManager implements IFloodlightModule,
30 ITopologyNetService {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070031 private final static Logger log = LoggerFactory.getLogger(TopologyManager.class);
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070032 protected IFloodlightProviderService floodlightProvider;
33
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070034 protected GraphDBOperation dbHandler;
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080035
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070036
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070037 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070038 * Default constructor.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070039 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070040 public TopologyManager() {
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080041 }
42
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070043 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070044 * Constructor for given database configuration file.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070045 *
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070046 * @param config the database configuration file to use for
47 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070048 */
Pavlin Radoslavove1b37bc2013-10-16 03:57:06 -070049 public TopologyManager(String config) {
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070050 this.init(config);
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080051 }
52
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070053 /**
Pavlin Radoslavov0367d352013-10-19 11:04:43 -070054 * Constructor for a given database operation handler.
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070055 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070056 * @param dbHandler the database operation handler to use for the
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070057 * initialization.
58 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070059 public TopologyManager(GraphDBOperation dbHandler) {
60 this.dbHandler = dbHandler;
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070061 }
62
63 /**
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070064 * Init the module.
65 *
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070066 * @param config the database configuration file to use for
67 * the initialization.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070068 */
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070069 public void init(String config) {
70 try {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070071 dbHandler = new GraphDBOperation(config);
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070072 } catch (Exception e) {
73 log.error(e.getMessage());
74 }
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080075 }
76
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070077 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070078 * Shutdown the Topology Manager operation.
79 */
80 public void finalize() {
81 close();
82 }
83
84 /**
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070085 * Close the service. It will close the corresponding database connection.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070086 */
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -070087 public void close() {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070088 dbHandler.close();
Pavlin Radoslavovd7d8b792013-02-22 10:24:38 -080089 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -080090
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070091 /**
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070092 * Get the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070093 *
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070094 * @return the collection of offered module services.
Pavlin Radoslavovc5d2fbc2013-06-27 18:15:56 -070095 */
Pavlin Radoslavov5d8d77e2013-10-18 18:49:25 -070096 @Override
97 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
98 Collection<Class<? extends IFloodlightService>> l =
99 new ArrayList<Class<? extends IFloodlightService>>();
100 l.add(ITopologyNetService.class);
101 return l;
102 }
103
104 /**
105 * Get the collection of implemented services.
106 *
107 * @return the collection of implemented services.
108 */
109 @Override
110 public Map<Class<? extends IFloodlightService>, IFloodlightService>
111 getServiceImpls() {
112 Map<Class<? extends IFloodlightService>,
113 IFloodlightService> m =
114 new HashMap<Class<? extends IFloodlightService>,
115 IFloodlightService>();
116 m.put(ITopologyNetService.class, this);
117 return m;
118 }
119
120 /**
121 * Get the collection of modules this module depends on.
122 *
123 * @return the collection of modules this module depends on.
124 */
125 @Override
126 public Collection<Class<? extends IFloodlightService>>
127 getModuleDependencies() {
128 Collection<Class<? extends IFloodlightService>> l =
129 new ArrayList<Class<? extends IFloodlightService>>();
130 l.add(IFloodlightProviderService.class);
131 l.add(INetworkGraphService.class);
132 l.add(IDatagridService.class);
133 return l;
134 }
135
136 /**
137 * Initialize the module.
138 *
139 * @param context the module context to use for the initialization.
140 */
141 @Override
142 public void init(FloodlightModuleContext context)
143 throws FloodlightModuleException {
144 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
145
146 String conf = "";
147 this.init(conf);
148 }
149
150 /**
151 * Startup module operation.
152 *
153 * @param context the module context to use for the startup.
154 */
155 @Override
156 public void startUp(FloodlightModuleContext context) {
157
Pavlin Radoslavovcec899a2013-06-27 15:47:50 -0700158 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800159
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700160 /**
161 * Fetch the Switch and Ports info from the Titan Graph
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000162 * and return it for fast access during the shortest path
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700163 * computation.
164 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700165 * After fetching the state, method @ref getTopologyShortestPath()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700166 * can be used for fast shortest path computation.
167 *
168 * Note: There is certain cost to fetch the state, hence it should
169 * be used only when there is a large number of shortest path
170 * computations that need to be done on the same topology.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700171 * Typically, a single call to @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700172 * should be followed by a large number of calls to
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700173 * method @ref getTopologyShortestPath().
174 * After the last @ref getTopologyShortestPath() call,
175 * method @ref dropTopology() should be used to release
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700176 * the internal state that is not needed anymore:
177 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700178 * Topology topology = topologyManager.newDatabaseTopology();
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700179 * for (int i = 0; i < 10000; i++) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700180 * dataPath = topologyManager.getTopologyShortestPath(topology, ...);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700181 * ...
182 * }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700183 * topologyManager.dropTopology(shortestPathTopo);
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000184 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700185 * @return the allocated topology handler.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700186 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700187 public Topology newDatabaseTopology() {
188 Topology topology = new Topology();
189 topology.readFromDatabase(dbHandler);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700190
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700191 return topology;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700192 }
193
194 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700195 * Release the topology that was populated by
196 * method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700197 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700198 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700199 * for additional information and usage.
Pavlin Radoslavov9556b142013-05-20 21:49:04 +0000200 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700201 * @param topology the topology to release.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700202 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700203 public void dropTopology(Topology topology) {
204 topology = null;
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700205 }
206
207 /**
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700208 * Compute the network path for a Flow.
209 *
210 * @param topology the topology handler to use.
211 * @param flowPath the Flow to compute the network path for.
212 * @return the data path with the computed path if found, otherwise null.
213 */
214 public static DataPath computeNetworkPath(Topology topology,
215 FlowPath flowPath) {
216 //
217 // Compute the network path based on the desired Flow Path type
218 //
219 switch (flowPath.flowPathType()) {
220 case FP_TYPE_SHORTEST_PATH: {
221 SwitchPort src = flowPath.dataPath().srcPort();
222 SwitchPort dest = flowPath.dataPath().dstPort();
223 return ShortestPath.getTopologyShortestPath(topology, src, dest);
224 }
225 case FP_TYPE_EXPLICIT_PATH:
226 return flowPath.dataPath();
227 }
228
229 return null;
230 }
231
232 /**
233 * Test whether two Flow Entries represent same points in a data path.
234 *
235 * NOTE: Two Flow Entries represent same points in a data path if
236 * the Switch DPID, incoming port and outgoing port are same.
237 *
238 * NOTE: This method is specialized for shortest-path unicast paths,
239 * and probably should be moved somewhere else.
240 *
241 * @param oldFlowEntry the first Flow Entry to compare.
242 * @param newFlowEntry the second Flow Entry to compare.
243 * @return true if the two Flow Entries represent same points in a
244 * data path, otherwise false.
245 */
246 public static boolean isSameFlowEntryDataPath(FlowEntry oldFlowEntry,
247 FlowEntry newFlowEntry) {
248 // Test the DPID
249 if (oldFlowEntry.dpid().value() != newFlowEntry.dpid().value())
250 return false;
251
252 // Test the inPort
253 do {
254 Port oldPort = oldFlowEntry.inPort();
255 Port newPort = newFlowEntry.inPort();
256 if ((oldPort != null) && (newPort != null) &&
257 (oldPort.value() == newPort.value())) {
258 break;
259 }
260 if ((oldPort == null) && (newPort == null))
261 break;
262 return false; // inPort is different
263 } while (false);
264
265 // Test the outPort
266 do {
267 Port oldPort = oldFlowEntry.outPort();
268 Port newPort = newFlowEntry.outPort();
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; // outPort is different
276 } while (false);
277
278 return true;
279 }
280
281 /**
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700282 * Get the shortest path from a source to a destination by
283 * using the pre-populated local topology state prepared
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700284 * by method @ref newDatabaseTopology().
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700285 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700286 * See the documentation for method @ref newDatabaseTopology()
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700287 * for additional information and usage.
288 *
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700289 * @param topology the topology handler to use.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700290 * @param src the source in the shortest path computation.
291 * @param dest the destination in the shortest path computation.
292 * @return the data path with the computed shortest path if
293 * found, otherwise null.
294 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700295 public DataPath getTopologyShortestPath(Topology topology,
296 SwitchPort src, SwitchPort dest) {
297 return ShortestPath.getTopologyShortestPath(topology, src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700298 }
299
300 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700301 * Get the shortest path from a source to a destination by using
302 * the underlying database.
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700303 *
304 * @param src the source in the shortest path computation.
305 * @param dest the destination in the shortest path computation.
306 * @return the data path with the computed shortest path if
307 * found, otherwise null.
308 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800309 @Override
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700310 public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
311 return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800312 }
313
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700314 /**
315 * Test whether a route exists from a source to a destination.
316 *
317 * @param src the source node for the test.
318 * @param dest the destination node for the test.
319 * @return true if a route exists, otherwise false.
320 */
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800321 @Override
Pavlin Radoslavovf83aa442013-02-26 14:09:01 -0800322 public Boolean routeExists(SwitchPort src, SwitchPort dest) {
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700323 DataPath dataPath = getDatabaseShortestPath(src, dest);
Pavlin Radoslavova5f167b2013-03-21 11:39:27 -0700324 return (dataPath != null);
Pavlin Radoslavovf34c2902013-02-22 10:33:34 -0800325 }
Pavlin Radoslavov382b22a2013-01-28 09:24:04 -0800326}