blob: 29deb94033948ca547aa07dee504b3638adfe0b7 [file] [log] [blame]
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07003import java.util.ArrayList;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07004import java.util.Collection;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07005import java.util.HashMap;
6import java.util.Iterator;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07007import java.util.LinkedList;
8import java.util.List;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07009import java.util.Map;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070010
11import java.util.concurrent.BlockingQueue;
12import java.util.concurrent.LinkedBlockingQueue;
13
14import net.onrc.onos.datagrid.IDatagridService;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070015import net.onrc.onos.ofcontroller.topology.ShortestPath;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070016import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070017import net.onrc.onos.ofcontroller.topology.TopologyElement;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070018import net.onrc.onos.ofcontroller.topology.TopologyManager;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070019import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070020import net.onrc.onos.ofcontroller.util.EventEntry;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070021import net.onrc.onos.ofcontroller.util.FlowEntry;
22import net.onrc.onos.ofcontroller.util.FlowEntryAction;
23import net.onrc.onos.ofcontroller.util.FlowEntryActions;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070024import net.onrc.onos.ofcontroller.util.FlowEntryId;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070025import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
26import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
27import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070028import net.onrc.onos.ofcontroller.util.FlowId;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070029import net.onrc.onos.ofcontroller.util.FlowPath;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070030import net.onrc.onos.ofcontroller.util.FlowPathUserState;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070031
32import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
34
35/**
36 * Class for implementing the Path Computation and Path Maintenance.
37 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070038class FlowEventHandler extends Thread implements IFlowEventHandlerService {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070039 /** The logger. */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070040 private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070041
42 private FlowManager flowManager; // The Flow Manager to use
43 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070044 private Topology topology; // The network topology
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070045 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070046 private List<FlowEntry> unmatchedFlowEntryUpdates =
47 new LinkedList<FlowEntry>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070048
49 // The queue with Flow Path and Topology Element updates
50 private BlockingQueue<EventEntry<?>> networkEvents =
51 new LinkedBlockingQueue<EventEntry<?>>();
52
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070053 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070054 private List<EventEntry<TopologyElement>> topologyEvents =
55 new LinkedList<EventEntry<TopologyElement>>();
56 private List<EventEntry<FlowPath>> flowPathEvents =
57 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070058 private List<EventEntry<FlowEntry>> flowEntryEvents =
59 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070060
61 /**
62 * Constructor for a given Flow Manager and Datagrid Service.
63 *
64 * @param flowManager the Flow Manager to use.
65 * @param datagridService the Datagrid Service to use.
66 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070067 FlowEventHandler(FlowManager flowManager,
68 IDatagridService datagridService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070069 this.flowManager = flowManager;
70 this.datagridService = datagridService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070071 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070072 }
73
74 /**
75 * Run the thread.
76 */
77 @Override
78 public void run() {
79 //
80 // Obtain the initial Topology state
81 //
82 Collection<TopologyElement> topologyElements =
83 datagridService.getAllTopologyElements();
84 for (TopologyElement topologyElement : topologyElements) {
85 EventEntry<TopologyElement> eventEntry =
86 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
87 topologyEvents.add(eventEntry);
88 }
89 //
90 // Obtain the initial Flow Path state
91 //
92 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
93 for (FlowPath flowPath : flowPaths) {
94 EventEntry<FlowPath> eventEntry =
95 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
96 flowPathEvents.add(eventEntry);
97 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070098 //
99 // Obtain the initial FlowEntry state
100 //
101 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
102 for (FlowEntry flowEntry : flowEntries) {
103 EventEntry<FlowEntry> eventEntry =
104 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
105 flowEntryEvents.add(eventEntry);
106 }
107
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700108 // Process the events (if any)
109 processEvents();
110
111 //
112 // The main loop
113 //
114 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
115 try {
116 while (true) {
117 EventEntry<?> eventEntry = networkEvents.take();
118 collection.add(eventEntry);
119 networkEvents.drainTo(collection);
120
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700121 //
122 // Demultiplex all events:
123 // - EventEntry<TopologyElement>
124 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700125 // - EventEntry<FlowEntry>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700126 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700127 for (EventEntry<?> event : collection) {
128 if (event.eventData() instanceof TopologyElement) {
129 EventEntry<TopologyElement> topologyEventEntry =
130 (EventEntry<TopologyElement>)event;
131 topologyEvents.add(topologyEventEntry);
132 } else if (event.eventData() instanceof FlowPath) {
133 EventEntry<FlowPath> flowPathEventEntry =
134 (EventEntry<FlowPath>)event;
135 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700136 } else if (event.eventData() instanceof FlowEntry) {
137 EventEntry<FlowEntry> flowEntryEventEntry =
138 (EventEntry<FlowEntry>)event;
139 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700140 }
141 }
142 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700143
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700144 // Process the events (if any)
145 processEvents();
146 }
147 } catch (Exception exception) {
148 log.debug("Exception processing Network Events: ", exception);
149 }
150 }
151
152 /**
153 * Process the events (if any)
154 */
155 private void processEvents() {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700156 List<FlowPath> newFlowPaths = new LinkedList<FlowPath>();
157 List<FlowPath> recomputeFlowPaths = new LinkedList<FlowPath>();
158 List<FlowPath> modifiedFlowPaths = new LinkedList<FlowPath>();
159
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700160 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
161 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700162 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700163 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700164
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700165 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700166 // Process the Flow Path events
167 //
168 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
169 FlowPath flowPath = eventEntry.eventData();
170
171 switch (eventEntry.eventType()) {
172 case ENTRY_ADD: {
173 //
174 // Add a new Flow Path
175 //
176 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
177 //
178 // TODO: What to do if the Flow Path already exists?
179 // Remove and then re-add it, or merge the info?
180 // For now, we don't have to do anything.
181 //
182 break;
183 }
184
185 switch (flowPath.flowPathType()) {
186 case FP_TYPE_SHORTEST_PATH:
187 //
188 // Reset the Data Path, in case it was set already, because
189 // we are going to recompute it anyway.
190 //
191 flowPath.flowEntries().clear();
192 recomputeFlowPaths.add(flowPath);
193 break;
194 case FP_TYPE_EXPLICIT_PATH:
195 //
196 // Mark all Flow Entries for installation in the switches.
197 //
198 for (FlowEntry flowEntry : flowPath.flowEntries()) {
199 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
200 }
201 modifiedFlowPaths.add(flowPath);
202 break;
203 }
204 newFlowPaths.add(flowPath);
205
206 break;
207 }
208
209 case ENTRY_REMOVE: {
210 //
211 // Remove an existing Flow Path.
212 //
213 // Find the Flow Path, and mark the Flow and its Flow Entries
214 // for deletion.
215 //
216 FlowPath existingFlowPath =
217 allFlowPaths.get(flowPath.flowId().value());
218 if (existingFlowPath == null)
219 continue; // Nothing to do
220
221 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
222 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
223 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
224 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
225 }
226
227 allFlowPaths.remove(existingFlowPath.flowId());
228 modifiedFlowPaths.add(existingFlowPath);
229
230 break;
231 }
232 }
233 }
234
235 //
236 // Process the topology events
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700237 //
238 boolean isTopologyModified = false;
239 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
240 TopologyElement topologyElement = eventEntry.eventData();
241 switch (eventEntry.eventType()) {
242 case ENTRY_ADD:
243 isTopologyModified = topology.addTopologyElement(topologyElement);
244 break;
245 case ENTRY_REMOVE:
246 isTopologyModified = topology.removeTopologyElement(topologyElement);
247 break;
248 }
249 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700250 if (isTopologyModified) {
251 // TODO: For now, if the topology changes, we recompute all Flows
252 recomputeFlowPaths.addAll(allFlowPaths.values());
253 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700254
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700255 // Add all new Flows
256 for (FlowPath flowPath : newFlowPaths) {
257 allFlowPaths.put(flowPath.flowId().value(), flowPath);
258 }
259
260 // Recompute all affected Flow Paths and keep only the modified
261 for (FlowPath flowPath : recomputeFlowPaths) {
262 if (recomputeFlowPath(flowPath))
263 modifiedFlowPaths.add(flowPath);
264 }
265
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700266 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700267 // Process previously unmatched Flow Entry updates
268 //
269 if ((! flowPathEvents.isEmpty()) && (! unmatchedFlowEntryUpdates.isEmpty())) {
270 List<FlowEntry> remainingUpdates = new LinkedList<FlowEntry>();
271 for (FlowEntry flowEntry : unmatchedFlowEntryUpdates) {
272 if (! updateFlowEntry(flowEntry))
273 remainingUpdates.add(flowEntry);
274 }
275 unmatchedFlowEntryUpdates = remainingUpdates;
276 }
277
278 //
279 // Process the Flow Entry events
280 //
281 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
282 FlowEntry flowEntry = eventEntry.eventData();
283 switch (eventEntry.eventType()) {
284 case ENTRY_ADD:
285 //
286 // Find the corresponding Flow Entry and update it.
287 // If not found, then keep it in a local cache for
288 // later matching.
289 //
290 if (! updateFlowEntry(flowEntry))
291 unmatchedFlowEntryUpdates.add(flowEntry);
292 break;
293 case ENTRY_REMOVE:
294 //
295 // NOTE: For now we remove the Flow Entries based on
296 // local decisions, so no need to remove them because of an
297 // external event.
298 //
299 break;
300 }
301 }
302
303 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700304 // Push the Flow Entries that have been modified
305 //
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700306 flowManager.pushModifiedFlowEntries(modifiedFlowPaths);
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700307
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700308 // Cleanup
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700309 topologyEvents.clear();
310 flowPathEvents.clear();
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700311 flowEntryEvents.clear();
312 }
313
314 /**
315 * Update a Flow Entry because of an external event.
316 *
317 * @param flowEntry the FlowEntry with the new state.
318 * @return true if the Flow Entry was found and updated, otherwise false.
319 */
320 private boolean updateFlowEntry(FlowEntry flowEntry) {
321 if ((! flowEntry.isValidFlowId()) ||
322 (! flowEntry.isValidFlowEntryId())) {
323 //
324 // Ignore events for Flow Entries with invalid Flow ID or
325 // Flow Entry ID.
326 // This shouldn't happen.
327 //
328 return true;
329 }
330
331 FlowPath flowPath = allFlowPaths.get(flowEntry.flowId().value());
332 if (flowPath == null)
333 return false;
334
335 //
336 // Iterate over all Flow Entries and find a match based on the DPID
337 //
338 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
339 if (localFlowEntry.dpid().value() != flowEntry.dpid().value())
340 continue;
341 //
342 // TODO: We might want to check the FlowEntryMatch and
343 // FlowEntryActions to double-check it is the same Flow Entry
344 //
345
346 //
347 // Local Flow Entry match found
348 //
349 if (localFlowEntry.isValidFlowEntryId()) {
350 if (localFlowEntry.flowEntryId().value() !=
351 flowEntry.flowEntryId().value()) {
352 //
353 // Find a local Flow Entry, but the Flow Entry ID doesn't
354 // match. Ignore the event.
355 //
356 return true;
357 }
358 } else {
359 // Update the Flow Entry ID
360 FlowEntryId flowEntryId =
361 new FlowEntryId(flowEntry.flowEntryId().value());
362 localFlowEntry.setFlowEntryId(flowEntryId);
363 }
364
365 //
366 // Update the local Flow Entry.
367 // For now we update only the Flow Entry Switch State
368 //
369 localFlowEntry.setFlowEntrySwitchState(flowEntry.flowEntrySwitchState());
370 return true;
371 }
372
373 return false; // Entry not found
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700374 }
375
376 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700377 * Recompute a Flow Path.
378 *
379 * @param flowPath the Flow Path to recompute.
380 * @return true if the recomputed Flow Path has changed, otherwise false.
381 */
382 private boolean recomputeFlowPath(FlowPath flowPath) {
383 boolean hasChanged = false;
384
385 //
386 // Test whether the Flow Path needs to be recomputed
387 //
388 switch (flowPath.flowPathType()) {
389 case FP_TYPE_SHORTEST_PATH:
390 break;
391 case FP_TYPE_EXPLICIT_PATH:
392 return false; // An explicit path never changes
393 }
394
395 DataPath oldDataPath = flowPath.dataPath();
396
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700397 // Compute the new path
398 DataPath newDataPath = TopologyManager.computeNetworkPath(topology,
399 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700400 if (newDataPath == null) {
401 // We need the DataPath to compare the paths
402 newDataPath = new DataPath();
403 }
404 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
405
406 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700407 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700408 //
409 if (oldDataPath.flowEntries().size() !=
410 newDataPath.flowEntries().size()) {
411 hasChanged = true;
412 } else {
413 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
414 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
415 while (oldIter.hasNext() && newIter.hasNext()) {
416 FlowEntry oldFlowEntry = oldIter.next();
417 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700418 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
419 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700420 hasChanged = true;
421 break;
422 }
423 }
424 }
425 if (! hasChanged)
426 return hasChanged;
427
428 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700429 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700430 // - If a Flow Entry for a switch is in the old data path, but not
431 // in the new data path, then mark it for deletion.
432 // - If a Flow Entry for a switch is in the new data path, but not
433 // in the old data path, then mark it for addition.
434 // - If a Flow Entry for a switch is in both the old and the new
435 // data path, but it has changed, e.g., the incoming and/or outgoing
436 // port(s), then mark the old Flow Entry for deletion, and mark
437 // the new Flow Entry for addition.
438 // - If a Flow Entry for a switch is in both the old and the new
439 // data path, and it hasn't changed, then just keep it.
440 //
441 // NOTE: We use the Switch DPID of each entry to match the entries
442 //
443 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
444 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
445 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
446 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
447
448 // Prepare maps with the Flow Entries, so they are fast to lookup
449 for (FlowEntry flowEntry : oldDataPath.flowEntries())
450 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
451 for (FlowEntry flowEntry : newDataPath.flowEntries())
452 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
453
454 //
455 // Find the old Flow Entries that should be deleted
456 //
457 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
458 FlowEntry newFlowEntry =
459 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
460 if (newFlowEntry == null) {
461 // The old Flow Entry should be deleted
462 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
463 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
464 deletedFlowEntries.add(oldFlowEntry);
465 }
466 }
467
468 //
469 // Find the new Flow Entries that should be added or updated
470 //
471 int idx = 0;
472 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
473 FlowEntry oldFlowEntry =
474 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
475
476 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700477 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
478 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700479 //
480 // Both Flow Entries are same
481 //
482 finalFlowEntries.add(oldFlowEntry);
483 idx++;
484 continue;
485 }
486
487 if (oldFlowEntry != null) {
488 //
489 // The old Flow Entry should be deleted
490 //
491 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
492 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
493 deletedFlowEntries.add(oldFlowEntry);
494 }
495
496 //
497 // Add the new Flow Entry
498 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700499 //
500 // NOTE: Assign only the Flow ID.
501 // The Flow Entry ID is assigned later only for the Flow Entries
502 // this instance is responsible for.
503 //
504 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700505
506 // Set the incoming port matching
507 FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
508 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
509 flowEntryMatch.enableInPort(newFlowEntry.inPort());
510
511 //
512 // Set the actions:
513 // If the first Flow Entry, copy the Flow Path actions to it.
514 //
515 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
516 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
517 FlowEntryActions flowActions =
518 new FlowEntryActions(flowPath.flowEntryActions());
519 for (FlowEntryAction action : flowActions.actions())
520 flowEntryActions.addAction(action);
521 }
522 idx++;
523
524 //
525 // Add the outgoing port output action
526 //
527 FlowEntryAction flowEntryAction = new FlowEntryAction();
528 flowEntryAction.setActionOutput(newFlowEntry.outPort());
529 flowEntryActions.addAction(flowEntryAction);
530
531 //
532 // Set the state of the new Flow Entry
533 //
534 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
535 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
536 finalFlowEntries.add(newFlowEntry);
537 }
538
539 //
540 // Replace the old Flow Entries with the new Flow Entries.
541 // Note that the Flow Entries that will be deleted are added at
542 // the end.
543 //
544 for (FlowEntry flowEntry : deletedFlowEntries)
545 finalFlowEntries.add(flowEntry);
546 flowPath.dataPath().setFlowEntries(finalFlowEntries);
547
548 return hasChanged;
549 }
550
551 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700552 * Receive a notification that a Flow is added.
553 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700554 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700555 */
556 @Override
557 public void notificationRecvFlowAdded(FlowPath flowPath) {
558 EventEntry<FlowPath> eventEntry =
559 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
560 networkEvents.add(eventEntry);
561 }
562
563 /**
564 * Receive a notification that a Flow is removed.
565 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700566 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700567 */
568 @Override
569 public void notificationRecvFlowRemoved(FlowPath flowPath) {
570 EventEntry<FlowPath> eventEntry =
571 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
572 networkEvents.add(eventEntry);
573 }
574
575 /**
576 * Receive a notification that a Flow is updated.
577 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700578 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700579 */
580 @Override
581 public void notificationRecvFlowUpdated(FlowPath flowPath) {
582 // NOTE: The ADD and UPDATE events are processed in same way
583 EventEntry<FlowPath> eventEntry =
584 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
585 networkEvents.add(eventEntry);
586 }
587
588 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700589 * Receive a notification that a FlowEntry is added.
590 *
591 * @param flowEntry the FlowEntry that is added.
592 */
593 @Override
594 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
595 EventEntry<FlowEntry> eventEntry =
596 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
597 networkEvents.add(eventEntry);
598 }
599
600 /**
601 * Receive a notification that a FlowEntry is removed.
602 *
603 * @param flowEntry the FlowEntry that is removed.
604 */
605 @Override
606 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
607 EventEntry<FlowEntry> eventEntry =
608 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
609 networkEvents.add(eventEntry);
610 }
611
612 /**
613 * Receive a notification that a FlowEntry is updated.
614 *
615 * @param flowEntry the FlowEntry that is updated.
616 */
617 @Override
618 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
619 // NOTE: The ADD and UPDATE events are processed in same way
620 EventEntry<FlowEntry> eventEntry =
621 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
622 networkEvents.add(eventEntry);
623 }
624
625 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700626 * Receive a notification that a Topology Element is added.
627 *
628 * @param topologyElement the Topology Element that is added.
629 */
630 @Override
631 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
632 EventEntry<TopologyElement> eventEntry =
633 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
634 networkEvents.add(eventEntry);
635 }
636
637 /**
638 * Receive a notification that a Topology Element is removed.
639 *
640 * @param topologyElement the Topology Element that is removed.
641 */
642 @Override
643 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
644 EventEntry<TopologyElement> eventEntry =
645 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
646 networkEvents.add(eventEntry);
647 }
648
649 /**
650 * Receive a notification that a Topology Element is updated.
651 *
652 * @param topologyElement the Topology Element that is updated.
653 */
654 @Override
655 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
656 // NOTE: The ADD and UPDATE events are processed in same way
657 EventEntry<TopologyElement> eventEntry =
658 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
659 networkEvents.add(eventEntry);
660 }
661}