blob: 601bccb389ca54179a32fa480526e578f39a326a [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 Radoslavovb6f53542013-03-01 16:02:14 -080021import net.floodlightcontroller.util.OFMessageDamper;
yoshi2fd4c7e2013-11-22 15:47:55 -080022import net.onrc.onos.graph.DBOperation;
23import net.onrc.onos.graph.GraphDBManager;
Pavlin Radoslavov05378272013-10-19 23:23:05 -070024import net.onrc.onos.datagrid.IDatagridService;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070025import net.onrc.onos.ofcontroller.core.INetMapStorage;
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -070026import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
HIGUCHI Yuta60a10142013-06-14 15:50:10 -070027import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
Brian O'Connor8c166a72013-11-14 18:41:48 -080028import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
Pavlin Radoslavovc0862662013-12-10 15:31:49 -080029import net.onrc.onos.ofcontroller.forwarding.IForwardingService;
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070030import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov63e42602013-12-12 12:54:05 -080031import net.onrc.onos.ofcontroller.util.Dpid;
32import net.onrc.onos.ofcontroller.util.FlowEntry;
33import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
34import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
35import net.onrc.onos.ofcontroller.util.FlowEntryId;
36import net.onrc.onos.ofcontroller.util.FlowId;
37import net.onrc.onos.ofcontroller.util.FlowPath;
38import net.onrc.onos.ofcontroller.util.FlowPathUserState;
39import net.onrc.onos.ofcontroller.util.Pair;
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -080040import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080041
Pavlin Radoslavov262e6832013-12-18 14:37:35 -080042import com.thinkaurelius.titan.core.TitanException;
43
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -080044import com.esotericsoftware.kryo2.Kryo;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080045
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080046import org.slf4j.Logger;
47import org.slf4j.LoggerFactory;
48
admin944ef4f2013-10-08 17:48:37 -070049/**
HIGUCHI Yutaeb567aa2013-10-08 19:27:35 -070050 * Flow Manager class for handling the network flows.
admin944ef4f2013-10-08 17:48:37 -070051 */
Pavlin Radoslavov5adf1522013-04-04 17:43:41 -070052public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
Naoki Shiota1a37ca12013-11-18 10:55:23 -080053 // flag to use FlowPusher instead of FlowSwitchOperation/MessageDamper
54 private final static boolean enableFlowPusher = false;
yoshitomob292c622013-11-23 14:35:58 -080055 protected DBOperation dbHandlerApi;
56 protected DBOperation dbHandlerInner;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080057
Jonathan Hart50a94982013-04-10 14:49:51 -070058 protected volatile IFloodlightProviderService floodlightProvider;
Pavlin Radoslavov05378272013-10-19 23:23:05 -070059 protected volatile IDatagridService datagridService;
60 protected IRestApiService restApi;
Pavlin Radoslavov571cff92013-03-20 02:01:32 -070061 protected FloodlightModuleContext context;
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070062 protected FlowEventHandler flowEventHandler;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080063
Brian O'Connor8c166a72013-11-14 18:41:48 -080064 protected IFlowPusherService pusher;
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080065 protected IForwardingService forwardingService;
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -080066
67 private KryoFactory kryoFactory = new KryoFactory();
68
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +000069 // Flow Entry ID generation state
70 private static Random randomGenerator = new Random();
71 private static int nextFlowEntryIdPrefix = 0;
72 private static int nextFlowEntryIdSuffix = 0;
Pavlin Radoslavov01391c92013-03-14 17:13:21 -070073
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080074 /** The logger. */
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070075 private final static Logger log = LoggerFactory.getLogger(FlowManager.class);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080076
Pavlin Radoslavov584bd112013-11-21 20:59:33 -080077 // The queue to write Flow Entries to the database
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080078 private BlockingQueue<FlowPath> flowPathsToDatabaseQueue =
79 new LinkedBlockingQueue<FlowPath>();
Pavlin Radoslavov584bd112013-11-21 20:59:33 -080080 FlowDatabaseWriter flowDatabaseWriter;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080081
admin944ef4f2013-10-08 17:48:37 -070082 /**
83 * Initialize the Flow Manager.
84 *
85 * @param conf the Graph Database configuration string.
86 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080087 @Override
yoshi2fd4c7e2013-11-22 15:47:55 -080088 public void init(final String dbStore, final String conf) {
yoshib6a66eb2014-01-21 10:11:49 -080089 dbHandlerApi = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloud.conf");
90 dbHandlerInner = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloud.conf");
yoshid38cd312013-12-02 19:54:44 -080091
92 //dbHandlerApi = GraphDBManager.getDBOperation(dbStore, conf);
93 //dbHandlerInner = GraphDBManager.getDBOperation(dbStore, conf);
yoshitomob292c622013-11-23 14:35:58 -080094
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080095 }
96
admin944ef4f2013-10-08 17:48:37 -070097 /**
98 * Shutdown the Flow Manager operation.
99 */
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800100 @Override
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800101 protected void finalize() {
Toshio Koide9fe1cb22013-06-13 13:51:11 -0700102 close();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800103 }
104
admin944ef4f2013-10-08 17:48:37 -0700105 /**
106 * Shutdown the Flow Manager operation.
107 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800108 @Override
109 public void close() {
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700110 datagridService.deregisterFlowEventHandlerService(flowEventHandler);
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800111 dbHandlerApi.close();
112 dbHandlerInner.close();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800113 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800114
admin944ef4f2013-10-08 17:48:37 -0700115 /**
116 * Get the collection of offered module services.
117 *
118 * @return the collection of offered module services.
119 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800120 @Override
121 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800122 Collection<Class<? extends IFloodlightService>> l =
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800123 new ArrayList<Class<? extends IFloodlightService>>();
124 l.add(IFlowService.class);
125 return l;
126 }
127
admin944ef4f2013-10-08 17:48:37 -0700128 /**
129 * Get the collection of implemented services.
130 *
131 * @return the collection of implemented services.
132 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800133 @Override
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800134 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800135 getServiceImpls() {
136 Map<Class<? extends IFloodlightService>,
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -0700137 IFloodlightService> m =
138 new HashMap<Class<? extends IFloodlightService>,
139 IFloodlightService>();
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800140 m.put(IFlowService.class, this);
141 return m;
142 }
143
admin944ef4f2013-10-08 17:48:37 -0700144 /**
145 * Get the collection of modules this module depends on.
146 *
147 * @return the collection of modules this module depends on.
148 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800149 @Override
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800150 public Collection<Class<? extends IFloodlightService>>
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700151 getModuleDependencies() {
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800152 Collection<Class<? extends IFloodlightService>> l =
153 new ArrayList<Class<? extends IFloodlightService>>();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800154 l.add(IFloodlightProviderService.class);
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -0700155 l.add(INetworkGraphService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700156 l.add(IDatagridService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800157 l.add(IRestApiService.class);
Pavlin Radoslavovc0862662013-12-10 15:31:49 -0800158 l.add(IFlowPusherService.class);
Pavlin Radoslavov63c2d052013-12-18 18:17:55 -0800159 //
160 // TODO: Comment-out the dependency on the IForwardingService,
161 // because it is an optional module. Apparently, adding the dependency
162 // here automatically enables the module.
163 //
164 // l.add(IForwardingService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800165 return l;
166 }
167
admin944ef4f2013-10-08 17:48:37 -0700168 /**
169 * Initialize the module.
170 *
171 * @param context the module context to use for the initialization.
172 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800173 @Override
174 public void init(FloodlightModuleContext context)
175 throws FloodlightModuleException {
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700176 this.context = context;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800177 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700178 datagridService = context.getServiceImpl(IDatagridService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800179 restApi = context.getServiceImpl(IRestApiService.class);
Pavlin Radoslavov939ca6b2013-12-03 12:35:37 -0800180 pusher = context.getServiceImpl(IFlowPusherService.class);
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800181 forwardingService = context.getServiceImpl(IForwardingService.class);
Brian O'Connor8c166a72013-11-14 18:41:48 -0800182
yoshi0fee3de2013-11-23 09:13:37 -0800183 this.init("","");
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800184 }
185
admin944ef4f2013-10-08 17:48:37 -0700186 /**
187 * Get the next Flow Entry ID to use.
188 *
189 * @return the next Flow Entry ID to use.
190 */
Naoki Shiota4e77de92013-11-18 17:29:54 -0800191 @Override
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700192 public synchronized long getNextFlowEntryId() {
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +0000193 //
194 // Generate the next Flow Entry ID.
195 // NOTE: For now, the higher 32 bits are random, and
196 // the lower 32 bits are sequential.
197 // In the future, we need a better allocation mechanism.
198 //
199 if ((nextFlowEntryIdSuffix & 0xffffffffL) == 0xffffffffL) {
200 nextFlowEntryIdPrefix = randomGenerator.nextInt();
201 nextFlowEntryIdSuffix = 0;
202 } else {
203 nextFlowEntryIdSuffix++;
204 }
205 long result = (long)nextFlowEntryIdPrefix << 32;
206 result = result | (0xffffffffL & nextFlowEntryIdSuffix);
207 return result;
208 }
209
admin944ef4f2013-10-08 17:48:37 -0700210 /**
211 * Startup module operation.
212 *
213 * @param context the module context to use for the startup.
214 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800215 @Override
216 public void startUp(FloodlightModuleContext context) {
admin944ef4f2013-10-08 17:48:37 -0700217 restApi.addRestletRoutable(new FlowWebRoutable());
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700218
admin944ef4f2013-10-08 17:48:37 -0700219 // Initialize the Flow Entry ID generator
220 nextFlowEntryIdPrefix = randomGenerator.nextInt();
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800221
222 //
223 // The thread to write to the database
224 //
225 flowDatabaseWriter = new FlowDatabaseWriter(this,
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800226 flowPathsToDatabaseQueue);
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800227 flowDatabaseWriter.start();
228
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700229 //
Pavlin Radoslavovc9da5322013-11-22 11:59:46 -0800230 // The Flow Event Handler thread:
231 // - create
232 // - register with the Datagrid Service
233 // - startup
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700234 //
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700235 flowEventHandler = new FlowEventHandler(this, datagridService);
236 datagridService.registerFlowEventHandlerService(flowEventHandler);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700237 flowEventHandler.start();
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800238 }
239
240 /**
241 * Add a flow.
242 *
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800243 * @param flowPath the Flow Path to install.
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800244 * @return the Flow ID on success, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800245 */
246 @Override
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800247 public FlowId addFlow(FlowPath flowPath) {
248
249 // Allocate the Flow ID if necessary
Pavlin Radoslavov892dd182013-12-05 23:33:15 -0800250 if (! flowPath.isValidFlowId()) {
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800251 long id = getNextFlowEntryId();
252 flowPath.setFlowId(new FlowId(id));
253 }
254
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700255 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700256 // NOTE: We need to explicitly initialize some of the state,
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700257 // in case the application didn't do it.
258 //
259 for (FlowEntry flowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov07d22b42013-12-15 16:33:33 -0800260 // The Flow Entry switch state
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700261 if (flowEntry.flowEntrySwitchState() ==
262 FlowEntrySwitchState.FE_SWITCH_UNKNOWN) {
263 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800264 }
Pavlin Radoslavov07d22b42013-12-15 16:33:33 -0800265 // The Flow Entry ID
266 if (! flowEntry.isValidFlowEntryId()) {
267 long id = getNextFlowEntryId();
268 flowEntry.setFlowEntryId(new FlowEntryId(id));
269 }
270 // The Flow ID
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700271 if (! flowEntry.isValidFlowId())
272 flowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavov89c8f432013-03-15 18:50:46 -0700273 }
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800274
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800275 if (FlowDatabaseOperation.addFlow(dbHandlerApi, flowPath)) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700276 datagridService.notificationSendFlowAdded(flowPath);
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800277 return flowPath.flowId();
Pavlin Radoslavovad3a1e62013-07-09 13:30:16 -0700278 }
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800279 return null;
Pavlin Radoslavov9425f702013-04-04 19:55:07 -0700280 }
281
282 /**
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000283 * Delete all previously added flows.
284 *
285 * @return true on success, otherwise false.
286 */
287 @Override
288 public boolean deleteAllFlows() {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800289 if (FlowDatabaseOperation.deleteAllFlows(dbHandlerApi)) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700290 datagridService.notificationSendAllFlowsRemoved();
291 return true;
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000292 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700293 return false;
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000294 }
295
296 /**
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800297 * Delete a previously added flow.
298 *
299 * @param flowId the Flow ID of the flow to delete.
300 * @return true on success, otherwise false.
301 */
302 @Override
303 public boolean deleteFlow(FlowId flowId) {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800304 if (FlowDatabaseOperation.deleteFlow(dbHandlerApi, flowId)) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700305 datagridService.notificationSendFlowRemoved(flowId);
306 return true;
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700307 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700308 return false;
Pavlin Radoslavov916832f2013-03-14 17:48:41 -0700309 }
310
311 /**
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800312 * Get a previously added flow.
313 *
314 * @param flowId the Flow ID of the flow to get.
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800315 * @return the Flow Path if found, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800316 */
317 @Override
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800318 public FlowPath getFlow(FlowId flowId) {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800319 return FlowDatabaseOperation.getFlow(dbHandlerApi, flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700320 }
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800321
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700322 /**
323 * Get all installed flows by all installers.
324 *
325 * @return the Flow Paths if found, otherwise null.
326 */
327 @Override
328 public ArrayList<FlowPath> getAllFlows() {
Pavlin Radoslavovbc96ae12013-11-05 08:44:02 -0800329 return FlowDatabaseOperation.getAllFlows(dbHandlerApi);
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800330 }
331
332 /**
admin944ef4f2013-10-08 17:48:37 -0700333 * Get summary of all installed flows by all installers in a given range.
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700334 *
admin944ef4f2013-10-08 17:48:37 -0700335 * @param flowId the Flow ID of the first flow in the flow range to get.
HIGUCHI Yutaeb567aa2013-10-08 19:27:35 -0700336 * @param maxFlows the maximum number of flows to be returned.
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700337 * @return the Flow Paths if found, otherwise null.
338 */
339 @Override
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800340 public ArrayList<FlowPath> getAllFlowsSummary(FlowId flowId,
341 int maxFlows) {
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800342 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
343 SortedMap<Long, FlowPath> sortedFlowPaths =
344 flowEventHandler.getAllFlowPathsCopy();
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700345
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800346 //
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800347 // Truncate each Flow Path and Flow Entry
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800348 //
349 for (FlowPath flowPath : sortedFlowPaths.values()) {
350 //
351 // TODO: Add only the Flow Paths that have been successfully
352 // installed.
353 //
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800354 flowPath.setFlowEntryMatch(null);
355 flowPath.setFlowEntryActions(null);
356 for (FlowEntry flowEntry : flowPath.flowEntries()) {
357 flowEntry.setFlowEntryMatch(null);
358 flowEntry.setFlowEntryActions(null);
359 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800360 flowPaths.add(flowPath);
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800361 }
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700362
Pavlin Radoslavove79c19a2013-12-06 09:28:15 -0800363 return flowPaths;
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700364 }
365
366 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800367 * Get the collection of my switches.
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700368 *
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800369 * @return the collection of my switches.
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700370 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800371 public Map<Long, IOFSwitch> getMySwitches() {
372 return floodlightProvider.getSwitches();
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700373 }
374
375 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800376 * Get the network topology.
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700377 *
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800378 * @return the network topology.
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700379 */
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800380 @Override
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800381 public Topology getTopology() {
382 return flowEventHandler.getTopology();
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700383 }
384
385 /**
Pavlin Radoslavov4df85ae2013-11-26 14:48:32 -0800386 * Inform the Flow Manager that a Flow Entry on switch expired.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700387 *
Pavlin Radoslavov3bd5ccf2013-11-26 15:10:21 -0800388 * @param sw the switch the Flow Entry expired on.
Pavlin Radoslavov4df85ae2013-11-26 14:48:32 -0800389 * @param flowEntryId the Flow Entry ID of the expired Flow Entry.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700390 */
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800391 @Override
Pavlin Radoslavovc5718e72013-12-10 15:47:10 -0800392 public void flowEntryOnSwitchExpired(IOFSwitch sw,
393 FlowEntryId flowEntryId) {
394 // Find the Flow Entry
395 FlowEntry flowEntry = datagridService.getFlowEntry(flowEntryId);
yoshia97632b2013-12-17 15:46:08 -0800396 if (flowEntry == null)
Pavlin Radoslavovc5718e72013-12-10 15:47:10 -0800397 return; // Flow Entry not found
398
399 // Find the Flow Path
400 FlowPath flowPath = datagridService.getFlow(flowEntry.flowId());
401 if (flowPath == null)
402 return; // Flow Path not found
403
404 //
405 // Remove the Flow if the Flow Entry expired on the first switch
406 //
407 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
408 if (srcDpid.value() != sw.getId())
409 return;
410 deleteFlow(flowPath.flowId());
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700411 }
412
413 /**
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800414 * Inform the Flow Manager that a collection of Flow Entries have been
415 * pushed to a switch.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700416 *
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800417 * @param entries the collection of <IOFSwitch, FlowEntry> pairs
418 * that have been pushed.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700419 */
Yuta HIGUCHI3ab1fd02013-12-17 11:01:02 -0800420 @Override
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800421 public void flowEntriesPushedToSwitch(
422 Collection<Pair<IOFSwitch, FlowEntry>> entries) {
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700423
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800424 //
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800425 // Process all entries
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800426 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800427 // TODO: For now we have to create an explicit FlowEntry copy so
428 // we don't modify the original FlowEntry.
429 // This should go away after we start using the OpenFlow Barrier
430 // mechnanism in the FlowPusher.
431 //
432 Kryo kryo = kryoFactory.newKryo();
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800433 for (Pair<IOFSwitch, FlowEntry> entry : entries) {
Pavlin Radoslavov4535bc12013-12-05 10:43:49 -0800434 FlowEntry flowEntry = entry.second;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800435
436 //
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800437 // Mark the Flow Entry that it has been pushed to the switch
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800438 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800439 FlowEntry copyFlowEntry = kryo.copy(flowEntry);
440 copyFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700441
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800442 //
443 // Write the Flow Entry to the Datagrid
444 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800445 switch (copyFlowEntry.flowEntryUserState()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800446 case FE_USER_ADD:
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800447 datagridService.notificationSendFlowEntryAdded(copyFlowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800448 break;
449 case FE_USER_MODIFY:
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800450 datagridService.notificationSendFlowEntryUpdated(copyFlowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800451 break;
452 case FE_USER_DELETE:
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800453 datagridService.notificationSendFlowEntryRemoved(copyFlowEntry.flowEntryId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800454 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800455 case FE_USER_UNKNOWN:
456 assert(false);
457 break;
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800458 }
459 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800460 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800461 }
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700462
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800463 /**
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800464 * Generate a notification that a collection of Flow Paths has been
465 * installed in the network.
466 *
467 * @param flowPaths the collection of installed Flow Paths.
468 */
469 void notificationFlowPathsInstalled(Collection<FlowPath> flowPaths) {
Pavlin Radoslavov63c2d052013-12-18 18:17:55 -0800470 //
471 // TODO: Add an explicit check for null pointer, because
472 // the IForwardingService is optional. Remove the "if" statement
473 // after hte Forwarding Module becomes mandatory.
474 //
475 if (forwardingService != null)
476 forwardingService.flowsInstalled(flowPaths);
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800477 }
478
479 /**
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800480 * Push modified Flow-related state as appropriate.
481 *
482 * @param modifiedFlowPaths the collection of modified Flow Paths.
483 * @param modifiedFlowEntries the collection of modified Flow Entries.
484 */
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800485 void pushModifiedFlowState(Collection<FlowPath> modifiedFlowPaths,
486 Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800487 //
488 // Push the modified Flow state:
489 // - Flow Entries to switches and the datagrid
490 // - Flow Paths to the database
491 //
492 pushModifiedFlowEntriesToSwitches(modifiedFlowEntries);
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800493 pushModifiedFlowPathsToDatabase(modifiedFlowPaths);
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800494 cleanupDeletedFlowEntriesFromDatagrid(modifiedFlowEntries);
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800495 }
496
497 /**
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700498 * Push modified Flow Entries to switches.
499 *
500 * NOTE: Only the Flow Entries to switches controlled by this instance
501 * are pushed.
502 *
503 * @param modifiedFlowEntries the collection of modified Flow Entries.
504 */
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800505 private void pushModifiedFlowEntriesToSwitches(
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800506 Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700507 if (modifiedFlowEntries.isEmpty())
508 return;
509
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800510 List<Pair<IOFSwitch, FlowEntry>> entries =
511 new LinkedList<Pair<IOFSwitch, FlowEntry>>();
512
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700513 Map<Long, IOFSwitch> mySwitches = getMySwitches();
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700514
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800515 //
516 // Create a collection of my Flow Entries to push
517 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800518 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700519 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
520 if (mySwitch == null)
521 continue;
522
Pavlin Radoslavovd1b728c2013-12-18 21:39:58 -0800523 if (flowEntry.flowEntrySwitchState() ==
524 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
525 //
526 // Don't push again Flow Entries that were already already
527 // installed into the switches.
528 //
529 continue;
530 }
531
Pavlin Radoslavovaca49d12013-12-04 19:49:17 -0800532 //
533 // Assign Flow Entry IDs if missing.
534 //
535 // NOTE: This is an additional safeguard, in case the
536 // mySwitches set has changed (after the Flow Entry IDs
537 // assignments by the caller).
538 //
539 if (! flowEntry.isValidFlowEntryId()) {
540 long id = getNextFlowEntryId();
541 flowEntry.setFlowEntryId(new FlowEntryId(id));
542 }
543
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800544 log.debug("Pushing Flow Entry To Switch: {}", flowEntry);
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800545 entries.add(new Pair<IOFSwitch, FlowEntry>(mySwitch, flowEntry));
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700546 }
Pavlin Radoslavovab3f8862013-12-04 18:35:53 -0800547
548 pusher.pushFlowEntries(entries);
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700549 }
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700550
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700551 /**
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800552 * Cleanup deleted Flow Entries from the datagrid.
553 *
554 * NOTE: We cleanup only the Flow Entries that are not for our switches.
555 * This is needed to handle the case a switch going down:
556 * It has no Master controller instance, hence no controller instance
557 * will cleanup its flow entries.
558 * This is sub-optimal: we need to elect a controller instance to handle
559 * the cleanup of such orphaned flow entries.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700560 *
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800561 * @param modifiedFlowEntries the collection of modified Flow Entries.
562 */
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800563 private void cleanupDeletedFlowEntriesFromDatagrid(
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800564 Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800565 if (modifiedFlowEntries.isEmpty())
566 return;
567
568 Map<Long, IOFSwitch> mySwitches = getMySwitches();
569
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800570 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800571 //
572 // Process only Flow Entries that should be deleted and have
573 // a valid Flow Entry ID.
574 //
Pavlin Radoslavov426a8532013-12-02 17:32:21 -0800575 if (! flowEntry.isValidFlowEntryId())
576 continue;
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800577 if (flowEntry.flowEntryUserState() !=
578 FlowEntryUserState.FE_USER_DELETE) {
579 continue;
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700580 }
581
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800582 //
583 // NOTE: The deletion of Flow Entries for my switches is handled
584 // elsewhere.
585 //
586 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
587 if (mySwitch != null)
588 continue;
589
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800590 log.debug("Pushing cleanup of Flow Entry To Datagrid: {}", flowEntry);
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800591
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700592 //
593 // Write the Flow Entry to the Datagrid
594 //
Pavlin Radoslavovda0ab442013-12-04 14:08:58 -0800595 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700596 }
597 }
598
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800599 /**
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800600 * Class to implement writing to the database in a separate thread.
601 */
602 class FlowDatabaseWriter extends Thread {
603 private FlowManager flowManager;
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800604 private BlockingQueue<FlowPath> blockingQueue;
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800605
606 /**
607 * Constructor.
608 *
609 * @param flowManager the Flow Manager to use.
610 * @param blockingQueue the blocking queue to use.
611 */
612 FlowDatabaseWriter(FlowManager flowManager,
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800613 BlockingQueue<FlowPath> blockingQueue) {
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800614 this.flowManager = flowManager;
615 this.blockingQueue = blockingQueue;
616 }
617
618 /**
619 * Run the thread.
620 */
621 @Override
622 public void run() {
623 //
624 // The main loop
625 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800626 Collection<FlowPath> collection = new LinkedList<FlowPath>();
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800627 this.setName("FlowDatabaseWriter " + this.getId() );
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800628 try {
629 while (true) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800630 FlowPath flowPath = blockingQueue.take();
631 collection.add(flowPath);
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800632 blockingQueue.drainTo(collection);
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800633 flowManager.writeModifiedFlowPathsToDatabase(collection);
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800634 collection.clear();
635 }
636 } catch (Exception exception) {
637 log.debug("Exception writing to the Database: ", exception);
638 }
639 }
640 }
641
642 /**
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800643 * Push Flow Paths to the Network MAP.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800644 *
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800645 * NOTE: The complete Flow Paths are pushed only on the instance
646 * responsible for the first switch. This is to avoid database errors
647 * when multiple instances are writing Flow Entries for the same Flow Path.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800648 *
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800649 * @param modifiedFlowPaths the collection of Flow Paths to push.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800650 */
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800651 private void pushModifiedFlowPathsToDatabase(
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800652 Collection<FlowPath> modifiedFlowPaths) {
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -0800653 List<FlowPath> copiedFlowPaths = new LinkedList<FlowPath>();
654
655 //
656 // Create a copy of the Flow Paths to push, because the pushing
657 // itself will happen on a separate thread.
658 //
659 Kryo kryo = kryoFactory.newKryo();
660 for (FlowPath flowPath : modifiedFlowPaths) {
661 FlowPath copyFlowPath = kryo.copy(flowPath);
662 copiedFlowPaths.add(copyFlowPath);
663 }
664 kryoFactory.deleteKryo(kryo);
665
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800666 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800667 // We only add the Flow Paths to the Database Queue.
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800668 // The FlowDatabaseWriter thread is responsible for the actual writing.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800669 //
Pavlin Radoslavovda8d7232013-12-12 12:48:14 -0800670 flowPathsToDatabaseQueue.addAll(copiedFlowPaths);
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800671 }
672
673 /**
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800674 * Write Flow Paths to the Network MAP.
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800675 *
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800676 * NOTE: The complete Flow Paths are pushed only on the instance
677 * responsible for the first switch. This is to avoid database errors
678 * when multiple instances are writing Flow Entries for the same Flow Path.
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800679 *
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800680 * @param modifiedFlowPaths the collection of Flow Paths to write.
Pavlin Radoslavov584bd112013-11-21 20:59:33 -0800681 */
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800682 private void writeModifiedFlowPathsToDatabase(
683 Collection<FlowPath> modifiedFlowPaths) {
684 if (modifiedFlowPaths.isEmpty())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800685 return;
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700686
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800687 Map<Long, IOFSwitch> mySwitches = getMySwitches();
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700688
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800689 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800690 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800691 // Push the changes only on the instance responsible for the
692 // first switch.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800693 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800694 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
695 IOFSwitch mySrcSwitch = mySwitches.get(srcDpid.value());
696 if (mySrcSwitch == null)
697 continue;
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800698
699 //
Pavlin Radoslavovef545052013-12-05 15:17:25 -0800700 // Delete the Flow Path from the Network Map
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800701 //
Pavlin Radoslavovef545052013-12-05 15:17:25 -0800702 if (flowPath.flowPathUserState() ==
703 FlowPathUserState.FP_USER_DELETE) {
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800704 log.debug("Deleting Flow Path From Database: {}", flowPath);
Pavlin Radoslavovef545052013-12-05 15:17:25 -0800705
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800706 boolean retry = false;
707 do {
708 retry = false;
709 try {
710 if (! FlowDatabaseOperation.deleteFlow(
711 dbHandlerInner,
712 flowPath.flowId())) {
713 log.error("Cannot delete Flow Path {} from Network Map",
714 flowPath.flowId());
715 retry = true;
716 }
717 } catch (TitanException te) {
718 log.error("Titan Exception deleting Flow Path from Network MAP: {}", te);
719 retry = true;
720 } catch (Exception e) {
721 log.error("Exception deleting Flow Path from Network MAP: {}", e);
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800722 }
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800723 } while (retry);
724
Pavlin Radoslavovef545052013-12-05 15:17:25 -0800725 continue;
726 }
727
728 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800729 // Test whether all Flow Entries are valid
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800730 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800731 boolean allValid = true;
732 for (FlowEntry flowEntry : flowPath.flowEntries()) {
733 if (flowEntry.flowEntryUserState() ==
734 FlowEntryUserState.FE_USER_DELETE) {
735 continue;
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700736 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800737 if (! flowEntry.isValidFlowEntryId()) {
738 allValid = false;
739 break;
740 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800741 if (flowEntry.flowEntrySwitchState() !=
742 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
743 allValid = false;
744 break;
745 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800746 }
747 if (! allValid)
748 continue;
749
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800750 log.debug("Pushing Flow Path To Database: {}", flowPath);
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800751
752 //
753 // Write the Flow Path to the Network Map
754 //
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800755 boolean retry = false;
756 do {
757 retry = false;
758 try {
Masayoshi Kobayashi178ead12013-12-19 20:50:19 -0800759 long startTime = System.nanoTime();
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800760 if (! FlowDatabaseOperation.addFlow(dbHandlerInner, flowPath)) {
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800761 log.error("Cannot write to Network Map Flow Path {}", flowPath.flowId());
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800762 retry = true;
763 }
Masayoshi Kobayashi178ead12013-12-19 20:50:19 -0800764 // FIXME Flag to turn ON logging
765 //long endTime = System.nanoTime();
766 //log.error("Performance %% Flow path total time {} : {}", endTime - startTime, flowPath.toString());
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800767 } catch (TitanException te) {
768 log.error("Titan Exception writing Flow Path to Network MAP: ", te);
769 retry = true;
Masayoshi Kobayashi178ead12013-12-19 20:50:19 -0800770 // FIXME Flag to turn ON logging
771 //long endTime = System.nanoTime();
772 //log.error("Performance %% Flow path total time {} : {}", endTime - startTime, flowPath.toString());
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800773 } catch (Exception e) {
774 log.error("Exception writing Flow Path to Network MAP: ", e);
Masayoshi Kobayashi178ead12013-12-19 20:50:19 -0800775 // FIXME Flag to turn ON logging
776 //long endTime = System.nanoTime();
777 //log.error("Performance %% Flow path total time {} : {}", endTime - startTime, flowPath.toString());
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800778 }
Pavlin Radoslavov262e6832013-12-18 14:37:35 -0800779 } while (retry);
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700780 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800781 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800782}