blob: 5a4edc385c7e6ad94a79d85a0955d77e9bd259f9 [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;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -08005import java.util.EnumSet;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -08006import java.util.HashMap;
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +00007import java.util.LinkedList;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -08008import java.util.Map;
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +00009import java.util.Random;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080010import java.util.concurrent.Executors;
11import java.util.concurrent.ScheduledExecutorService;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080012import java.util.concurrent.TimeUnit;
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;
Pavlin Radoslavov05378272013-10-19 23:23:05 -070022
23import net.onrc.onos.datagrid.IDatagridService;
Pankaj Berde38646d62013-06-21 11:34:04 -070024import net.onrc.onos.graph.GraphDBOperation;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070025import net.onrc.onos.ofcontroller.core.INetMapStorage;
26import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
27import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -070028import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
HIGUCHI Yuta60a10142013-06-14 15:50:10 -070029import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
Pavlin Radoslavov1278ac72013-10-16 04:43:49 -070030import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070031import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070032import net.onrc.onos.ofcontroller.util.*;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080033
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080034import org.openflow.protocol.OFType;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080035import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
admin944ef4f2013-10-08 17:48:37 -070038/**
HIGUCHI Yutaeb567aa2013-10-08 19:27:35 -070039 * Flow Manager class for handling the network flows.
admin944ef4f2013-10-08 17:48:37 -070040 */
Pavlin Radoslavov5adf1522013-04-04 17:43:41 -070041public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080042
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070043 protected GraphDBOperation dbHandler;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080044
Jonathan Hart50a94982013-04-10 14:49:51 -070045 protected volatile IFloodlightProviderService floodlightProvider;
Pavlin Radoslavov1278ac72013-10-16 04:43:49 -070046 protected volatile ITopologyNetService topologyNetService;
Pavlin Radoslavov05378272013-10-19 23:23:05 -070047 protected volatile IDatagridService datagridService;
48 protected IRestApiService restApi;
Pavlin Radoslavov571cff92013-03-20 02:01:32 -070049 protected FloodlightModuleContext context;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080050
51 protected OFMessageDamper messageDamper;
52
Pavlin Radoslavov78c4e492013-03-12 17:17:48 -070053 //
54 // TODO: Values copied from elsewhere (class LearningSwitch).
55 // The local copy should go away!
56 //
57 protected static final int OFMESSAGE_DAMPER_CAPACITY = 50000; // TODO: find sweet spot
58 protected static final int OFMESSAGE_DAMPER_TIMEOUT = 250; // ms
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080059
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +000060 // Flow Entry ID generation state
61 private static Random randomGenerator = new Random();
62 private static int nextFlowEntryIdPrefix = 0;
63 private static int nextFlowEntryIdSuffix = 0;
64 private static long nextFlowEntryId = 0;
65
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080066 /** The logger. */
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070067 private final static Logger log = LoggerFactory.getLogger(FlowManager.class);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080068
69 // The periodic task(s)
Jonathan Hart50a94982013-04-10 14:49:51 -070070 private ScheduledExecutorService mapReaderScheduler;
71 private ScheduledExecutorService shortestPathReconcileScheduler;
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -070072
admin944ef4f2013-10-08 17:48:37 -070073 /**
74 * Periodic task for reading the Flow Entries and pushing changes
75 * into the switches.
76 */
Pavlin Radoslavov571cff92013-03-20 02:01:32 -070077 final Runnable mapReader = new Runnable() {
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080078 public void run() {
Pavlin Radoslavova75caea2013-04-10 19:11:26 -070079 try {
80 runImpl();
81 } catch (Exception e) {
82 log.debug("Exception processing All Flow Entries from the Network MAP: ", e);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070083 dbHandler.rollback();
Pavlin Radoslavova75caea2013-04-10 19:11:26 -070084 return;
85 }
86 }
87
88 private void runImpl() {
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -070089 long startTime = System.nanoTime();
90 int counterAllFlowEntries = 0;
91 int counterMyNotUpdatedFlowEntries = 0;
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -070092
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080093 if (floodlightProvider == null) {
94 log.debug("FloodlightProvider service not found!");
95 return;
96 }
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +000097 Map<Long, IOFSwitch> mySwitches =
98 floodlightProvider.getSwitches();
Pankaj Berdebf51e4f2013-10-03 17:49:23 -070099 if (mySwitches.isEmpty()) {
Pankaj Berde85a877b2013-10-03 18:26:35 -0700100 log.trace("No switches controlled");
Pankaj Berdebf51e4f2013-10-03 17:49:23 -0700101 return;
102 }
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700103 LinkedList<IFlowEntry> addFlowEntries =
104 new LinkedList<IFlowEntry>();
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000105 LinkedList<IFlowEntry> deleteFlowEntries =
106 new LinkedList<IFlowEntry>();
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700107
108 //
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700109 // Fetch all Flow Entries which need to be updated and select
110 // only my Flow Entries that need to be updated into the
111 // switches.
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700112 //
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000113 Iterable<IFlowEntry> allFlowEntries =
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700114 dbHandler.getAllSwitchNotUpdatedFlowEntries();
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700115 for (IFlowEntry flowEntryObj : allFlowEntries) {
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700116 counterAllFlowEntries++;
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000117
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000118 String dpidStr = flowEntryObj.getSwitchDpid();
119 if (dpidStr == null)
120 continue;
121 Dpid dpid = new Dpid(dpidStr);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800122 IOFSwitch mySwitch = mySwitches.get(dpid.value());
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000123 if (mySwitch == null)
124 continue; // Ignore the entry: not my switch
125
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700126 IFlowPath flowObj =
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700127 dbHandler.getFlowPathByFlowEntry(flowEntryObj);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700128 if (flowObj == null)
129 continue; // Should NOT happen
130 if (flowObj.getFlowId() == null)
131 continue; // Invalid entry
132
133 //
134 // NOTE: For now we process the DELETE before the ADD
135 // to cover the more common scenario.
136 // TODO: This is error prone and needs to be fixed!
137 //
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000138 String userState = flowEntryObj.getUserState();
139 if (userState == null)
140 continue;
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700141 if (userState.equals("FE_USER_DELETE")) {
142 // An entry that needs to be deleted.
143 deleteFlowEntries.add(flowEntryObj);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700144 installFlowEntry(mySwitch, flowObj, flowEntryObj);
145 } else {
146 addFlowEntries.add(flowEntryObj);
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700147 }
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700148 counterMyNotUpdatedFlowEntries++;
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700149 }
150
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700151 //
152 // Process the Flow Entries that need to be added
153 //
154 for (IFlowEntry flowEntryObj : addFlowEntries) {
155 IFlowPath flowObj =
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700156 dbHandler.getFlowPathByFlowEntry(flowEntryObj);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700157 if (flowObj == null)
158 continue; // Should NOT happen
159 if (flowObj.getFlowId() == null)
160 continue; // Invalid entry
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700161
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700162 Dpid dpid = new Dpid(flowEntryObj.getSwitchDpid());
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700163 IOFSwitch mySwitch = mySwitches.get(dpid.value());
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000164 if (mySwitch == null)
165 continue; // Shouldn't happen
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700166 installFlowEntry(mySwitch, flowObj, flowEntryObj);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800167 }
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000168
169 //
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000170 // Delete all Flow Entries marked for deletion from the
Pavlin Radoslavov44a3dcd2013-04-04 18:42:56 -0700171 // Network MAP.
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000172 //
173 // TODO: We should use the OpenFlow Barrier mechanism
174 // to check for errors, and delete the Flow Entries after the
175 // Barrier message is received.
176 //
177 while (! deleteFlowEntries.isEmpty()) {
178 IFlowEntry flowEntryObj = deleteFlowEntries.poll();
179 IFlowPath flowObj =
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700180 dbHandler.getFlowPathByFlowEntry(flowEntryObj);
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000181 if (flowObj == null) {
182 log.debug("Did not find FlowPath to be deleted");
183 continue;
184 }
185 flowObj.removeFlowEntry(flowEntryObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700186 dbHandler.removeFlowEntry(flowEntryObj);
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000187 }
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700188
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700189 dbHandler.commit();
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700190
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700191 long estimatedTime = System.nanoTime() - startTime;
192 double rate = 0.0;
193 if (estimatedTime > 0)
194 rate = ((double)counterAllFlowEntries * 1000000000) / estimatedTime;
195 String logMsg = "MEASUREMENT: Processed AllFlowEntries: " +
196 counterAllFlowEntries + " MyNotUpdatedFlowEntries: " +
197 counterMyNotUpdatedFlowEntries + " in " +
198 (double)estimatedTime / 1000000000 + " sec: " +
199 rate + " paths/s";
200 log.debug(logMsg);
201 }
202 };
203
admin944ef4f2013-10-08 17:48:37 -0700204 /**
205 * Periodic task for reading the Flow Paths and recomputing the
206 * shortest paths.
207 */
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700208 final Runnable shortestPathReconcile = new Runnable() {
209 public void run() {
Pavlin Radoslavova75caea2013-04-10 19:11:26 -0700210 try {
211 runImpl();
212 } catch (Exception e) {
213 log.debug("Exception processing All Flows from the Network MAP: ", e);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700214 dbHandler.rollback();
Pavlin Radoslavova75caea2013-04-10 19:11:26 -0700215 return;
216 }
217 }
218
219 private void runImpl() {
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700220 long startTime = System.nanoTime();
221 int counterAllFlowPaths = 0;
222 int counterMyFlowPaths = 0;
223
224 if (floodlightProvider == null) {
225 log.debug("FloodlightProvider service not found!");
226 return;
227 }
228 Map<Long, IOFSwitch> mySwitches =
229 floodlightProvider.getSwitches();
Pankaj Berdebf51e4f2013-10-03 17:49:23 -0700230 if (mySwitches.isEmpty()) {
Pankaj Berde85a877b2013-10-03 18:26:35 -0700231 log.trace("No switches controlled");
Pankaj Berdebf51e4f2013-10-03 17:49:23 -0700232 return;
233 }
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700234 LinkedList<IFlowPath> deleteFlows = new LinkedList<IFlowPath>();
235
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700236 //
237 // Fetch and recompute the Shortest Path for those
238 // Flow Paths this controller is responsible for.
239 //
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700240 Topology topology = topologyNetService.newDatabaseTopology();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700241 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700242 for (IFlowPath flowPathObj : allFlowPaths) {
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700243 counterAllFlowPaths++;
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700244 if (flowPathObj == null)
245 continue;
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700246
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700247 String srcDpidStr = flowPathObj.getSrcSwitch();
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000248 if (srcDpidStr == null)
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700249 continue;
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700250 Dpid srcDpid = new Dpid(srcDpidStr);
Pavlin Radoslavov2659a0b2013-04-03 20:30:40 -0700251 //
252 // Use the source DPID as a heuristic to decide
253 // which controller is responsible for maintaining the
254 // shortest path.
255 // NOTE: This heuristic is error-prone: if the switch
256 // goes away and no controller is responsible for that
257 // switch, then the original Flow Path is not cleaned-up
258 //
259 IOFSwitch mySwitch = mySwitches.get(srcDpid.value());
260 if (mySwitch == null)
261 continue; // Ignore: not my responsibility
262
Pavlin Radoslavov99d1b152013-04-09 22:57:33 -0700263 // Test the Data Path Summary string
264 String dataPathSummaryStr = flowPathObj.getDataPathSummary();
265 if (dataPathSummaryStr == null)
266 continue; // Could be invalid entry?
267 if (dataPathSummaryStr.isEmpty())
268 continue; // No need to maintain this flow
269
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000270 //
271 // Test whether we need to complete the Flow cleanup,
272 // if the Flow has been deleted by the user.
273 //
274 String flowUserState = flowPathObj.getUserState();
275 if ((flowUserState != null)
276 && flowUserState.equals("FE_USER_DELETE")) {
277 Iterable<IFlowEntry> flowEntries = flowPathObj.getFlowEntries();
Yuta HIGUCHI2ded2dd2013-10-09 18:06:41 -0700278 final boolean empty = !flowEntries.iterator().hasNext();
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000279 if (empty)
280 deleteFlows.add(flowPathObj);
281 }
282
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000283 // Fetch the fields needed to recompute the shortest path
284 Short srcPortShort = flowPathObj.getSrcPort();
285 String dstDpidStr = flowPathObj.getDstSwitch();
286 Short dstPortShort = flowPathObj.getDstPort();
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700287 Long flowPathFlagsLong = flowPathObj.getFlowPathFlags();
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000288 if ((srcPortShort == null) ||
289 (dstDpidStr == null) ||
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700290 (dstPortShort == null) ||
291 (flowPathFlagsLong == null)) {
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000292 continue;
293 }
294
295 Port srcPort = new Port(srcPortShort);
296 Dpid dstDpid = new Dpid(dstDpidStr);
297 Port dstPort = new Port(dstPortShort);
298 SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
299 SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700300 FlowPathFlags flowPathFlags = new FlowPathFlags(flowPathFlagsLong);
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000301
Pavlin Radoslavov2659a0b2013-04-03 20:30:40 -0700302 counterMyFlowPaths++;
303
Pavlin Radoslavov832aa652013-03-29 16:21:59 -0700304 //
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700305 // NOTE: Using here the regular getDatabaseShortestPath()
306 // method won't work here, because that method calls
307 // internally "conn.endTx(Transaction.COMMIT)", and that
308 // will invalidate all handlers to the Titan database.
Pavlin Radoslavov832aa652013-03-29 16:21:59 -0700309 // If we want to experiment with calling here
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700310 // getDatabaseShortestPath(), we need to refactor that code
Pavlin Radoslavov832aa652013-03-29 16:21:59 -0700311 // to avoid closing the transaction.
312 //
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700313 DataPath dataPath =
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700314 topologyNetService.getTopologyShortestPath(
315 topology,
316 srcSwitchPort,
317 dstSwitchPort);
Pavlin Radoslavov4a325822013-04-02 22:16:59 +0000318 if (dataPath == null) {
319 // We need the DataPath to compare the paths
320 dataPath = new DataPath();
321 dataPath.setSrcPort(srcSwitchPort);
322 dataPath.setDstPort(dstSwitchPort);
323 }
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700324 dataPath.applyFlowPathFlags(flowPathFlags);
Pavlin Radoslavov4a325822013-04-02 22:16:59 +0000325
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700326 String newDataPathSummaryStr = dataPath.dataPathSummary();
327 if (dataPathSummaryStr.equals(newDataPathSummaryStr))
328 continue; // Nothing changed
329
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700330 reconcileFlow(flowPathObj, dataPath);
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700331 }
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000332
333 //
334 // Delete all leftover Flows marked for deletion from the
335 // Network MAP.
336 //
337 while (! deleteFlows.isEmpty()) {
338 IFlowPath flowPathObj = deleteFlows.poll();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700339 dbHandler.removeFlowPath(flowPathObj);
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000340 }
341
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700342 topologyNetService.dropTopology(topology);
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700343
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700344 dbHandler.commit();
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700345
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700346 long estimatedTime = System.nanoTime() - startTime;
Pavlin Radoslavov1552f952013-04-04 17:51:22 -0700347 double rate = 0.0;
348 if (estimatedTime > 0)
349 rate = ((double)counterAllFlowPaths * 1000000000) / estimatedTime;
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700350 String logMsg = "MEASUREMENT: Processed AllFlowPaths: " +
Pavlin Radoslavov1552f952013-04-04 17:51:22 -0700351 counterAllFlowPaths + " MyFlowPaths: " +
352 counterMyFlowPaths + " in " +
353 (double)estimatedTime / 1000000000 + " sec: " +
354 rate + " paths/s";
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700355 log.debug(logMsg);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800356 }
357 };
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700358
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800359
admin944ef4f2013-10-08 17:48:37 -0700360 /**
361 * Initialize the Flow Manager.
362 *
363 * @param conf the Graph Database configuration string.
364 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800365 @Override
366 public void init(String conf) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700367 dbHandler = new GraphDBOperation(conf);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800368 }
369
admin944ef4f2013-10-08 17:48:37 -0700370 /**
371 * Shutdown the Flow Manager operation.
372 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800373 public void finalize() {
Toshio Koide9fe1cb22013-06-13 13:51:11 -0700374 close();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800375 }
376
admin944ef4f2013-10-08 17:48:37 -0700377 /**
378 * Shutdown the Flow Manager operation.
379 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800380 @Override
381 public void close() {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700382 datagridService.deregisterFlowService(this);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700383 dbHandler.close();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800384 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800385
admin944ef4f2013-10-08 17:48:37 -0700386 /**
387 * Get the collection of offered module services.
388 *
389 * @return the collection of offered module services.
390 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800391 @Override
392 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
393 Collection<Class<? extends IFloodlightService>> l =
394 new ArrayList<Class<? extends IFloodlightService>>();
395 l.add(IFlowService.class);
396 return l;
397 }
398
admin944ef4f2013-10-08 17:48:37 -0700399 /**
400 * Get the collection of implemented services.
401 *
402 * @return the collection of implemented services.
403 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800404 @Override
405 public Map<Class<? extends IFloodlightService>, IFloodlightService>
406 getServiceImpls() {
407 Map<Class<? extends IFloodlightService>,
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -0700408 IFloodlightService> m =
409 new HashMap<Class<? extends IFloodlightService>,
410 IFloodlightService>();
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800411 m.put(IFlowService.class, this);
412 return m;
413 }
414
admin944ef4f2013-10-08 17:48:37 -0700415 /**
416 * Get the collection of modules this module depends on.
417 *
418 * @return the collection of modules this module depends on.
419 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800420 @Override
421 public Collection<Class<? extends IFloodlightService>>
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700422 getModuleDependencies() {
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800423 Collection<Class<? extends IFloodlightService>> l =
424 new ArrayList<Class<? extends IFloodlightService>>();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800425 l.add(IFloodlightProviderService.class);
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -0700426 l.add(INetworkGraphService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700427 l.add(IDatagridService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800428 l.add(IRestApiService.class);
429 return l;
430 }
431
admin944ef4f2013-10-08 17:48:37 -0700432 /**
433 * Initialize the module.
434 *
435 * @param context the module context to use for the initialization.
436 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800437 @Override
438 public void init(FloodlightModuleContext context)
439 throws FloodlightModuleException {
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700440 this.context = context;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800441 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700442 topologyNetService = context.getServiceImpl(ITopologyNetService.class);
443 datagridService = context.getServiceImpl(IDatagridService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800444 restApi = context.getServiceImpl(IRestApiService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700445
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800446 messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
447 EnumSet.of(OFType.FLOW_MOD),
448 OFMESSAGE_DAMPER_TIMEOUT);
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -0700449
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700450 this.init("");
451
admin944ef4f2013-10-08 17:48:37 -0700452 mapReaderScheduler = Executors.newScheduledThreadPool(1);
453 shortestPathReconcileScheduler = Executors.newScheduledThreadPool(1);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800454 }
455
admin944ef4f2013-10-08 17:48:37 -0700456 /**
457 * Get the next Flow Entry ID to use.
458 *
459 * @return the next Flow Entry ID to use.
460 */
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700461 public synchronized long getNextFlowEntryId() {
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +0000462 //
463 // Generate the next Flow Entry ID.
464 // NOTE: For now, the higher 32 bits are random, and
465 // the lower 32 bits are sequential.
466 // In the future, we need a better allocation mechanism.
467 //
468 if ((nextFlowEntryIdSuffix & 0xffffffffL) == 0xffffffffL) {
469 nextFlowEntryIdPrefix = randomGenerator.nextInt();
470 nextFlowEntryIdSuffix = 0;
471 } else {
472 nextFlowEntryIdSuffix++;
473 }
474 long result = (long)nextFlowEntryIdPrefix << 32;
475 result = result | (0xffffffffL & nextFlowEntryIdSuffix);
476 return result;
477 }
478
admin944ef4f2013-10-08 17:48:37 -0700479 /**
480 * Startup module operation.
481 *
482 * @param context the module context to use for the startup.
483 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800484 @Override
485 public void startUp(FloodlightModuleContext context) {
admin944ef4f2013-10-08 17:48:37 -0700486 restApi.addRestletRoutable(new FlowWebRoutable());
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700487
admin944ef4f2013-10-08 17:48:37 -0700488 // Initialize the Flow Entry ID generator
489 nextFlowEntryIdPrefix = randomGenerator.nextInt();
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700490
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700491 datagridService.registerFlowService(this);
492 // TODO: Flow Paths not used yet
493 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
494
admin944ef4f2013-10-08 17:48:37 -0700495 mapReaderScheduler.scheduleAtFixedRate(
496 mapReader, 3, 3, TimeUnit.SECONDS);
497 shortestPathReconcileScheduler.scheduleAtFixedRate(
498 shortestPathReconcile, 3, 3, TimeUnit.SECONDS);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800499 }
500
501 /**
502 * Add a flow.
503 *
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800504 * @param flowPath the Flow Path to install.
505 * @param flowId the return-by-reference Flow ID as assigned internally.
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700506 * @param dataPathSummaryStr the data path summary string if the added
507 * flow will be maintained internally, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800508 * @return true on success, otherwise false.
509 */
510 @Override
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700511 public boolean addFlow(FlowPath flowPath, FlowId flowId,
512 String dataPathSummaryStr) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700513 if (FlowDatabaseOperation.addFlow(this, dbHandler, flowPath, flowId,
514 dataPathSummaryStr)) {
515 datagridService.notificationSendFlowAdded(flowPath);
516 return true;
517 }
518 return false;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800519 }
520
521 /**
Pavlin Radoslavov9425f702013-04-04 19:55:07 -0700522 * Add a flow entry to the Network MAP.
523 *
524 * @param flowObj the corresponding Flow Path object for the Flow Entry.
525 * @param flowEntry the Flow Entry to install.
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700526 * @return the added Flow Entry object on success, otherwise null.
Pavlin Radoslavov9425f702013-04-04 19:55:07 -0700527 */
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700528 private IFlowEntry addFlowEntry(IFlowPath flowObj, FlowEntry flowEntry) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700529 return FlowDatabaseOperation.addFlowEntry(this, dbHandler, flowObj,
530 flowEntry);
Pavlin Radoslavov9425f702013-04-04 19:55:07 -0700531 }
532
533 /**
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000534 * Delete all previously added flows.
535 *
536 * @return true on success, otherwise false.
537 */
538 @Override
539 public boolean deleteAllFlows() {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700540 if (FlowDatabaseOperation.deleteAllFlows(dbHandler)) {
541 datagridService.notificationSendAllFlowsRemoved();
542 return true;
543 }
544 return false;
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000545 }
546
547 /**
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800548 * Delete a previously added flow.
549 *
550 * @param flowId the Flow ID of the flow to delete.
551 * @return true on success, otherwise false.
552 */
553 @Override
554 public boolean deleteFlow(FlowId flowId) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700555 if (FlowDatabaseOperation.deleteFlow(dbHandler, flowId)) {
556 datagridService.notificationSendFlowRemoved(flowId);
557 return true;
558 }
559 return false;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800560 }
561
562 /**
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000563 * Clear the state for all previously added flows.
564 *
565 * @return true on success, otherwise false.
566 */
567 @Override
568 public boolean clearAllFlows() {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700569 if (FlowDatabaseOperation.clearAllFlows(dbHandler)) {
570 datagridService.notificationSendAllFlowsRemoved();
571 return true;
572 }
573 return false;
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000574 }
575
576 /**
Pavlin Radoslavov916832f2013-03-14 17:48:41 -0700577 * Clear the state for a previously added flow.
578 *
579 * @param flowId the Flow ID of the flow to clear.
580 * @return true on success, otherwise false.
581 */
582 @Override
583 public boolean clearFlow(FlowId flowId) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700584 if (FlowDatabaseOperation.clearFlow(dbHandler, flowId)) {
585 datagridService.notificationSendFlowRemoved(flowId);
586 return true;
587 }
588 return false;
Pavlin Radoslavov916832f2013-03-14 17:48:41 -0700589 }
590
591 /**
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800592 * Get a previously added flow.
593 *
594 * @param flowId the Flow ID of the flow to get.
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800595 * @return the Flow Path if found, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800596 */
597 @Override
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800598 public FlowPath getFlow(FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700599 return FlowDatabaseOperation.getFlow(dbHandler, flowId);
600 }
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800601
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700602 /**
603 * Get all installed flows by all installers.
604 *
605 * @return the Flow Paths if found, otherwise null.
606 */
607 @Override
608 public ArrayList<FlowPath> getAllFlows() {
609 return FlowDatabaseOperation.getAllFlows(dbHandler);
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800610 }
611
612 /**
613 * Get all previously added flows by a specific installer for a given
614 * data path endpoints.
615 *
616 * @param installerId the Caller ID of the installer of the flow to get.
617 * @param dataPathEndpoints the data path endpoints of the flow to get.
618 * @return the Flow Paths if found, otherwise null.
619 */
620 @Override
621 public ArrayList<FlowPath> getAllFlows(CallerId installerId,
622 DataPathEndpoints dataPathEndpoints) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700623 return FlowDatabaseOperation.getAllFlows(dbHandler, installerId,
624 dataPathEndpoints);
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800625 }
626
627 /**
628 * Get all installed flows by all installers for given data path endpoints.
629 *
630 * @param dataPathEndpoints the data path endpoints of the flows to get.
631 * @return the Flow Paths if found, otherwise null.
632 */
633 @Override
634 public ArrayList<FlowPath> getAllFlows(DataPathEndpoints dataPathEndpoints) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700635 return FlowDatabaseOperation.getAllFlows(dbHandler, dataPathEndpoints);
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800636 }
637
638 /**
admin944ef4f2013-10-08 17:48:37 -0700639 * Get summary of all installed flows by all installers in a given range.
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700640 *
admin944ef4f2013-10-08 17:48:37 -0700641 * @param flowId the Flow ID of the first flow in the flow range to get.
HIGUCHI Yutaeb567aa2013-10-08 19:27:35 -0700642 * @param maxFlows the maximum number of flows to be returned.
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700643 * @return the Flow Paths if found, otherwise null.
644 */
645 @Override
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700646 public ArrayList<IFlowPath> getAllFlowsSummary(FlowId flowId,
647 int maxFlows) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700648 return FlowDatabaseOperation.getAllFlowsSummary(dbHandler, flowId,
649 maxFlows);
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700650 }
651
652 /**
admin944ef4f2013-10-08 17:48:37 -0700653 * Get all Flows information, without the associated Flow Entries.
654 *
655 * @return all Flows information, without the associated Flow Entries.
656 */
657 public ArrayList<IFlowPath> getAllFlowsWithoutFlowEntries() {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700658 return FlowDatabaseOperation.getAllFlowsWithoutFlowEntries(dbHandler);
Pavlin Radoslavov99b12752013-04-04 17:28:06 -0700659 }
660
661 /**
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700662 * Add and maintain a shortest-path flow.
663 *
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700664 * NOTE: The Flow Path argument does NOT contain flow entries.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700665 *
666 * @param flowPath the Flow Path with the endpoints and the match
667 * conditions to install.
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700668 * @return the added shortest-path flow on success, otherwise null.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700669 */
670 @Override
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700671 public FlowPath addAndMaintainShortestPathFlow(FlowPath flowPath) {
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700672 //
Pavlin Radoslavov8b4b0592013-04-10 04:33:33 +0000673 // Don't do the shortest path computation here.
674 // Instead, let the Flow reconciliation thread take care of it.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700675 //
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700676
Pavlin Radoslavov8b4b0592013-04-10 04:33:33 +0000677 // We need the DataPath to populate the Network MAP
678 DataPath dataPath = new DataPath();
679 dataPath.setSrcPort(flowPath.dataPath().srcPort());
680 dataPath.setDstPort(flowPath.dataPath().dstPort());
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700681
682 //
683 // Prepare the computed Flow Path
684 //
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700685 FlowPath computedFlowPath = new FlowPath();
686 computedFlowPath.setFlowId(new FlowId(flowPath.flowId().value()));
687 computedFlowPath.setInstallerId(new CallerId(flowPath.installerId().value()));
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700688 computedFlowPath.setFlowPathFlags(new FlowPathFlags(flowPath.flowPathFlags().flags()));
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700689 computedFlowPath.setDataPath(dataPath);
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700690 computedFlowPath.setFlowEntryMatch(new FlowEntryMatch(flowPath.flowEntryMatch()));
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700691 computedFlowPath.setFlowEntryActions(new FlowEntryActions(flowPath.flowEntryActions()));
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700692
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700693 FlowId flowId = new FlowId();
Pavlin Radoslavov8b4b0592013-04-10 04:33:33 +0000694 String dataPathSummaryStr = dataPath.dataPathSummary();
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700695 if (! addFlow(computedFlowPath, flowId, dataPathSummaryStr))
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700696 return null;
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700697
698 // TODO: Mark the flow for maintenance purpose
699
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700700 return (computedFlowPath);
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700701 }
702
703 /**
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700704 * Reconcile a flow.
705 *
706 * @param flowObj the flow that needs to be reconciliated.
707 * @param newDataPath the new data path to use.
708 * @return true on success, otherwise false.
709 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700710 private boolean reconcileFlow(IFlowPath flowObj, DataPath newDataPath) {
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700711
712 //
713 // Set the incoming port matching and the outgoing port output
714 // actions for each flow entry.
715 //
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700716 int idx = 0;
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700717 for (FlowEntry flowEntry : newDataPath.flowEntries()) {
718 // Set the incoming port matching
719 FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
720 flowEntry.setFlowEntryMatch(flowEntryMatch);
721 flowEntryMatch.enableInPort(flowEntry.inPort());
722
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700723 //
724 // Set the actions
725 //
726 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
727 //
728 // If the first Flow Entry, copy the Flow Path actions to it
729 //
730 if (idx == 0) {
731 String actionsStr = flowObj.getActions();
732 if (actionsStr != null) {
733 FlowEntryActions flowActions = new FlowEntryActions(actionsStr);
734 for (FlowEntryAction action : flowActions.actions())
735 flowEntryActions.addAction(action);
736 }
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700737 }
Pavlin Radoslavov282f4ff2013-07-18 11:21:37 -0700738 idx++;
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700739 //
740 // Add the outgoing port output action
741 //
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700742 FlowEntryAction flowEntryAction = new FlowEntryAction();
743 flowEntryAction.setActionOutput(flowEntry.outPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700744 flowEntryActions.addAction(flowEntryAction);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700745 }
746
747 //
748 // Remove the old Flow Entries, and add the new Flow Entries
749 //
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700750 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700751 for (IFlowEntry flowEntryObj : flowEntries) {
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700752 flowEntryObj.setUserState("FE_USER_DELETE");
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700753 flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700754 }
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700755 for (FlowEntry flowEntry : newDataPath.flowEntries()) {
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700756 addFlowEntry(flowObj, flowEntry);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700757 }
758
759 //
760 // Set the Data Path Summary
761 //
762 String dataPathSummaryStr = newDataPath.dataPathSummary();
763 flowObj.setDataPathSummary(dataPathSummaryStr);
764
765 return true;
766 }
767
768 /**
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700769 * Reconcile all flows in a set.
770 *
771 * @param flowObjSet the set of flows that need to be reconciliated.
772 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700773 private void reconcileFlows(Iterable<IFlowPath> flowObjSet) {
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700774 if (! flowObjSet.iterator().hasNext())
775 return;
Pavlin Radoslavov0eeb15d2013-04-05 10:23:51 -0700776 // TODO: Not implemented/used yet.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700777 }
778
779 /**
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700780 * Install a Flow Entry on a switch.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700781 *
Pavlin Radoslavov2b858f82013-03-28 11:37:37 -0700782 * @param mySwitch the switch to install the Flow Entry into.
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700783 * @param flowObj the flow path object for the flow entry to install.
784 * @param flowEntryObj the flow entry object to install.
785 * @return true on success, otherwise false.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700786 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700787 private boolean installFlowEntry(IOFSwitch mySwitch, IFlowPath flowObj,
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700788 IFlowEntry flowEntryObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700789 return FlowSwitchOperation.installFlowEntry(
790 floodlightProvider.getOFMessageFactory(),
791 messageDamper, mySwitch, flowObj, flowEntryObj);
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700792 }
793
794 /**
795 * Install a Flow Entry on a switch.
796 *
797 * @param mySwitch the switch to install the Flow Entry into.
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700798 * @param flowPath the flow path for the flow entry to install.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700799 * @param flowEntry the flow entry to install.
800 * @return true on success, otherwise false.
801 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700802 private boolean installFlowEntry(IOFSwitch mySwitch, FlowPath flowPath,
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700803 FlowEntry flowEntry) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700804 return FlowSwitchOperation.installFlowEntry(
805 floodlightProvider.getOFMessageFactory(),
806 messageDamper, mySwitch, flowPath, flowEntry);
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700807 }
808
809 /**
810 * Remove a Flow Entry from a switch.
811 *
Pavlin Radoslavov2b858f82013-03-28 11:37:37 -0700812 * @param mySwitch the switch to remove the Flow Entry from.
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700813 * @param flowPath the flow path for the flow entry to remove.
Pavlin Radoslavov6b6f4a82013-03-28 03:30:00 -0700814 * @param flowEntry the flow entry to remove.
815 * @return true on success, otherwise false.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700816 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700817 private boolean removeFlowEntry(IOFSwitch mySwitch, FlowPath flowPath,
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700818 FlowEntry flowEntry) {
Pavlin Radoslavov6b6f4a82013-03-28 03:30:00 -0700819 //
820 // The installFlowEntry() method implements both installation
821 // and removal of flow entries.
822 //
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700823 return (installFlowEntry(mySwitch, flowPath, flowEntry));
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700824 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700825
826 /**
827 * Receive a notification that a Flow is added.
828 *
829 * @param flowPath the flow that is added.
830 */
831 @Override
832 public void notificationRecvFlowAdded(FlowPath flowPath) {
833 // TODO
834 }
835
836 /**
837 * Receive a notification that a Flow is removed.
838 *
839 * @param flowPath the flow that is removed.
840 */
841 @Override
842 public void notificationRecvFlowRemoved(FlowPath flowPath) {
843 // TODO
844 }
845
846 /**
847 * Receive a notification that a Flow is updated.
848 *
849 * @param flowPath the flow that is updated.
850 */
851 @Override
852 public void notificationRecvFlowUpdated(FlowPath flowPath) {
853 // TODO
854 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800855}