blob: 6a0d3e1ed331771d49ff86b756afe143e83d67ea [file] [log] [blame]
alshabib77b88482015-04-07 15:47:50 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.net.flowobjective.impl;
17
18import com.google.common.collect.Maps;
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
25import org.onlab.osgi.DefaultServiceDirectory;
26import org.onlab.osgi.ServiceDirectory;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070027import org.onlab.util.ItemNotFoundException;
alshabib77b88482015-04-07 15:47:50 -070028import org.onosproject.cluster.ClusterService;
29import org.onosproject.mastership.MastershipEvent;
30import org.onosproject.mastership.MastershipListener;
31import org.onosproject.mastership.MastershipService;
alshabib77b88482015-04-07 15:47:50 -070032import org.onosproject.net.DeviceId;
33import org.onosproject.net.behaviour.Pipeliner;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070034import org.onosproject.net.behaviour.PipelinerContext;
alshabibaebe7752015-04-07 17:45:42 -070035import org.onosproject.net.device.DeviceEvent;
36import org.onosproject.net.device.DeviceListener;
alshabib77b88482015-04-07 15:47:50 -070037import org.onosproject.net.device.DeviceService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -070038import org.onosproject.net.driver.DefaultDriverProviderService;
alshabib77b88482015-04-07 15:47:50 -070039import org.onosproject.net.driver.DriverHandler;
40import org.onosproject.net.driver.DriverService;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070041import org.onosproject.net.flow.FlowRuleService;
alshabib77b88482015-04-07 15:47:50 -070042import org.onosproject.net.flowobjective.FilteringObjective;
43import org.onosproject.net.flowobjective.FlowObjectiveService;
alshabib2a441c62015-04-13 18:39:38 -070044import org.onosproject.net.flowobjective.FlowObjectiveStore;
45import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
alshabib77b88482015-04-07 15:47:50 -070046import org.onosproject.net.flowobjective.ForwardingObjective;
47import org.onosproject.net.flowobjective.NextObjective;
alshabib910aff12015-04-09 16:55:57 -070048import org.onosproject.net.flowobjective.Objective;
Jonathan Hart17d00452015-04-21 17:10:00 -070049import org.onosproject.net.flowobjective.ObjectiveError;
alshabib2a441c62015-04-13 18:39:38 -070050import org.onosproject.net.flowobjective.ObjectiveEvent;
Saurav Das423fe2b2015-12-04 10:52:59 -080051import org.onosproject.net.flowobjective.ObjectiveEvent.Type;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070052import org.onosproject.net.group.GroupService;
alshabib77b88482015-04-07 15:47:50 -070053import org.slf4j.Logger;
54import org.slf4j.LoggerFactory;
55
Saurav Das4ce45962015-11-24 23:21:05 -080056import java.util.Collections;
alshabib77b88482015-04-07 15:47:50 -070057import java.util.Map;
Saurav Das8a0732e2015-11-20 15:27:53 -080058import java.util.Objects;
alshabib2a441c62015-04-13 18:39:38 -070059import java.util.Set;
Saurav Das4ce45962015-11-24 23:21:05 -080060import java.util.concurrent.ConcurrentHashMap;
Jonathan Hart17d00452015-04-21 17:10:00 -070061import java.util.concurrent.ExecutorService;
alshabib77b88482015-04-07 15:47:50 -070062
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -070063import static com.google.common.base.Preconditions.checkNotNull;
Thomas Vachuska866b46a2015-04-30 00:26:55 -070064import static java.util.concurrent.Executors.newFixedThreadPool;
Jonathan Hart17d00452015-04-21 17:10:00 -070065import static org.onlab.util.Tools.groupedThreads;
Changhoon Yoon541ef712015-05-23 17:18:34 +090066import static org.onosproject.security.AppGuard.checkPermission;
Changhoon Yoonb856b812015-08-10 03:47:19 +090067import static org.onosproject.security.AppPermission.Type.*;
68
Changhoon Yoon541ef712015-05-23 17:18:34 +090069
alshabib77b88482015-04-07 15:47:50 -070070
71/**
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070072 * Provides implementation of the flow objective programming service.
alshabib77b88482015-04-07 15:47:50 -070073 */
alshabib2a441c62015-04-13 18:39:38 -070074@Component(immediate = true)
alshabib77b88482015-04-07 15:47:50 -070075@Service
76public class FlowObjectiveManager implements FlowObjectiveService {
77
Saurav Dasbd7f7422015-04-23 16:31:47 -070078 public static final int INSTALL_RETRY_ATTEMPTS = 5;
Jonathan Hart17d00452015-04-21 17:10:00 -070079 public static final long INSTALL_RETRY_INTERVAL = 1000; // ms
alshabib77b88482015-04-07 15:47:50 -070080
Jonathan Hart17d00452015-04-21 17:10:00 -070081 private final Logger log = LoggerFactory.getLogger(getClass());
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070082
alshabib77b88482015-04-07 15:47:50 -070083 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected DriverService driverService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected DeviceService deviceService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected MastershipService mastershipService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected ClusterService clusterService;
94
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070095 // Note: The following dependencies are added on behalf of the pipeline
96 // driver behaviours to assure these services are available for their
97 // initialization.
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected FlowRuleService flowRuleService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected GroupService groupService;
103
alshabib2a441c62015-04-13 18:39:38 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected FlowObjectiveStore flowObjectiveStore;
106
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700107 // Note: This must remain an optional dependency to allow re-install of default drivers.
108 // Note: For now disabled until we can move to OPTIONAL_UNARY dependency
109 // @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected DefaultDriverProviderService defaultDriverService;
112
alshabib2a441c62015-04-13 18:39:38 -0700113 private final FlowObjectiveStoreDelegate delegate = new InternalStoreDelegate();
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700114
115 private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap();
alshabib910aff12015-04-09 16:55:57 -0700116 private final Map<DeviceId, Pipeliner> pipeliners = Maps.newConcurrentMap();
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700117
118 private final PipelinerContext context = new InnerPipelineContext();
119 private final MastershipListener mastershipListener = new InnerMastershipListener();
120 private final DeviceListener deviceListener = new InnerDeviceListener();
121
alshabib77b88482015-04-07 15:47:50 -0700122 protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
alshabib910aff12015-04-09 16:55:57 -0700123
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700124 private Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap();
alshabib2a441c62015-04-13 18:39:38 -0700125
Jonathan Hart17d00452015-04-21 17:10:00 -0700126 private ExecutorService executorService;
alshabib2a441c62015-04-13 18:39:38 -0700127
alshabib77b88482015-04-07 15:47:50 -0700128 @Activate
129 protected void activate() {
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700130 executorService = newFixedThreadPool(4, groupedThreads("onos/objective-installer", "%d"));
alshabib2a441c62015-04-13 18:39:38 -0700131 flowObjectiveStore.setDelegate(delegate);
alshabib77b88482015-04-07 15:47:50 -0700132 mastershipService.addListener(mastershipListener);
alshabibaebe7752015-04-07 17:45:42 -0700133 deviceService.addListener(deviceListener);
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700134 deviceService.getDevices().forEach(device -> setupPipelineHandler(device.id()));
alshabib77b88482015-04-07 15:47:50 -0700135 log.info("Started");
136 }
137
138 @Deactivate
139 protected void deactivate() {
alshabib2a441c62015-04-13 18:39:38 -0700140 flowObjectiveStore.unsetDelegate(delegate);
alshabib77b88482015-04-07 15:47:50 -0700141 mastershipService.removeListener(mastershipListener);
alshabibaebe7752015-04-07 17:45:42 -0700142 deviceService.removeListener(deviceListener);
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700143 executorService.shutdown();
144 pipeliners.clear();
145 driverHandlers.clear();
alshabib77b88482015-04-07 15:47:50 -0700146 log.info("Stopped");
147 }
148
Jonathan Hart17d00452015-04-21 17:10:00 -0700149 /**
150 * Task that passes the flow objective down to the driver. The task will
151 * make a few attempts to find the appropriate driver, then eventually give
152 * up and report an error if no suitable driver could be found.
153 */
154 private class ObjectiveInstaller implements Runnable {
155 private final DeviceId deviceId;
156 private final Objective objective;
157
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -0700158 private final int numAttempts;
Jonathan Hart17d00452015-04-21 17:10:00 -0700159
160 public ObjectiveInstaller(DeviceId deviceId, Objective objective) {
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -0700161 this(deviceId, objective, 1);
162 }
163
164 public ObjectiveInstaller(DeviceId deviceId, Objective objective, int attemps) {
165 this.deviceId = checkNotNull(deviceId);
166 this.objective = checkNotNull(objective);
167 this.numAttempts = checkNotNull(attemps);
alshabib910aff12015-04-09 16:55:57 -0700168 }
alshabib77b88482015-04-07 15:47:50 -0700169
Jonathan Hart17d00452015-04-21 17:10:00 -0700170 @Override
171 public void run() {
172 try {
Jonathan Hart17d00452015-04-21 17:10:00 -0700173 Pipeliner pipeliner = getDevicePipeliner(deviceId);
174
175 if (pipeliner != null) {
176 if (objective instanceof NextObjective) {
177 pipeliner.next((NextObjective) objective);
178 } else if (objective instanceof ForwardingObjective) {
179 pipeliner.forward((ForwardingObjective) objective);
180 } else {
181 pipeliner.filter((FilteringObjective) objective);
182 }
183 } else if (numAttempts < INSTALL_RETRY_ATTEMPTS) {
Saurav Das3d038262015-04-23 12:36:58 -0700184 Thread.sleep(INSTALL_RETRY_INTERVAL);
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -0700185 executorService.submit(new ObjectiveInstaller(deviceId, objective, numAttempts + 1));
Jonathan Hart17d00452015-04-21 17:10:00 -0700186 } else {
187 // Otherwise we've tried a few times and failed, report an
188 // error back to the user.
189 objective.context().ifPresent(
190 c -> c.onError(objective, ObjectiveError.DEVICEMISSING));
191 }
192 } catch (Exception e) {
193 log.warn("Exception while installing flow objective", e);
194 }
195 }
196 }
197
198 @Override
199 public void filter(DeviceId deviceId, FilteringObjective filteringObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900200 checkPermission(FLOWRULE_WRITE);
Jonathan Hart17d00452015-04-21 17:10:00 -0700201 executorService.submit(new ObjectiveInstaller(deviceId, filteringObjective));
alshabib77b88482015-04-07 15:47:50 -0700202 }
203
204 @Override
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700205 public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900206 checkPermission(FLOWRULE_WRITE);
alshabib2a441c62015-04-13 18:39:38 -0700207 if (queueObjective(deviceId, forwardingObjective)) {
208 return;
alshabib910aff12015-04-09 16:55:57 -0700209 }
Jonathan Hart17d00452015-04-21 17:10:00 -0700210 executorService.submit(new ObjectiveInstaller(deviceId, forwardingObjective));
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700211 }
212
alshabib2a441c62015-04-13 18:39:38 -0700213 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700214 public void next(DeviceId deviceId, NextObjective nextObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900215 checkPermission(FLOWRULE_WRITE);
Jonathan Hart17d00452015-04-21 17:10:00 -0700216 executorService.submit(new ObjectiveInstaller(deviceId, nextObjective));
alshabib2a441c62015-04-13 18:39:38 -0700217 }
218
alshabibf6ea9e62015-04-21 17:08:26 -0700219 @Override
220 public int allocateNextId() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900221 checkPermission(FLOWRULE_WRITE);
alshabibf6ea9e62015-04-21 17:08:26 -0700222 return flowObjectiveStore.allocateNextId();
223 }
224
Xin Jin313708b2015-07-09 13:43:04 -0700225 @Override
226 public void initPolicy(String policy) {}
227
alshabib2a441c62015-04-13 18:39:38 -0700228 private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) {
229 if (fwd.nextId() != null &&
230 flowObjectiveStore.getNextGroup(fwd.nextId()) == null) {
Saurav Das3ea46622015-04-22 14:01:34 -0700231 log.trace("Queuing forwarding objective for nextId {}", fwd.nextId());
Saurav Das8a0732e2015-11-20 15:27:53 -0800232 // TODO: change to computeIfAbsent
Saurav Das4ce45962015-11-24 23:21:05 -0800233 Set<PendingNext> newset = Collections.newSetFromMap(
234 new ConcurrentHashMap<PendingNext, Boolean>());
235 newset.add(new PendingNext(deviceId, fwd));
236 Set<PendingNext> pnext = pendingForwards.putIfAbsent(fwd.nextId(), newset);
Saurav Das8a0732e2015-11-20 15:27:53 -0800237 if (pnext != null) {
238 pnext.add(new PendingNext(deviceId, fwd));
alshabib2a441c62015-04-13 18:39:38 -0700239 }
240 return true;
241 }
242 return false;
243 }
244
alshabib910aff12015-04-09 16:55:57 -0700245 // Retrieves the device pipeline behaviour from the cache.
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700246 private Pipeliner getDevicePipeliner(DeviceId deviceId) {
Thomas Vachuska94c3cf42015-07-20 13:01:12 -0700247 return pipeliners.get(deviceId);
alshabib77b88482015-04-07 15:47:50 -0700248 }
249
alshabib2a441c62015-04-13 18:39:38 -0700250 private void setupPipelineHandler(DeviceId deviceId) {
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700251 if (defaultDriverService == null) {
252 // We're not ready to go to work yet.
253 return;
254 }
255
Jonathan Hart17d00452015-04-21 17:10:00 -0700256 // Attempt to lookup the handler in the cache
257 DriverHandler handler = driverHandlers.get(deviceId);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700258 cTime = now();
259
Jonathan Hart17d00452015-04-21 17:10:00 -0700260 if (handler == null) {
261 try {
262 // Otherwise create it and if it has pipeline behaviour, cache it
263 handler = driverService.createHandler(deviceId);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700264 dTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700265 if (!handler.driver().hasBehaviour(Pipeliner.class)) {
266 log.warn("Pipeline behaviour not supported for device {}",
267 deviceId);
alshabib2a441c62015-04-13 18:39:38 -0700268 return;
269 }
Jonathan Hart17d00452015-04-21 17:10:00 -0700270 } catch (ItemNotFoundException e) {
271 log.warn("No applicable driver for device {}", deviceId);
272 return;
alshabib2a441c62015-04-13 18:39:38 -0700273 }
274
Jonathan Hart17d00452015-04-21 17:10:00 -0700275 driverHandlers.put(deviceId, handler);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700276 eTime = now();
alshabib2a441c62015-04-13 18:39:38 -0700277 }
Jonathan Hart17d00452015-04-21 17:10:00 -0700278
279 // Always (re)initialize the pipeline behaviour
280 log.info("Driver {} bound to device {} ... initializing driver",
281 handler.driver().name(), deviceId);
Thomas Vachuska0121a612015-07-21 11:18:09 -0700282 hTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700283 Pipeliner pipeliner = handler.behaviour(Pipeliner.class);
Thomas Vachuska94c3cf42015-07-20 13:01:12 -0700284 hbTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700285 pipeliner.init(deviceId, context);
286 pipeliners.putIfAbsent(deviceId, pipeliner);
alshabib2a441c62015-04-13 18:39:38 -0700287 }
alshabibaebe7752015-04-07 17:45:42 -0700288
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700289 // Triggers driver setup when the local node becomes a device master.
alshabib77b88482015-04-07 15:47:50 -0700290 private class InnerMastershipListener implements MastershipListener {
291 @Override
292 public void event(MastershipEvent event) {
293 switch (event.type()) {
alshabib77b88482015-04-07 15:47:50 -0700294 case MASTER_CHANGED:
Madan Jampani0174f452015-05-29 11:52:05 -0700295 log.debug("mastership changed on device {}", event.subject());
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700296 start = now();
Saurav Das3d038262015-04-23 12:36:58 -0700297 if (deviceService.isAvailable(event.subject())) {
298 setupPipelineHandler(event.subject());
299 }
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700300 stopWatch();
alshabib4313d102015-04-08 18:55:08 -0700301 break;
302 case BACKUPS_CHANGED:
alshabib77b88482015-04-07 15:47:50 -0700303 break;
304 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700305 break;
alshabib77b88482015-04-07 15:47:50 -0700306 }
307 }
alshabibaebe7752015-04-07 17:45:42 -0700308 }
alshabib77b88482015-04-07 15:47:50 -0700309
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700310 // Triggers driver setup when a device is (re)detected.
alshabibaebe7752015-04-07 17:45:42 -0700311 private class InnerDeviceListener implements DeviceListener {
312 @Override
313 public void event(DeviceEvent event) {
314 switch (event.type()) {
315 case DEVICE_ADDED:
316 case DEVICE_AVAILABILITY_CHANGED:
Madan Jampani0174f452015-05-29 11:52:05 -0700317 log.debug("Device either added or availability changed {}",
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700318 event.subject().id());
319 start = now();
alshabib4313d102015-04-08 18:55:08 -0700320 if (deviceService.isAvailable(event.subject().id())) {
Madan Jampani0174f452015-05-29 11:52:05 -0700321 log.debug("Device is now available {}", event.subject().id());
alshabib4313d102015-04-08 18:55:08 -0700322 setupPipelineHandler(event.subject().id());
323 }
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700324 stopWatch();
alshabib4313d102015-04-08 18:55:08 -0700325 break;
326 case DEVICE_UPDATED:
327 break;
328 case DEVICE_REMOVED:
329 break;
330 case DEVICE_SUSPENDED:
331 break;
332 case PORT_ADDED:
333 break;
334 case PORT_UPDATED:
335 break;
336 case PORT_REMOVED:
alshabibaebe7752015-04-07 17:45:42 -0700337 break;
338 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700339 break;
alshabibaebe7752015-04-07 17:45:42 -0700340 }
alshabib77b88482015-04-07 15:47:50 -0700341 }
342 }
alshabibaebe7752015-04-07 17:45:42 -0700343
Thomas Vachuska174bb912015-07-16 21:27:14 -0700344 // Temporary mechanism to monitor pipeliner setup time-cost; there are
345 // intermittent time where this takes in excess of 2 seconds. Why?
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700346 private long start = 0, totals = 0, count = 0;
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700347 private long cTime, dTime, eTime, hTime, hbTime;
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700348 private static final long LIMIT = 500;
Thomas Vachuska174bb912015-07-16 21:27:14 -0700349
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700350 private long now() {
Thomas Vachuska174bb912015-07-16 21:27:14 -0700351 return System.currentTimeMillis();
352 }
353
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700354 private void stopWatch() {
Thomas Vachuska174bb912015-07-16 21:27:14 -0700355 long duration = System.currentTimeMillis() - start;
356 totals += duration;
357 count += 1;
358 if (duration > LIMIT) {
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700359 log.info("Pipeline setup took {} ms; avg {} ms; cTime={}, dTime={}, eTime={}, hTime={}, hbTime={}",
360 duration, totals / count, diff(cTime), diff(dTime), diff(eTime), diff(hTime), diff(hbTime));
Thomas Vachuska174bb912015-07-16 21:27:14 -0700361 }
362 }
363
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700364 private long diff(long bTime) {
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700365 long diff = bTime - start;
366 return diff < 0 ? 0 : diff;
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700367 }
368
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700369 // Processing context for initializing pipeline driver behaviours.
370 private class InnerPipelineContext implements PipelinerContext {
371 @Override
372 public ServiceDirectory directory() {
373 return serviceDirectory;
alshabibaebe7752015-04-07 17:45:42 -0700374 }
alshabib2a441c62015-04-13 18:39:38 -0700375
376 @Override
377 public FlowObjectiveStore store() {
378 return flowObjectiveStore;
379 }
alshabib2a441c62015-04-13 18:39:38 -0700380 }
381
382 private class InternalStoreDelegate implements FlowObjectiveStoreDelegate {
383 @Override
384 public void notify(ObjectiveEvent event) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800385 if (event.type() == Type.ADD) {
386 log.debug("Received notification of obj event {}", event);
387 Set<PendingNext> pending = pendingForwards.remove(event.subject());
alshabib2a441c62015-04-13 18:39:38 -0700388
Saurav Das423fe2b2015-12-04 10:52:59 -0800389 if (pending == null) {
390 log.debug("Nothing pending for this obj event");
391 return;
392 }
393
394 log.debug("Processing pending forwarding objectives {}", pending.size());
395 pending.forEach(p -> getDevicePipeliner(p.deviceId())
396 .forward(p.forwardingObjective()));
alshabib2a441c62015-04-13 18:39:38 -0700397 }
alshabib2a441c62015-04-13 18:39:38 -0700398 }
399 }
400
401 /**
402 * Data class used to hold a pending forwarding objective that could not
403 * be processed because the associated next object was not present.
404 */
405 private class PendingNext {
406 private final DeviceId deviceId;
407 private final ForwardingObjective fwd;
408
409 public PendingNext(DeviceId deviceId, ForwardingObjective fwd) {
410 this.deviceId = deviceId;
411 this.fwd = fwd;
412 }
413
414 public DeviceId deviceId() {
415 return deviceId;
416 }
417
418 public ForwardingObjective forwardingObjective() {
419 return fwd;
420 }
Saurav Das8a0732e2015-11-20 15:27:53 -0800421
422 @Override
423 public int hashCode() {
424 return Objects.hash(deviceId, fwd);
425 }
426
427 @Override
428 public boolean equals(final Object obj) {
429 if (this == obj) {
430 return true;
431 }
432 if (!(obj instanceof PendingNext)) {
433 return false;
434 }
435 final PendingNext other = (PendingNext) obj;
436 if (this.deviceId.equals(other.deviceId) &&
437 this.fwd.equals(other.fwd)) {
438 return true;
439 }
440 return false;
441 }
alshabibaebe7752015-04-07 17:45:42 -0700442 }
alshabib77b88482015-04-07 15:47:50 -0700443}