blob: 9dfe999085892ce1e2318cb8820799953f6b2b07 [file] [log] [blame]
HIGUCHI Yuta60a10142013-06-14 15:50:10 -07001package net.onrc.onos.ofcontroller.flowmanager;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -08002
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.HashMap;
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +00006import java.util.LinkedList;
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -08007import java.util.List;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -08008import java.util.Map;
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +00009import java.util.Random;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080010import java.util.SortedMap;
Pavlin Radoslavov584bd112013-11-21 20:59:33 -080011import java.util.concurrent.BlockingQueue;
Pavlin Radoslavov584bd112013-11-21 20:59:33 -080012import java.util.concurrent.LinkedBlockingQueue;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080013
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080014import net.floodlightcontroller.core.IFloodlightProviderService;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080015import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080016import net.floodlightcontroller.core.module.FloodlightModuleContext;
17import net.floodlightcontroller.core.module.FloodlightModuleException;
18import net.floodlightcontroller.core.module.IFloodlightModule;
19import net.floodlightcontroller.core.module.IFloodlightService;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080020import net.floodlightcontroller.restserver.IRestApiService;
Pavlin Radoslavov05378272013-10-19 23:23:05 -070021import net.onrc.onos.datagrid.IDatagridService;
Pankaj Berde38646d62013-06-21 11:34:04 -070022import net.onrc.onos.graph.GraphDBOperation;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070023import net.onrc.onos.ofcontroller.core.INetMapStorage;
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -070024import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
HIGUCHI Yuta60a10142013-06-14 15:50:10 -070025import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
Brian O'Connor8c166a72013-11-14 18:41:48 -080026import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
Pavlin Radoslavovc0862662013-12-10 15:31:49 -080027import net.onrc.onos.ofcontroller.forwarding.IForwardingService;
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070028import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov63e42602013-12-12 12:54:05 -080029import net.onrc.onos.ofcontroller.util.Dpid;
30import net.onrc.onos.ofcontroller.util.FlowEntry;
31import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
32import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
33import net.onrc.onos.ofcontroller.util.FlowEntryId;
34import net.onrc.onos.ofcontroller.util.FlowId;
35import net.onrc.onos.ofcontroller.util.FlowPath;
36import net.onrc.onos.ofcontroller.util.FlowPathUserState;
37import net.onrc.onos.ofcontroller.util.Pair;
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -080038import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
39
Pavlin Radoslavov262e6832013-12-18 14:37:35 -080040import com.thinkaurelius.titan.core.TitanException;
41
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -080042import com.esotericsoftware.kryo2.Kryo;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080043
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080044import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
admin944ef4f2013-10-08 17:48:37 -070047/**
HIGUCHI Yutaeb567aa2013-10-08 19:27:35 -070048 * Flow Manager class for handling the network flows.
admin944ef4f2013-10-08 17:48:37 -070049 */
Pavlin Radoslavov5adf1522013-04-04 17:43:41 -070050public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080051
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -080052 private boolean enableOnrc2014MeasurementsFlows = true;
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080053
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -080054 protected GraphDBOperation dbHandlerApi;
55 protected GraphDBOperation dbHandlerInner;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080056
Jonathan Hart50a94982013-04-10 14:49:51 -070057 protected volatile IFloodlightProviderService floodlightProvider;
Pavlin Radoslavov05378272013-10-19 23:23:05 -070058 protected volatile IDatagridService datagridService;
59 protected IRestApiService restApi;
Pavlin Radoslavov571cff92013-03-20 02:01:32 -070060 protected FloodlightModuleContext context;
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070061 protected FlowEventHandler flowEventHandler;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080062
Brian O'Connor8c166a72013-11-14 18:41:48 -080063 protected IFlowPusherService pusher;
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080064 protected IForwardingService forwardingService;
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -080065
66 private KryoFactory kryoFactory = new KryoFactory();
67
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +000068 // Flow Entry ID generation state
69 private static Random randomGenerator = new Random();
70 private static int nextFlowEntryIdPrefix = 0;
71 private static int nextFlowEntryIdSuffix = 0;
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +000072
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080073 /** The logger. */
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070074 private final static Logger log = LoggerFactory.getLogger(FlowManager.class);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080075
Pavlin Radoslavov584bd112013-11-21 20:59:33 -080076 // The queue to write Flow Entries to the database
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080077 private BlockingQueue<FlowPath> flowPathsToDatabaseQueue =
78 new LinkedBlockingQueue<FlowPath>();
Pavlin Radoslavov584bd112013-11-21 20:59:33 -080079 FlowDatabaseWriter flowDatabaseWriter;
80
admin944ef4f2013-10-08 17:48:37 -070081 /**
82 * Initialize the Flow Manager.
83 *
84 * @param conf the Graph Database configuration string.
85 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080086 @Override
87 public void init(String conf) {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -080088 dbHandlerApi = new GraphDBOperation(conf);
89 dbHandlerInner = new GraphDBOperation(conf);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080090 }
91
admin944ef4f2013-10-08 17:48:37 -070092 /**
93 * Shutdown the Flow Manager operation.
94 */
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -080095 @Override
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -080096 protected void finalize() {
Toshio Koide9fe1cb22013-06-13 13:51:11 -070097 close();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080098 }
99
admin944ef4f2013-10-08 17:48:37 -0700100 /**
101 * Shutdown the Flow Manager operation.
102 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800103 @Override
104 public void close() {
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700105 datagridService.deregisterFlowEventHandlerService(flowEventHandler);
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800106 dbHandlerApi.close();
107 dbHandlerInner.close();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800108 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800109
admin944ef4f2013-10-08 17:48:37 -0700110 /**
111 * Get the collection of offered module services.
112 *
113 * @return the collection of offered module services.
114 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800115 @Override
116 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800117 Collection<Class<? extends IFloodlightService>> l =
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800118 new ArrayList<Class<? extends IFloodlightService>>();
119 l.add(IFlowService.class);
120 return l;
121 }
122
admin944ef4f2013-10-08 17:48:37 -0700123 /**
124 * Get the collection of implemented services.
125 *
126 * @return the collection of implemented services.
127 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800128 @Override
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800129 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800130 getServiceImpls() {
131 Map<Class<? extends IFloodlightService>,
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -0700132 IFloodlightService> m =
133 new HashMap<Class<? extends IFloodlightService>,
134 IFloodlightService>();
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800135 m.put(IFlowService.class, this);
136 return m;
137 }
138
admin944ef4f2013-10-08 17:48:37 -0700139 /**
140 * Get the collection of modules this module depends on.
141 *
142 * @return the collection of modules this module depends on.
143 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800144 @Override
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800145 public Collection<Class<? extends IFloodlightService>>
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700146 getModuleDependencies() {
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800147 Collection<Class<? extends IFloodlightService>> l =
148 new ArrayList<Class<? extends IFloodlightService>>();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800149 l.add(IFloodlightProviderService.class);
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -0700150 l.add(INetworkGraphService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700151 l.add(IDatagridService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800152 l.add(IRestApiService.class);
Pavlin Radoslavovc0862662013-12-10 15:31:49 -0800153 l.add(IFlowPusherService.class);
Pavlin Radoslavov63c2d052013-12-18 18:17:55 -0800154 //
155 // TODO: Comment-out the dependency on the IForwardingService,
156 // because it is an optional module. Apparently, adding the dependency
157 // here automatically enables the module.
158 //
159 // l.add(IForwardingService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800160 return l;
161 }
162
admin944ef4f2013-10-08 17:48:37 -0700163 /**
164 * Initialize the module.
165 *
166 * @param context the module context to use for the initialization.
167 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800168 @Override
169 public void init(FloodlightModuleContext context)
170 throws FloodlightModuleException {
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700171 this.context = context;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800172 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700173 datagridService = context.getServiceImpl(IDatagridService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800174 restApi = context.getServiceImpl(IRestApiService.class);
Pavlin Radoslavov939ca6b2013-12-03 12:35:37 -0800175 pusher = context.getServiceImpl(IFlowPusherService.class);
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800176 forwardingService = context.getServiceImpl(IForwardingService.class);
Brian O'Connor8c166a72013-11-14 18:41:48 -0800177
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700178 this.init("");
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800179 }
180
admin944ef4f2013-10-08 17:48:37 -0700181 /**
182 * Get the next Flow Entry ID to use.
183 *
184 * @return the next Flow Entry ID to use.
185 */
Naoki Shiota4e77de92013-11-18 17:29:54 -0800186 @Override
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700187 public synchronized long getNextFlowEntryId() {
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +0000188 //
189 // Generate the next Flow Entry ID.
190 // NOTE: For now, the higher 32 bits are random, and
191 // the lower 32 bits are sequential.
192 // In the future, we need a better allocation mechanism.
193 //
194 if ((nextFlowEntryIdSuffix & 0xffffffffL) == 0xffffffffL) {
195 nextFlowEntryIdPrefix = randomGenerator.nextInt();
196 nextFlowEntryIdSuffix = 0;
197 } else {
198 nextFlowEntryIdSuffix++;
199 }
200 long result = (long)nextFlowEntryIdPrefix << 32;
201 result = result | (0xffffffffL & nextFlowEntryIdSuffix);
202 return result;
203 }
204
admin944ef4f2013-10-08 17:48:37 -0700205 /**
206 * Startup module operation.
207 *
208 * @param context the module context to use for the startup.
209 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800210 @Override
211 public void startUp(FloodlightModuleContext context) {
admin944ef4f2013-10-08 17:48:37 -0700212 restApi.addRestletRoutable(new FlowWebRoutable());
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700213
admin944ef4f2013-10-08 17:48:37 -0700214 // Initialize the Flow Entry ID generator
215 nextFlowEntryIdPrefix = randomGenerator.nextInt();
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800216
217 //
218 // The thread to write to the database
219 //
220 flowDatabaseWriter = new FlowDatabaseWriter(this,
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800221 flowPathsToDatabaseQueue);
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800222 flowDatabaseWriter.start();
223
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700224 //
Pavlin Radoslavovc9da5322013-11-22 11:59:46 -0800225 // The Flow Event Handler thread:
226 // - create
227 // - register with the Datagrid Service
228 // - startup
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700229 //
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800230 flowEventHandler = new FlowEventHandler(this, datagridService);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700231 datagridService.registerFlowEventHandlerService(flowEventHandler);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700232 flowEventHandler.start();
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800233 }
234
235 /**
236 * Add a flow.
237 *
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800238 * @param flowPath the Flow Path to install.
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800239 * @return the Flow ID on success, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800240 */
241 @Override
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800242 public FlowId addFlow(FlowPath flowPath) {
243
244 // Allocate the Flow ID if necessary
Pavlin Radoslavov892dd182013-12-05 23:33:15 -0800245 if (! flowPath.isValidFlowId()) {
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800246 long id = getNextFlowEntryId();
247 flowPath.setFlowId(new FlowId(id));
248 }
249
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700250 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700251 // NOTE: We need to explicitly initialize some of the state,
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700252 // in case the application didn't do it.
253 //
254 for (FlowEntry flowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov07d22b42013-12-15 16:33:33 -0800255 // The Flow Entry switch state
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700256 if (flowEntry.flowEntrySwitchState() ==
257 FlowEntrySwitchState.FE_SWITCH_UNKNOWN) {
258 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
259 }
Pavlin Radoslavov07d22b42013-12-15 16:33:33 -0800260 // The Flow Entry ID
261 if (! flowEntry.isValidFlowEntryId()) {
262 long id = getNextFlowEntryId();
263 flowEntry.setFlowEntryId(new FlowEntryId(id));
264 }
265 // The Flow ID
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700266 if (! flowEntry.isValidFlowId())
267 flowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700268 }
269
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800270 if (FlowDatabaseOperation.addFlow(dbHandlerApi, flowPath)) {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800271 if (enableOnrc2014MeasurementsFlows) {
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800272 datagridService.notificationSendFlowIdAdded(flowPath.flowId(),
273 flowPath.dataPath().srcPort().dpid());
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800274 } else {
275 datagridService.notificationSendFlowAdded(flowPath);
276 }
277
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800278 return flowPath.flowId();
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700279 }
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800280 return null;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800281 }
282
283 /**
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000284 * Delete all previously added flows.
285 *
286 * @return true on success, otherwise false.
287 */
288 @Override
289 public boolean deleteAllFlows() {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800290 if (FlowDatabaseOperation.deleteAllFlows(dbHandlerApi)) {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800291 if (enableOnrc2014MeasurementsFlows) {
292 datagridService.notificationSendAllFlowIdsRemoved();
293 } else {
294 datagridService.notificationSendAllFlowsRemoved();
295 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700296 return true;
297 }
298 return false;
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000299 }
300
301 /**
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800302 * Delete a previously added flow.
303 *
304 * @param flowId the Flow ID of the flow to delete.
305 * @return true on success, otherwise false.
306 */
307 @Override
308 public boolean deleteFlow(FlowId flowId) {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800309 if (FlowDatabaseOperation.deleteFlow(dbHandlerApi, flowId)) {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800310 if (enableOnrc2014MeasurementsFlows) {
311 datagridService.notificationSendFlowIdRemoved(flowId);
312 } else {
313 datagridService.notificationSendFlowRemoved(flowId);
314 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700315 return true;
316 }
317 return false;
Pavlin Radoslavov916832f2013-03-14 17:48:41 -0700318 }
319
320 /**
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800321 * Get a previously added flow.
322 *
323 * @param flowId the Flow ID of the flow to get.
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800324 * @return the Flow Path if found, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800325 */
326 @Override
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800327 public FlowPath getFlow(FlowId flowId) {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800328 return FlowDatabaseOperation.getFlow(dbHandlerApi, flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700329 }
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800330
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700331 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800332 * Get a previously added flow entry.
333 *
334 * @param flowEntryId the Flow Entry ID of the flow entry to get.
335 * @return the Flow Entry if found, otherwise null.
336 */
337 public FlowEntry getFlowEntry(FlowEntryId flowEntryId) {
338 return FlowDatabaseOperation.getFlowEntry(dbHandlerApi, flowEntryId);
339 }
340
341 /**
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800342 * Get the source switch DPID of a previously added flow.
343 *
344 * @param flowId the Flow ID of the flow to get.
345 * @return the source switch DPID if found, otherwise null.
346 */
347 public Dpid getFlowSourceDpid(FlowId flowId) {
348 return FlowDatabaseOperation.getFlowSourceDpid(dbHandlerApi, flowId);
349 }
350
351 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700352 * Get all installed flows by all installers.
353 *
354 * @return the Flow Paths if found, otherwise null.
355 */
356 @Override
357 public ArrayList<FlowPath> getAllFlows() {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800358 return FlowDatabaseOperation.getAllFlows(dbHandlerApi);
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800359 }
360
361 /**
Pavlin Radoslavov16b761d2014-01-08 09:47:14 -0800362 * Get all installed flows whose Source Switch is controlled by this
363 * instance.
364 *
365 * @param mySwitches the collection of the switches controlled by this
366 * instance.
367 * @return the Flow Paths if found, otherwise null.
368 */
369 public ArrayList<FlowPath> getAllMyFlows(Map<Long, IOFSwitch> mySwitches) {
370 return FlowDatabaseOperation.getAllMyFlows(dbHandlerApi, mySwitches);
371 }
372
373 /**
admin944ef4f2013-10-08 17:48:37 -0700374 * Get summary of all installed flows by all installers in a given range.
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700375 *
admin944ef4f2013-10-08 17:48:37 -0700376 * @param flowId the Flow ID of the first flow in the flow range to get.
HIGUCHI Yutaeb567aa2013-10-08 19:27:35 -0700377 * @param maxFlows the maximum number of flows to be returned.
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700378 * @return the Flow Paths if found, otherwise null.
379 */
380 @Override
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800381 public ArrayList<FlowPath> getAllFlowsSummary(FlowId flowId,
382 int maxFlows) {
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800383 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
384 SortedMap<Long, FlowPath> sortedFlowPaths =
385 flowEventHandler.getAllFlowPathsCopy();
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800386
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800387 //
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800388 // Truncate each Flow Path and Flow Entry
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800389 //
390 for (FlowPath flowPath : sortedFlowPaths.values()) {
391 //
392 // TODO: Add only the Flow Paths that have been successfully
393 // installed.
394 //
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800395 flowPath.setFlowEntryMatch(null);
396 flowPath.setFlowEntryActions(null);
397 for (FlowEntry flowEntry : flowPath.flowEntries()) {
398 flowEntry.setFlowEntryMatch(null);
399 flowEntry.setFlowEntryActions(null);
400 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800401 flowPaths.add(flowPath);
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800402 }
403
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800404 return flowPaths;
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700405 }
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700406
407 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800408 * Get the collection of my switches.
409 *
410 * @return the collection of my switches.
411 */
412 public Map<Long, IOFSwitch> getMySwitches() {
413 return floodlightProvider.getSwitches();
414 }
415
416 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800417 * Get the network topology.
418 *
419 * @return the network topology.
420 */
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800421 @Override
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800422 public Topology getTopology() {
423 return flowEventHandler.getTopology();
424 }
425
426 /**
Pavlin Radoslavov4df85ae2013-11-26 14:48:32 -0800427 * Inform the Flow Manager that a Flow Entry on switch expired.
428 *
Pavlin Radoslavov3bd5ccf2013-11-26 15:10:21 -0800429 * @param sw the switch the Flow Entry expired on.
Pavlin Radoslavov4df85ae2013-11-26 14:48:32 -0800430 * @param flowEntryId the Flow Entry ID of the expired Flow Entry.
431 */
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800432 @Override
Pavlin Radoslavovc5718e72013-12-10 15:47:10 -0800433 public void flowEntryOnSwitchExpired(IOFSwitch sw,
434 FlowEntryId flowEntryId) {
435 // Find the Flow Entry
436 FlowEntry flowEntry = datagridService.getFlowEntry(flowEntryId);
Pavlin Radoslavovac0fabc2013-12-13 10:47:56 -0800437 if (flowEntry == null)
Pavlin Radoslavovc5718e72013-12-10 15:47:10 -0800438 return; // Flow Entry not found
439
440 // Find the Flow Path
441 FlowPath flowPath = datagridService.getFlow(flowEntry.flowId());
442 if (flowPath == null)
443 return; // Flow Path not found
444
445 //
446 // Remove the Flow if the Flow Entry expired on the first switch
447 //
448 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
449 if (srcDpid.value() != sw.getId())
450 return;
451 deleteFlow(flowPath.flowId());
Pavlin Radoslavov4df85ae2013-11-26 14:48:32 -0800452 }
453
454 /**
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800455 * Inform the Flow Manager that a collection of Flow Entries have been
456 * pushed to a switch.
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800457 *
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800458 * @param entries the collection of <IOFSwitch, FlowEntry> pairs
459 * that have been pushed.
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800460 */
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800461 @Override
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800462 public void flowEntriesPushedToSwitch(
463 Collection<Pair<IOFSwitch, FlowEntry>> entries) {
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800464
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800465 if (enableOnrc2014MeasurementsFlows)
466 return;
467
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800468 //
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800469 // Process all entries
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800470 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800471 // TODO: For now we have to create an explicit FlowEntry copy so
472 // we don't modify the original FlowEntry.
473 // This should go away after we start using the OpenFlow Barrier
474 // mechnanism in the FlowPusher.
475 //
476 Kryo kryo = kryoFactory.newKryo();
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800477 for (Pair<IOFSwitch, FlowEntry> entry : entries) {
Pavlin Radoslavov4535bc12013-12-05 10:43:49 -0800478 FlowEntry flowEntry = entry.second;
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800479
480 //
481 // Mark the Flow Entry that it has been pushed to the switch
482 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800483 FlowEntry copyFlowEntry = kryo.copy(flowEntry);
484 copyFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800485
486 //
487 // Write the Flow Entry to the Datagrid
488 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800489 switch (copyFlowEntry.flowEntryUserState()) {
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800490 case FE_USER_ADD:
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800491 datagridService.notificationSendFlowEntryAdded(copyFlowEntry);
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800492 break;
493 case FE_USER_MODIFY:
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800494 datagridService.notificationSendFlowEntryUpdated(copyFlowEntry);
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800495 break;
496 case FE_USER_DELETE:
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800497 datagridService.notificationSendFlowEntryRemoved(copyFlowEntry.flowEntryId());
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800498 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800499 case FE_USER_UNKNOWN:
500 assert(false);
501 break;
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800502 }
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800503 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800504 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800505 }
506
507 /**
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800508 * Generate a notification that a collection of Flow Paths has been
509 * installed in the network.
510 *
511 * @param flowPaths the collection of installed Flow Paths.
512 */
513 void notificationFlowPathsInstalled(Collection<FlowPath> flowPaths) {
Pavlin Radoslavov63c2d052013-12-18 18:17:55 -0800514 //
515 // TODO: Add an explicit check for null pointer, because
516 // the IForwardingService is optional. Remove the "if" statement
517 // after hte Forwarding Module becomes mandatory.
518 //
519 if (forwardingService != null)
520 forwardingService.flowsInstalled(flowPaths);
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800521 }
522
523 /**
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800524 * Push modified Flow-related state as appropriate.
525 *
526 * @param modifiedFlowPaths the collection of modified Flow Paths.
527 * @param modifiedFlowEntries the collection of modified Flow Entries.
528 */
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800529 void pushModifiedFlowState(Collection<FlowPath> modifiedFlowPaths,
530 Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800531 //
532 // Push the modified Flow state:
533 // - Flow Entries to switches and the datagrid
534 // - Flow Paths to the database
535 //
536 pushModifiedFlowEntriesToSwitches(modifiedFlowEntries);
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800537 if (enableOnrc2014MeasurementsFlows) {
538 writeModifiedFlowPathsToDatabase(modifiedFlowPaths);
539 } else {
540 pushModifiedFlowPathsToDatabase(modifiedFlowPaths);
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800541 cleanupDeletedFlowEntriesFromDatagrid(modifiedFlowEntries);
542 }
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800543 }
544
545 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800546 * Push modified Flow Entries to switches.
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700547 *
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800548 * NOTE: Only the Flow Entries to switches controlled by this instance
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700549 * are pushed.
550 *
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800551 * @param modifiedFlowEntries the collection of modified Flow Entries.
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700552 */
Pavlin Radoslavov7847db72014-01-10 11:35:21 -0800553 void pushModifiedFlowEntriesToSwitches(
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800554 Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800555 if (modifiedFlowEntries.isEmpty())
556 return;
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700557
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800558 List<Pair<IOFSwitch, FlowEntry>> entries =
559 new LinkedList<Pair<IOFSwitch, FlowEntry>>();
560
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800561 Map<Long, IOFSwitch> mySwitches = getMySwitches();
562
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800563 //
564 // Create a collection of my Flow Entries to push
565 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800566 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800567 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
568 if (mySwitch == null)
569 continue;
570
Pavlin Radoslavovd1b728c2013-12-18 21:39:58 -0800571 if (flowEntry.flowEntrySwitchState() ==
572 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
573 //
574 // Don't push again Flow Entries that were already already
575 // installed into the switches.
576 //
577 continue;
578 }
579
Pavlin Radoslavovaca49d12013-12-04 19:49:17 -0800580 //
581 // Assign Flow Entry IDs if missing.
582 //
583 // NOTE: This is an additional safeguard, in case the
584 // mySwitches set has changed (after the Flow Entry IDs
585 // assignments by the caller).
586 //
587 if (! flowEntry.isValidFlowEntryId()) {
588 long id = getNextFlowEntryId();
589 flowEntry.setFlowEntryId(new FlowEntryId(id));
590 }
591
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800592 log.debug("Pushing Flow Entry To Switch: {}", flowEntry);
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800593 entries.add(new Pair<IOFSwitch, FlowEntry>(mySwitch, flowEntry));
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800594 }
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800595
596 pusher.pushFlowEntries(entries);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800597 }
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700598
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800599 /**
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800600 * Cleanup deleted Flow Entries from the datagrid.
601 *
602 * NOTE: We cleanup only the Flow Entries that are not for our switches.
603 * This is needed to handle the case a switch going down:
604 * It has no Master controller instance, hence no controller instance
605 * will cleanup its flow entries.
606 * This is sub-optimal: we need to elect a controller instance to handle
607 * the cleanup of such orphaned flow entries.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800608 *
609 * @param modifiedFlowEntries the collection of modified Flow Entries.
610 */
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800611 private void cleanupDeletedFlowEntriesFromDatagrid(
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800612 Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800613 if (modifiedFlowEntries.isEmpty())
614 return;
615
616 Map<Long, IOFSwitch> mySwitches = getMySwitches();
617
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800618 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800619 //
620 // Process only Flow Entries that should be deleted and have
621 // a valid Flow Entry ID.
622 //
Pavlin Radoslavov426a8532013-12-02 17:32:21 -0800623 if (! flowEntry.isValidFlowEntryId())
624 continue;
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800625 if (flowEntry.flowEntryUserState() !=
626 FlowEntryUserState.FE_USER_DELETE) {
627 continue;
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800628 }
629
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800630 //
631 // NOTE: The deletion of Flow Entries for my switches is handled
632 // elsewhere.
633 //
634 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
635 if (mySwitch != null)
636 continue;
637
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800638 log.debug("Pushing cleanup of Flow Entry To Datagrid: {}", flowEntry);
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800639
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800640 //
641 // Write the Flow Entry to the Datagrid
642 //
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800643 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800644 }
645 }
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700646
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800647 /**
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800648 * Class to implement writing to the database in a separate thread.
649 */
650 class FlowDatabaseWriter extends Thread {
651 private FlowManager flowManager;
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800652 private BlockingQueue<FlowPath> blockingQueue;
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800653
654 /**
655 * Constructor.
656 *
657 * @param flowManager the Flow Manager to use.
658 * @param blockingQueue the blocking queue to use.
659 */
660 FlowDatabaseWriter(FlowManager flowManager,
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800661 BlockingQueue<FlowPath> blockingQueue) {
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800662 this.flowManager = flowManager;
663 this.blockingQueue = blockingQueue;
664 }
665
666 /**
667 * Run the thread.
668 */
669 @Override
670 public void run() {
671 //
672 // The main loop
673 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800674 Collection<FlowPath> collection = new LinkedList<FlowPath>();
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800675 this.setName("FlowDatabaseWriter " + this.getId() );
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800676 try {
677 while (true) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800678 FlowPath flowPath = blockingQueue.take();
679 collection.add(flowPath);
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800680 blockingQueue.drainTo(collection);
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800681 flowManager.writeModifiedFlowPathsToDatabase(collection);
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800682 collection.clear();
683 }
684 } catch (Exception exception) {
685 log.debug("Exception writing to the Database: ", exception);
686 }
687 }
688 }
689
690 /**
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800691 * Push Flow Paths to the Network MAP.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800692 *
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800693 * NOTE: The complete Flow Paths are pushed only on the instance
694 * responsible for the first switch. This is to avoid database errors
695 * when multiple instances are writing Flow Entries for the same Flow Path.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800696 *
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800697 * @param modifiedFlowPaths the collection of Flow Paths to push.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800698 */
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800699 private void pushModifiedFlowPathsToDatabase(
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800700 Collection<FlowPath> modifiedFlowPaths) {
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -0800701 List<FlowPath> copiedFlowPaths = new LinkedList<FlowPath>();
702
703 //
704 // Create a copy of the Flow Paths to push, because the pushing
705 // itself will happen on a separate thread.
706 //
707 Kryo kryo = kryoFactory.newKryo();
708 for (FlowPath flowPath : modifiedFlowPaths) {
709 FlowPath copyFlowPath = kryo.copy(flowPath);
710 copiedFlowPaths.add(copyFlowPath);
711 }
712 kryoFactory.deleteKryo(kryo);
713
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800714 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800715 // We only add the Flow Paths to the Database Queue.
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800716 // The FlowDatabaseWriter thread is responsible for the actual writing.
717 //
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -0800718 flowPathsToDatabaseQueue.addAll(copiedFlowPaths);
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800719 }
720
721 /**
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800722 * Write Flow Paths to the Network MAP.
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800723 *
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800724 * NOTE: The complete Flow Paths are pushed only on the instance
725 * responsible for the first switch. This is to avoid database errors
726 * when multiple instances are writing Flow Entries for the same Flow Path.
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800727 *
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800728 * @param modifiedFlowPaths the collection of Flow Paths to write.
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800729 */
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800730 void writeModifiedFlowPathsToDatabase(
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800731 Collection<FlowPath> modifiedFlowPaths) {
732 if (modifiedFlowPaths.isEmpty())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800733 return;
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700734
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800735 Map<Long, IOFSwitch> mySwitches = getMySwitches();
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700736
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800737 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800738 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800739 // Push the changes only on the instance responsible for the
740 // first switch.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800741 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800742 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
743 IOFSwitch mySrcSwitch = mySwitches.get(srcDpid.value());
744 if (mySrcSwitch == null)
745 continue;
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800746
747 //
Pavlin Radoslavovef545052013-12-05 15:17:25 -0800748 // Delete the Flow Path from the Network Map
749 //
750 if (flowPath.flowPathUserState() ==
751 FlowPathUserState.FP_USER_DELETE) {
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800752 log.debug("Deleting Flow Path From Database: {}", flowPath);
Pavlin Radoslavovef545052013-12-05 15:17:25 -0800753
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800754 boolean retry = false;
755 do {
756 retry = false;
757 try {
758 if (! FlowDatabaseOperation.deleteFlow(
759 dbHandlerInner,
760 flowPath.flowId())) {
761 log.error("Cannot delete Flow Path {} from Network Map",
762 flowPath.flowId());
763 retry = true;
764 }
765 } catch (TitanException te) {
766 log.error("Titan Exception deleting Flow Path from Network MAP: {}", te);
767 retry = true;
768 } catch (Exception e) {
769 log.error("Exception deleting Flow Path from Network MAP: {}", e);
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800770 }
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800771 } while (retry);
772
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800773 if (enableOnrc2014MeasurementsFlows) {
774 // Send the notification
775 datagridService.notificationSendFlowIdRemoved(flowPath.flowId());
776 }
777
Pavlin Radoslavovef545052013-12-05 15:17:25 -0800778 continue;
779 }
780
781 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800782 // Test whether all Flow Entries are valid
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800783 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800784 boolean allValid = true;
785 for (FlowEntry flowEntry : flowPath.flowEntries()) {
786 if (flowEntry.flowEntryUserState() ==
787 FlowEntryUserState.FE_USER_DELETE) {
788 continue;
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700789 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800790 if (! flowEntry.isValidFlowEntryId()) {
791 allValid = false;
792 break;
793 }
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800794 if (! enableOnrc2014MeasurementsFlows) {
795 if (flowEntry.flowEntrySwitchState() !=
796 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
797 allValid = false;
798 break;
799 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800800 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800801 }
802 if (! allValid)
803 continue;
804
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800805 log.debug("Pushing Flow Path To Database: {}", flowPath);
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800806
807 //
808 // Write the Flow Path to the Network Map
809 //
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800810 boolean retry = false;
811 do {
812 retry = false;
813 try {
814 if (! FlowDatabaseOperation.addFlow(dbHandlerInner, flowPath)) {
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800815 log.error("Cannot write to Network Map Flow Path {}", flowPath.flowId());
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800816 retry = true;
817 }
818 } catch (TitanException te) {
819 log.error("Titan Exception writing Flow Path to Network MAP: ", te);
820 retry = true;
821 } catch (Exception e) {
822 log.error("Exception writing Flow Path to Network MAP: ", e);
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800823 }
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800824 } while (retry);
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800825
826 if (enableOnrc2014MeasurementsFlows) {
Pavlin Radoslavovf4bdf262014-01-09 13:51:40 -0800827 // Send the notifications
Pavlin Radoslavov7847db72014-01-10 11:35:21 -0800828
Pavlin Radoslavovf4bdf262014-01-09 13:51:40 -0800829 for (FlowEntry flowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov8edd4412014-01-10 11:37:32 -0800830 if (flowEntry.flowEntrySwitchState() !=
Pavlin Radoslavovf4bdf262014-01-09 13:51:40 -0800831 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavov8edd4412014-01-10 11:37:32 -0800832 continue;
Pavlin Radoslavovf4bdf262014-01-09 13:51:40 -0800833 }
Pavlin Radoslavov8edd4412014-01-10 11:37:32 -0800834 // datagridService.notificationSendFlowEntryIdAdded(flowEntry.flowEntryId(), flowEntry.dpid());
Pavlin Radoslavov7847db72014-01-10 11:35:21 -0800835
836 //
837 // Write the Flow Entry to the Datagrid
838 //
839 switch (flowEntry.flowEntryUserState()) {
840 case FE_USER_ADD:
841 datagridService.notificationSendFlowEntryAdded(flowEntry);
842 break;
843 case FE_USER_MODIFY:
844 datagridService.notificationSendFlowEntryUpdated(flowEntry);
845 break;
846 case FE_USER_DELETE:
847 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
848 break;
849 case FE_USER_UNKNOWN:
850 assert(false);
851 break;
852 }
Pavlin Radoslavovf4bdf262014-01-09 13:51:40 -0800853 }
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800854 }
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700855 }
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700856 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800857}