blob: cd1c994d51696947cb667a4f711d86e7d115591d [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 Radoslavov3f9ba652013-10-25 17:19:01 -070010import java.util.concurrent.BlockingQueue;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080011import java.util.concurrent.Executors;
Pavlin Radoslavov3f9ba652013-10-25 17:19:01 -070012import java.util.concurrent.LinkedBlockingQueue;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080013import java.util.concurrent.ScheduledExecutorService;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080014import java.util.concurrent.TimeUnit;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080015
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080016import net.floodlightcontroller.core.IFloodlightProviderService;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080017import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080018import net.floodlightcontroller.core.module.FloodlightModuleContext;
19import net.floodlightcontroller.core.module.FloodlightModuleException;
20import net.floodlightcontroller.core.module.IFloodlightModule;
21import net.floodlightcontroller.core.module.IFloodlightService;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080022import net.floodlightcontroller.restserver.IRestApiService;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080023import net.floodlightcontroller.util.OFMessageDamper;
Pavlin Radoslavov05378272013-10-19 23:23:05 -070024
25import net.onrc.onos.datagrid.IDatagridService;
Pankaj Berde38646d62013-06-21 11:34:04 -070026import net.onrc.onos.graph.GraphDBOperation;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070027import net.onrc.onos.ofcontroller.core.INetMapStorage;
28import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
29import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -070030import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
HIGUCHI Yuta60a10142013-06-14 15:50:10 -070031import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
Pavlin Radoslavov1278ac72013-10-16 04:43:49 -070032import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070033import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -070034import net.onrc.onos.ofcontroller.topology.TopologyElement;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070035import net.onrc.onos.ofcontroller.util.*;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080036
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080037import org.openflow.protocol.OFType;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080038import org.slf4j.Logger;
39import org.slf4j.LoggerFactory;
40
admin944ef4f2013-10-08 17:48:37 -070041/**
HIGUCHI Yutaeb567aa2013-10-08 19:27:35 -070042 * Flow Manager class for handling the network flows.
admin944ef4f2013-10-08 17:48:37 -070043 */
Pavlin Radoslavov5adf1522013-04-04 17:43:41 -070044public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080045
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070046 protected GraphDBOperation dbHandler;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080047
Jonathan Hart50a94982013-04-10 14:49:51 -070048 protected volatile IFloodlightProviderService floodlightProvider;
Pavlin Radoslavov1278ac72013-10-16 04:43:49 -070049 protected volatile ITopologyNetService topologyNetService;
Pavlin Radoslavov05378272013-10-19 23:23:05 -070050 protected volatile IDatagridService datagridService;
51 protected IRestApiService restApi;
Pavlin Radoslavov571cff92013-03-20 02:01:32 -070052 protected FloodlightModuleContext context;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080053
54 protected OFMessageDamper messageDamper;
55
Pavlin Radoslavov78c4e492013-03-12 17:17:48 -070056 //
57 // TODO: Values copied from elsewhere (class LearningSwitch).
58 // The local copy should go away!
59 //
60 protected static final int OFMESSAGE_DAMPER_CAPACITY = 50000; // TODO: find sweet spot
61 protected static final int OFMESSAGE_DAMPER_TIMEOUT = 250; // ms
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080062
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +000063 // Flow Entry ID generation state
64 private static Random randomGenerator = new Random();
65 private static int nextFlowEntryIdPrefix = 0;
66 private static int nextFlowEntryIdSuffix = 0;
67 private static long nextFlowEntryId = 0;
68
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080069 /** The logger. */
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070070 private final static Logger log = LoggerFactory.getLogger(FlowManager.class);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080071
72 // The periodic task(s)
Jonathan Hart50a94982013-04-10 14:49:51 -070073 private ScheduledExecutorService mapReaderScheduler;
74 private ScheduledExecutorService shortestPathReconcileScheduler;
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -070075
Pavlin Radoslavov3f9ba652013-10-25 17:19:01 -070076 // The queue with Flow Path updates
77 protected BlockingQueue<EventEntry<FlowPath>> flowPathEvents =
78 new LinkedBlockingQueue<EventEntry<FlowPath>>();
79
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -070080 // The queue with Topology Element updates
81 protected BlockingQueue<EventEntry<TopologyElement>> topologyEvents =
82 new LinkedBlockingQueue<EventEntry<TopologyElement>>();
83
admin944ef4f2013-10-08 17:48:37 -070084 /**
85 * Periodic task for reading the Flow Entries and pushing changes
86 * into the switches.
87 */
Pavlin Radoslavov571cff92013-03-20 02:01:32 -070088 final Runnable mapReader = new Runnable() {
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080089 public void run() {
Pavlin Radoslavova75caea2013-04-10 19:11:26 -070090 try {
91 runImpl();
92 } catch (Exception e) {
93 log.debug("Exception processing All Flow Entries from the Network MAP: ", e);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070094 dbHandler.rollback();
Pavlin Radoslavova75caea2013-04-10 19:11:26 -070095 return;
96 }
97 }
98
99 private void runImpl() {
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700100 long startTime = System.nanoTime();
101 int counterAllFlowEntries = 0;
102 int counterMyNotUpdatedFlowEntries = 0;
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700103
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800104 if (floodlightProvider == null) {
105 log.debug("FloodlightProvider service not found!");
106 return;
107 }
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000108 Map<Long, IOFSwitch> mySwitches =
109 floodlightProvider.getSwitches();
Pankaj Berdebf51e4f2013-10-03 17:49:23 -0700110 if (mySwitches.isEmpty()) {
Pankaj Berde85a877b2013-10-03 18:26:35 -0700111 log.trace("No switches controlled");
Pankaj Berdebf51e4f2013-10-03 17:49:23 -0700112 return;
113 }
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700114 LinkedList<IFlowEntry> addFlowEntries =
115 new LinkedList<IFlowEntry>();
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000116 LinkedList<IFlowEntry> deleteFlowEntries =
117 new LinkedList<IFlowEntry>();
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700118
119 //
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700120 // Fetch all Flow Entries which need to be updated and select
121 // only my Flow Entries that need to be updated into the
122 // switches.
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700123 //
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000124 Iterable<IFlowEntry> allFlowEntries =
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700125 dbHandler.getAllSwitchNotUpdatedFlowEntries();
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700126 for (IFlowEntry flowEntryObj : allFlowEntries) {
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700127 counterAllFlowEntries++;
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000128
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000129 String dpidStr = flowEntryObj.getSwitchDpid();
130 if (dpidStr == null)
131 continue;
132 Dpid dpid = new Dpid(dpidStr);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800133 IOFSwitch mySwitch = mySwitches.get(dpid.value());
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000134 if (mySwitch == null)
135 continue; // Ignore the entry: not my switch
136
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700137 IFlowPath flowObj =
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700138 dbHandler.getFlowPathByFlowEntry(flowEntryObj);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700139 if (flowObj == null)
140 continue; // Should NOT happen
141 if (flowObj.getFlowId() == null)
142 continue; // Invalid entry
143
144 //
145 // NOTE: For now we process the DELETE before the ADD
146 // to cover the more common scenario.
147 // TODO: This is error prone and needs to be fixed!
148 //
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000149 String userState = flowEntryObj.getUserState();
150 if (userState == null)
151 continue;
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700152 if (userState.equals("FE_USER_DELETE")) {
153 // An entry that needs to be deleted.
154 deleteFlowEntries.add(flowEntryObj);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700155 installFlowEntry(mySwitch, flowObj, flowEntryObj);
156 } else {
157 addFlowEntries.add(flowEntryObj);
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700158 }
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700159 counterMyNotUpdatedFlowEntries++;
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700160 }
161
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700162 //
163 // Process the Flow Entries that need to be added
164 //
165 for (IFlowEntry flowEntryObj : addFlowEntries) {
166 IFlowPath flowObj =
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700167 dbHandler.getFlowPathByFlowEntry(flowEntryObj);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700168 if (flowObj == null)
169 continue; // Should NOT happen
170 if (flowObj.getFlowId() == null)
171 continue; // Invalid entry
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700172
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700173 Dpid dpid = new Dpid(flowEntryObj.getSwitchDpid());
Pavlin Radoslavov01391c92013-03-14 17:13:21 -0700174 IOFSwitch mySwitch = mySwitches.get(dpid.value());
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000175 if (mySwitch == null)
176 continue; // Shouldn't happen
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700177 installFlowEntry(mySwitch, flowObj, flowEntryObj);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800178 }
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000179
180 //
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000181 // Delete all Flow Entries marked for deletion from the
Pavlin Radoslavov44a3dcd2013-04-04 18:42:56 -0700182 // Network MAP.
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000183 //
184 // TODO: We should use the OpenFlow Barrier mechanism
185 // to check for errors, and delete the Flow Entries after the
186 // Barrier message is received.
187 //
188 while (! deleteFlowEntries.isEmpty()) {
189 IFlowEntry flowEntryObj = deleteFlowEntries.poll();
190 IFlowPath flowObj =
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700191 dbHandler.getFlowPathByFlowEntry(flowEntryObj);
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000192 if (flowObj == null) {
193 log.debug("Did not find FlowPath to be deleted");
194 continue;
195 }
196 flowObj.removeFlowEntry(flowEntryObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700197 dbHandler.removeFlowEntry(flowEntryObj);
Masayoshi Kobayashic9da09e2013-03-26 20:52:02 +0000198 }
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700199
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700200 dbHandler.commit();
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700201
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700202 long estimatedTime = System.nanoTime() - startTime;
203 double rate = 0.0;
204 if (estimatedTime > 0)
205 rate = ((double)counterAllFlowEntries * 1000000000) / estimatedTime;
206 String logMsg = "MEASUREMENT: Processed AllFlowEntries: " +
207 counterAllFlowEntries + " MyNotUpdatedFlowEntries: " +
208 counterMyNotUpdatedFlowEntries + " in " +
209 (double)estimatedTime / 1000000000 + " sec: " +
210 rate + " paths/s";
211 log.debug(logMsg);
212 }
213 };
214
admin944ef4f2013-10-08 17:48:37 -0700215 /**
216 * Periodic task for reading the Flow Paths and recomputing the
217 * shortest paths.
218 */
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700219 final Runnable shortestPathReconcile = new Runnable() {
220 public void run() {
Pavlin Radoslavova75caea2013-04-10 19:11:26 -0700221 try {
222 runImpl();
223 } catch (Exception e) {
224 log.debug("Exception processing All Flows from the Network MAP: ", e);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700225 dbHandler.rollback();
Pavlin Radoslavova75caea2013-04-10 19:11:26 -0700226 return;
227 }
228 }
229
230 private void runImpl() {
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700231 long startTime = System.nanoTime();
232 int counterAllFlowPaths = 0;
233 int counterMyFlowPaths = 0;
234
235 if (floodlightProvider == null) {
236 log.debug("FloodlightProvider service not found!");
237 return;
238 }
239 Map<Long, IOFSwitch> mySwitches =
240 floodlightProvider.getSwitches();
Pankaj Berdebf51e4f2013-10-03 17:49:23 -0700241 if (mySwitches.isEmpty()) {
Pankaj Berde85a877b2013-10-03 18:26:35 -0700242 log.trace("No switches controlled");
Pankaj Berdebf51e4f2013-10-03 17:49:23 -0700243 return;
244 }
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700245 LinkedList<IFlowPath> deleteFlows = new LinkedList<IFlowPath>();
246
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700247 //
248 // Fetch and recompute the Shortest Path for those
249 // Flow Paths this controller is responsible for.
250 //
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700251 Topology topology = topologyNetService.newDatabaseTopology();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700252 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700253 for (IFlowPath flowPathObj : allFlowPaths) {
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700254 counterAllFlowPaths++;
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700255 if (flowPathObj == null)
256 continue;
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700257
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700258 String srcDpidStr = flowPathObj.getSrcSwitch();
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000259 if (srcDpidStr == null)
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700260 continue;
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700261 Dpid srcDpid = new Dpid(srcDpidStr);
Pavlin Radoslavov2659a0b2013-04-03 20:30:40 -0700262 //
263 // Use the source DPID as a heuristic to decide
264 // which controller is responsible for maintaining the
265 // shortest path.
266 // NOTE: This heuristic is error-prone: if the switch
267 // goes away and no controller is responsible for that
268 // switch, then the original Flow Path is not cleaned-up
269 //
270 IOFSwitch mySwitch = mySwitches.get(srcDpid.value());
271 if (mySwitch == null)
272 continue; // Ignore: not my responsibility
273
Pavlin Radoslavov99d1b152013-04-09 22:57:33 -0700274 // Test the Data Path Summary string
275 String dataPathSummaryStr = flowPathObj.getDataPathSummary();
276 if (dataPathSummaryStr == null)
277 continue; // Could be invalid entry?
278 if (dataPathSummaryStr.isEmpty())
279 continue; // No need to maintain this flow
280
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000281 //
282 // Test whether we need to complete the Flow cleanup,
283 // if the Flow has been deleted by the user.
284 //
285 String flowUserState = flowPathObj.getUserState();
286 if ((flowUserState != null)
287 && flowUserState.equals("FE_USER_DELETE")) {
288 Iterable<IFlowEntry> flowEntries = flowPathObj.getFlowEntries();
Yuta HIGUCHI2ded2dd2013-10-09 18:06:41 -0700289 final boolean empty = !flowEntries.iterator().hasNext();
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000290 if (empty)
291 deleteFlows.add(flowPathObj);
292 }
293
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000294 // Fetch the fields needed to recompute the shortest path
295 Short srcPortShort = flowPathObj.getSrcPort();
296 String dstDpidStr = flowPathObj.getDstSwitch();
297 Short dstPortShort = flowPathObj.getDstPort();
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700298 String flowPathTypeStr = flowPathObj.getFlowPathType();
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700299 Long flowPathFlagsLong = flowPathObj.getFlowPathFlags();
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000300 if ((srcPortShort == null) ||
301 (dstDpidStr == null) ||
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700302 (dstPortShort == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700303 (flowPathTypeStr == null) ||
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700304 (flowPathFlagsLong == null)) {
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000305 continue;
306 }
307
308 Port srcPort = new Port(srcPortShort);
309 Dpid dstDpid = new Dpid(dstDpidStr);
310 Port dstPort = new Port(dstPortShort);
311 SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
312 SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700313 FlowPathType flowPathType = FlowPathType.valueOf(flowPathTypeStr);
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700314 FlowPathFlags flowPathFlags = new FlowPathFlags(flowPathFlagsLong);
Pavlin Radoslavov6db8c6e2013-04-08 00:14:07 +0000315
Pavlin Radoslavov2659a0b2013-04-03 20:30:40 -0700316 counterMyFlowPaths++;
317
Pavlin Radoslavov832aa652013-03-29 16:21:59 -0700318 //
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700319 // NOTE: Using here the regular getDatabaseShortestPath()
320 // method won't work here, because that method calls
321 // internally "conn.endTx(Transaction.COMMIT)", and that
322 // will invalidate all handlers to the Titan database.
Pavlin Radoslavov832aa652013-03-29 16:21:59 -0700323 // If we want to experiment with calling here
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700324 // getDatabaseShortestPath(), we need to refactor that code
Pavlin Radoslavov832aa652013-03-29 16:21:59 -0700325 // to avoid closing the transaction.
326 //
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700327 DataPath dataPath =
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700328 topologyNetService.getTopologyShortestPath(
329 topology,
330 srcSwitchPort,
331 dstSwitchPort);
Pavlin Radoslavov4a325822013-04-02 22:16:59 +0000332 if (dataPath == null) {
333 // We need the DataPath to compare the paths
334 dataPath = new DataPath();
335 dataPath.setSrcPort(srcSwitchPort);
336 dataPath.setDstPort(dstSwitchPort);
337 }
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700338 dataPath.applyFlowPathFlags(flowPathFlags);
Pavlin Radoslavov4a325822013-04-02 22:16:59 +0000339
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700340 String newDataPathSummaryStr = dataPath.dataPathSummary();
341 if (dataPathSummaryStr.equals(newDataPathSummaryStr))
342 continue; // Nothing changed
343
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700344 reconcileFlow(flowPathObj, dataPath);
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700345 }
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000346
347 //
348 // Delete all leftover Flows marked for deletion from the
349 // Network MAP.
350 //
351 while (! deleteFlows.isEmpty()) {
352 IFlowPath flowPathObj = deleteFlows.poll();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700353 dbHandler.removeFlowPath(flowPathObj);
Pavlin Radoslavov710e2a72013-04-08 02:31:05 +0000354 }
355
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700356 topologyNetService.dropTopology(topology);
Pavlin Radoslavov0391b9d2013-03-29 11:54:25 -0700357
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700358 dbHandler.commit();
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700359
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700360 long estimatedTime = System.nanoTime() - startTime;
Pavlin Radoslavov1552f952013-04-04 17:51:22 -0700361 double rate = 0.0;
362 if (estimatedTime > 0)
363 rate = ((double)counterAllFlowPaths * 1000000000) / estimatedTime;
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700364 String logMsg = "MEASUREMENT: Processed AllFlowPaths: " +
Pavlin Radoslavov1552f952013-04-04 17:51:22 -0700365 counterAllFlowPaths + " MyFlowPaths: " +
366 counterMyFlowPaths + " in " +
367 (double)estimatedTime / 1000000000 + " sec: " +
368 rate + " paths/s";
Pavlin Radoslavov42f02ba2013-04-03 20:07:30 -0700369 log.debug(logMsg);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800370 }
371 };
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700372
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800373
admin944ef4f2013-10-08 17:48:37 -0700374 /**
375 * Initialize the Flow Manager.
376 *
377 * @param conf the Graph Database configuration string.
378 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800379 @Override
380 public void init(String conf) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700381 dbHandler = new GraphDBOperation(conf);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800382 }
383
admin944ef4f2013-10-08 17:48:37 -0700384 /**
385 * Shutdown the Flow Manager operation.
386 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800387 public void finalize() {
Toshio Koide9fe1cb22013-06-13 13:51:11 -0700388 close();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800389 }
390
admin944ef4f2013-10-08 17:48:37 -0700391 /**
392 * Shutdown the Flow Manager operation.
393 */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800394 @Override
395 public void close() {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700396 datagridService.deregisterFlowService(this);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700397 dbHandler.close();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800398 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800399
admin944ef4f2013-10-08 17:48:37 -0700400 /**
401 * Get the collection of offered module services.
402 *
403 * @return the collection of offered module services.
404 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800405 @Override
406 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
407 Collection<Class<? extends IFloodlightService>> l =
408 new ArrayList<Class<? extends IFloodlightService>>();
409 l.add(IFlowService.class);
410 return l;
411 }
412
admin944ef4f2013-10-08 17:48:37 -0700413 /**
414 * Get the collection of implemented services.
415 *
416 * @return the collection of implemented services.
417 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800418 @Override
419 public Map<Class<? extends IFloodlightService>, IFloodlightService>
420 getServiceImpls() {
421 Map<Class<? extends IFloodlightService>,
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -0700422 IFloodlightService> m =
423 new HashMap<Class<? extends IFloodlightService>,
424 IFloodlightService>();
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800425 m.put(IFlowService.class, this);
426 return m;
427 }
428
admin944ef4f2013-10-08 17:48:37 -0700429 /**
430 * Get the collection of modules this module depends on.
431 *
432 * @return the collection of modules this module depends on.
433 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800434 @Override
435 public Collection<Class<? extends IFloodlightService>>
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700436 getModuleDependencies() {
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800437 Collection<Class<? extends IFloodlightService>> l =
438 new ArrayList<Class<? extends IFloodlightService>>();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800439 l.add(IFloodlightProviderService.class);
Pavlin Radoslavove9a3ef92013-10-18 18:46:45 -0700440 l.add(INetworkGraphService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700441 l.add(IDatagridService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800442 l.add(IRestApiService.class);
443 return l;
444 }
445
admin944ef4f2013-10-08 17:48:37 -0700446 /**
447 * Initialize the module.
448 *
449 * @param context the module context to use for the initialization.
450 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800451 @Override
452 public void init(FloodlightModuleContext context)
453 throws FloodlightModuleException {
Pavlin Radoslavov571cff92013-03-20 02:01:32 -0700454 this.context = context;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800455 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700456 topologyNetService = context.getServiceImpl(ITopologyNetService.class);
457 datagridService = context.getServiceImpl(IDatagridService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800458 restApi = context.getServiceImpl(IRestApiService.class);
Pavlin Radoslavov05378272013-10-19 23:23:05 -0700459
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800460 messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
461 EnumSet.of(OFType.FLOW_MOD),
462 OFMESSAGE_DAMPER_TIMEOUT);
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -0700463
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700464 this.init("");
465
admin944ef4f2013-10-08 17:48:37 -0700466 mapReaderScheduler = Executors.newScheduledThreadPool(1);
467 shortestPathReconcileScheduler = Executors.newScheduledThreadPool(1);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800468 }
469
admin944ef4f2013-10-08 17:48:37 -0700470 /**
471 * Get the next Flow Entry ID to use.
472 *
473 * @return the next Flow Entry ID to use.
474 */
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700475 public synchronized long getNextFlowEntryId() {
Pavlin Radoslavov0b22d0e2013-04-02 01:12:46 +0000476 //
477 // Generate the next Flow Entry ID.
478 // NOTE: For now, the higher 32 bits are random, and
479 // the lower 32 bits are sequential.
480 // In the future, we need a better allocation mechanism.
481 //
482 if ((nextFlowEntryIdSuffix & 0xffffffffL) == 0xffffffffL) {
483 nextFlowEntryIdPrefix = randomGenerator.nextInt();
484 nextFlowEntryIdSuffix = 0;
485 } else {
486 nextFlowEntryIdSuffix++;
487 }
488 long result = (long)nextFlowEntryIdPrefix << 32;
489 result = result | (0xffffffffL & nextFlowEntryIdSuffix);
490 return result;
491 }
492
admin944ef4f2013-10-08 17:48:37 -0700493 /**
494 * Startup module operation.
495 *
496 * @param context the module context to use for the startup.
497 */
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800498 @Override
499 public void startUp(FloodlightModuleContext context) {
admin944ef4f2013-10-08 17:48:37 -0700500 restApi.addRestletRoutable(new FlowWebRoutable());
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700501
admin944ef4f2013-10-08 17:48:37 -0700502 // Initialize the Flow Entry ID generator
503 nextFlowEntryIdPrefix = randomGenerator.nextInt();
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700504
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700505 // Register with the Datagrid Service
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700506 datagridService.registerFlowService(this);
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700507
508 // Obtain the initial Topology state
509 Collection<TopologyElement> topologyElements =
510 datagridService.getAllTopologyElements();
511 for (TopologyElement topologyElement : topologyElements) {
512 EventEntry<TopologyElement> eventEntry =
513 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
514 topologyEvents.add(eventEntry);
515 }
516
517 // Obtain the initial Flow state
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700518 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
Pavlin Radoslavov3f9ba652013-10-25 17:19:01 -0700519 for (FlowPath flowPath : flowPaths) {
520 EventEntry<FlowPath> eventEntry =
521 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
522 flowPathEvents.add(eventEntry);
523 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700524
Pavlin Radoslavov3f9ba652013-10-25 17:19:01 -0700525 // Schedule the periodic tasks
admin944ef4f2013-10-08 17:48:37 -0700526 mapReaderScheduler.scheduleAtFixedRate(
527 mapReader, 3, 3, TimeUnit.SECONDS);
528 shortestPathReconcileScheduler.scheduleAtFixedRate(
529 shortestPathReconcile, 3, 3, TimeUnit.SECONDS);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800530 }
531
532 /**
533 * Add a flow.
534 *
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800535 * @param flowPath the Flow Path to install.
536 * @param flowId the return-by-reference Flow ID as assigned internally.
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700537 * @param dataPathSummaryStr the data path summary string if the added
538 * flow will be maintained internally, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800539 * @return true on success, otherwise false.
540 */
541 @Override
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700542 public boolean addFlow(FlowPath flowPath, FlowId flowId,
543 String dataPathSummaryStr) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700544 if (FlowDatabaseOperation.addFlow(this, dbHandler, flowPath, flowId,
545 dataPathSummaryStr)) {
546 datagridService.notificationSendFlowAdded(flowPath);
547 return true;
548 }
549 return false;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800550 }
551
552 /**
Pavlin Radoslavov9425f702013-04-04 19:55:07 -0700553 * Add a flow entry to the Network MAP.
554 *
555 * @param flowObj the corresponding Flow Path object for the Flow Entry.
556 * @param flowEntry the Flow Entry to install.
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700557 * @return the added Flow Entry object on success, otherwise null.
Pavlin Radoslavov9425f702013-04-04 19:55:07 -0700558 */
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700559 private IFlowEntry addFlowEntry(IFlowPath flowObj, FlowEntry flowEntry) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700560 return FlowDatabaseOperation.addFlowEntry(this, dbHandler, flowObj,
561 flowEntry);
Pavlin Radoslavov9425f702013-04-04 19:55:07 -0700562 }
563
564 /**
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000565 * Delete all previously added flows.
566 *
567 * @return true on success, otherwise false.
568 */
569 @Override
570 public boolean deleteAllFlows() {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700571 if (FlowDatabaseOperation.deleteAllFlows(dbHandler)) {
572 datagridService.notificationSendAllFlowsRemoved();
573 return true;
574 }
575 return false;
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000576 }
577
578 /**
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800579 * Delete a previously added flow.
580 *
581 * @param flowId the Flow ID of the flow to delete.
582 * @return true on success, otherwise false.
583 */
584 @Override
585 public boolean deleteFlow(FlowId flowId) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700586 if (FlowDatabaseOperation.deleteFlow(dbHandler, flowId)) {
587 datagridService.notificationSendFlowRemoved(flowId);
588 return true;
589 }
590 return false;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800591 }
592
593 /**
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000594 * Clear the state for all previously added flows.
595 *
596 * @return true on success, otherwise false.
597 */
598 @Override
599 public boolean clearAllFlows() {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700600 if (FlowDatabaseOperation.clearAllFlows(dbHandler)) {
601 datagridService.notificationSendAllFlowsRemoved();
602 return true;
603 }
604 return false;
Pavlin Radoslavovbaea9242013-05-08 00:20:09 +0000605 }
606
607 /**
Pavlin Radoslavov916832f2013-03-14 17:48:41 -0700608 * Clear the state for a previously added flow.
609 *
610 * @param flowId the Flow ID of the flow to clear.
611 * @return true on success, otherwise false.
612 */
613 @Override
614 public boolean clearFlow(FlowId flowId) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700615 if (FlowDatabaseOperation.clearFlow(dbHandler, flowId)) {
616 datagridService.notificationSendFlowRemoved(flowId);
617 return true;
618 }
619 return false;
Pavlin Radoslavov916832f2013-03-14 17:48:41 -0700620 }
621
622 /**
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800623 * Get a previously added flow.
624 *
625 * @param flowId the Flow ID of the flow to get.
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800626 * @return the Flow Path if found, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800627 */
628 @Override
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800629 public FlowPath getFlow(FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700630 return FlowDatabaseOperation.getFlow(dbHandler, flowId);
631 }
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800632
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700633 /**
634 * Get all installed flows by all installers.
635 *
636 * @return the Flow Paths if found, otherwise null.
637 */
638 @Override
639 public ArrayList<FlowPath> getAllFlows() {
640 return FlowDatabaseOperation.getAllFlows(dbHandler);
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800641 }
642
643 /**
644 * Get all previously added flows by a specific installer for a given
645 * data path endpoints.
646 *
647 * @param installerId the Caller ID of the installer of the flow to get.
648 * @param dataPathEndpoints the data path endpoints of the flow to get.
649 * @return the Flow Paths if found, otherwise null.
650 */
651 @Override
652 public ArrayList<FlowPath> getAllFlows(CallerId installerId,
653 DataPathEndpoints dataPathEndpoints) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700654 return FlowDatabaseOperation.getAllFlows(dbHandler, installerId,
655 dataPathEndpoints);
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800656 }
657
658 /**
659 * Get all installed flows by all installers for given data path endpoints.
660 *
661 * @param dataPathEndpoints the data path endpoints of the flows to get.
662 * @return the Flow Paths if found, otherwise null.
663 */
664 @Override
665 public ArrayList<FlowPath> getAllFlows(DataPathEndpoints dataPathEndpoints) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700666 return FlowDatabaseOperation.getAllFlows(dbHandler, dataPathEndpoints);
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800667 }
668
669 /**
admin944ef4f2013-10-08 17:48:37 -0700670 * Get summary of all installed flows by all installers in a given range.
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700671 *
admin944ef4f2013-10-08 17:48:37 -0700672 * @param flowId the Flow ID of the first flow in the flow range to get.
HIGUCHI Yutaeb567aa2013-10-08 19:27:35 -0700673 * @param maxFlows the maximum number of flows to be returned.
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700674 * @return the Flow Paths if found, otherwise null.
675 */
676 @Override
Pavlin Radoslavov50e532e2013-10-20 02:07:51 -0700677 public ArrayList<IFlowPath> getAllFlowsSummary(FlowId flowId,
678 int maxFlows) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700679 return FlowDatabaseOperation.getAllFlowsSummary(dbHandler, flowId,
680 maxFlows);
Umesh Krishnaswamy57a32a92013-03-21 14:21:15 -0700681 }
682
683 /**
admin944ef4f2013-10-08 17:48:37 -0700684 * Get all Flows information, without the associated Flow Entries.
685 *
686 * @return all Flows information, without the associated Flow Entries.
687 */
688 public ArrayList<IFlowPath> getAllFlowsWithoutFlowEntries() {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700689 return FlowDatabaseOperation.getAllFlowsWithoutFlowEntries(dbHandler);
Pavlin Radoslavov99b12752013-04-04 17:28:06 -0700690 }
691
692 /**
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700693 * Add and maintain a shortest-path flow.
694 *
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700695 * NOTE: The Flow Path argument does NOT contain flow entries.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700696 *
697 * @param flowPath the Flow Path with the endpoints and the match
698 * conditions to install.
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700699 * @return the added shortest-path flow on success, otherwise null.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700700 */
701 @Override
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700702 public FlowPath addAndMaintainShortestPathFlow(FlowPath flowPath) {
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700703 //
Pavlin Radoslavov8b4b0592013-04-10 04:33:33 +0000704 // Don't do the shortest path computation here.
705 // Instead, let the Flow reconciliation thread take care of it.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700706 //
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700707
Pavlin Radoslavov8b4b0592013-04-10 04:33:33 +0000708 // We need the DataPath to populate the Network MAP
709 DataPath dataPath = new DataPath();
710 dataPath.setSrcPort(flowPath.dataPath().srcPort());
711 dataPath.setDstPort(flowPath.dataPath().dstPort());
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700712
713 //
714 // Prepare the computed Flow Path
715 //
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700716 FlowPath computedFlowPath = new FlowPath();
717 computedFlowPath.setFlowId(new FlowId(flowPath.flowId().value()));
718 computedFlowPath.setInstallerId(new CallerId(flowPath.installerId().value()));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700719 computedFlowPath.setFlowPathType(flowPath.flowPathType());
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700720 computedFlowPath.setFlowPathFlags(new FlowPathFlags(flowPath.flowPathFlags().flags()));
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700721 computedFlowPath.setDataPath(dataPath);
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700722 computedFlowPath.setFlowEntryMatch(new FlowEntryMatch(flowPath.flowEntryMatch()));
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700723 computedFlowPath.setFlowEntryActions(new FlowEntryActions(flowPath.flowEntryActions()));
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700724
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700725 FlowId flowId = new FlowId();
Pavlin Radoslavov8b4b0592013-04-10 04:33:33 +0000726 String dataPathSummaryStr = dataPath.dataPathSummary();
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700727 if (! addFlow(computedFlowPath, flowId, dataPathSummaryStr))
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700728 return null;
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700729
730 // TODO: Mark the flow for maintenance purpose
731
Pavlin Radoslavove0575292013-03-28 05:35:25 -0700732 return (computedFlowPath);
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700733 }
734
735 /**
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700736 * Reconcile a flow.
737 *
738 * @param flowObj the flow that needs to be reconciliated.
739 * @param newDataPath the new data path to use.
740 * @return true on success, otherwise false.
741 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700742 private boolean reconcileFlow(IFlowPath flowObj, DataPath newDataPath) {
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700743
744 //
745 // Set the incoming port matching and the outgoing port output
746 // actions for each flow entry.
747 //
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700748 int idx = 0;
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700749 for (FlowEntry flowEntry : newDataPath.flowEntries()) {
750 // Set the incoming port matching
751 FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
752 flowEntry.setFlowEntryMatch(flowEntryMatch);
753 flowEntryMatch.enableInPort(flowEntry.inPort());
754
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700755 //
756 // Set the actions
757 //
758 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
759 //
760 // If the first Flow Entry, copy the Flow Path actions to it
761 //
762 if (idx == 0) {
763 String actionsStr = flowObj.getActions();
764 if (actionsStr != null) {
765 FlowEntryActions flowActions = new FlowEntryActions(actionsStr);
766 for (FlowEntryAction action : flowActions.actions())
767 flowEntryActions.addAction(action);
768 }
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700769 }
Pavlin Radoslavov282f4ff2013-07-18 11:21:37 -0700770 idx++;
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700771 //
772 // Add the outgoing port output action
773 //
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700774 FlowEntryAction flowEntryAction = new FlowEntryAction();
775 flowEntryAction.setActionOutput(flowEntry.outPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700776 flowEntryActions.addAction(flowEntryAction);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700777 }
778
779 //
780 // Remove the old Flow Entries, and add the new Flow Entries
781 //
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700782 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700783 for (IFlowEntry flowEntryObj : flowEntries) {
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700784 flowEntryObj.setUserState("FE_USER_DELETE");
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700785 flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700786 }
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700787 for (FlowEntry flowEntry : newDataPath.flowEntries()) {
Pavlin Radoslavov6fb76d12013-04-09 22:52:25 -0700788 addFlowEntry(flowObj, flowEntry);
Pavlin Radoslavov20d35a22013-04-05 10:16:15 -0700789 }
790
791 //
792 // Set the Data Path Summary
793 //
794 String dataPathSummaryStr = newDataPath.dataPathSummary();
795 flowObj.setDataPathSummary(dataPathSummaryStr);
796
797 return true;
798 }
799
800 /**
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700801 * Reconcile all flows in a set.
802 *
803 * @param flowObjSet the set of flows that need to be reconciliated.
804 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700805 private void reconcileFlows(Iterable<IFlowPath> flowObjSet) {
Pavlin Radoslavovdbaaf2e2013-03-29 04:25:55 -0700806 if (! flowObjSet.iterator().hasNext())
807 return;
Pavlin Radoslavov0eeb15d2013-04-05 10:23:51 -0700808 // TODO: Not implemented/used yet.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700809 }
810
811 /**
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700812 * Install a Flow Entry on a switch.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700813 *
Pavlin Radoslavov2b858f82013-03-28 11:37:37 -0700814 * @param mySwitch the switch to install the Flow Entry into.
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700815 * @param flowObj the flow path object for the flow entry to install.
816 * @param flowEntryObj the flow entry object to install.
817 * @return true on success, otherwise false.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700818 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700819 private boolean installFlowEntry(IOFSwitch mySwitch, IFlowPath flowObj,
Pavlin Radoslavovec8e2e62013-04-04 18:18:29 -0700820 IFlowEntry flowEntryObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700821 return FlowSwitchOperation.installFlowEntry(
822 floodlightProvider.getOFMessageFactory(),
823 messageDamper, mySwitch, flowObj, flowEntryObj);
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700824 }
825
826 /**
827 * Install a Flow Entry on a switch.
828 *
829 * @param mySwitch the switch to install the Flow Entry into.
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700830 * @param flowPath the flow path for the flow entry to install.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700831 * @param flowEntry the flow entry to install.
832 * @return true on success, otherwise false.
833 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700834 private boolean installFlowEntry(IOFSwitch mySwitch, FlowPath flowPath,
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700835 FlowEntry flowEntry) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700836 return FlowSwitchOperation.installFlowEntry(
837 floodlightProvider.getOFMessageFactory(),
838 messageDamper, mySwitch, flowPath, flowEntry);
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700839 }
840
841 /**
842 * Remove a Flow Entry from a switch.
843 *
Pavlin Radoslavov2b858f82013-03-28 11:37:37 -0700844 * @param mySwitch the switch to remove the Flow Entry from.
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700845 * @param flowPath the flow path for the flow entry to remove.
Pavlin Radoslavov6b6f4a82013-03-28 03:30:00 -0700846 * @param flowEntry the flow entry to remove.
847 * @return true on success, otherwise false.
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700848 */
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700849 private boolean removeFlowEntry(IOFSwitch mySwitch, FlowPath flowPath,
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700850 FlowEntry flowEntry) {
Pavlin Radoslavov6b6f4a82013-03-28 03:30:00 -0700851 //
852 // The installFlowEntry() method implements both installation
853 // and removal of flow entries.
854 //
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700855 return (installFlowEntry(mySwitch, flowPath, flowEntry));
Pavlin Radoslavovb9fe6b42013-03-27 16:25:05 -0700856 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700857
858 /**
859 * Receive a notification that a Flow is added.
860 *
861 * @param flowPath the flow that is added.
862 */
863 @Override
864 public void notificationRecvFlowAdded(FlowPath flowPath) {
865 // TODO
866 }
867
868 /**
869 * Receive a notification that a Flow is removed.
870 *
871 * @param flowPath the flow that is removed.
872 */
873 @Override
874 public void notificationRecvFlowRemoved(FlowPath flowPath) {
875 // TODO
876 }
877
878 /**
879 * Receive a notification that a Flow is updated.
880 *
881 * @param flowPath the flow that is updated.
882 */
883 @Override
884 public void notificationRecvFlowUpdated(FlowPath flowPath) {
885 // TODO
886 }
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700887
888 /**
889 * Receive a notification that a Topology Element is added.
890 *
891 * @param topologyElement the Topology Element that is added.
892 */
893 @Override
894 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
895 // TODO
896 }
897
898 /**
899 * Receive a notification that a Topology Element is removed.
900 *
901 * @param topologyElement the Topology Element that is removed.
902 */
903 @Override
904 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
905 // TODO
906 }
907
908 /**
909 * Receive a notification that a Topology Element is updated.
910 *
911 * @param topologyElement the Topology Element that is updated.
912 */
913 @Override
914 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
915 // TODO
916 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800917}