blob: 97c40d2e4032d9c1bb6c9af783349d62d6f7ffc8 [file] [log] [blame]
alshabib77b88482015-04-07 15:47:50 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
alshabib77b88482015-04-07 15:47:50 -07003 *
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;
Thomas Vachuskad27097c2016-06-14 19:10:41 -070019import com.google.common.collect.Sets;
alshabib77b88482015-04-07 15:47:50 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
26import org.onlab.osgi.DefaultServiceDirectory;
27import org.onlab.osgi.ServiceDirectory;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070028import org.onlab.util.ItemNotFoundException;
alshabib77b88482015-04-07 15:47:50 -070029import org.onosproject.cluster.ClusterService;
30import org.onosproject.mastership.MastershipEvent;
31import org.onosproject.mastership.MastershipListener;
32import org.onosproject.mastership.MastershipService;
alshabib77b88482015-04-07 15:47:50 -070033import org.onosproject.net.DeviceId;
Saurav Das24431192016-03-07 19:13:00 -080034import org.onosproject.net.behaviour.NextGroup;
alshabib77b88482015-04-07 15:47:50 -070035import org.onosproject.net.behaviour.Pipeliner;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070036import org.onosproject.net.behaviour.PipelinerContext;
alshabibaebe7752015-04-07 17:45:42 -070037import org.onosproject.net.device.DeviceEvent;
38import org.onosproject.net.device.DeviceListener;
alshabib77b88482015-04-07 15:47:50 -070039import org.onosproject.net.device.DeviceService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -070040import org.onosproject.net.driver.DefaultDriverProviderService;
alshabib77b88482015-04-07 15:47:50 -070041import org.onosproject.net.driver.DriverHandler;
42import org.onosproject.net.driver.DriverService;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070043import org.onosproject.net.flow.FlowRuleService;
alshabib77b88482015-04-07 15:47:50 -070044import org.onosproject.net.flowobjective.FilteringObjective;
45import org.onosproject.net.flowobjective.FlowObjectiveService;
alshabib2a441c62015-04-13 18:39:38 -070046import org.onosproject.net.flowobjective.FlowObjectiveStore;
47import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
alshabib77b88482015-04-07 15:47:50 -070048import org.onosproject.net.flowobjective.ForwardingObjective;
49import org.onosproject.net.flowobjective.NextObjective;
alshabib910aff12015-04-09 16:55:57 -070050import org.onosproject.net.flowobjective.Objective;
Jonathan Hart17d00452015-04-21 17:10:00 -070051import org.onosproject.net.flowobjective.ObjectiveError;
alshabib2a441c62015-04-13 18:39:38 -070052import org.onosproject.net.flowobjective.ObjectiveEvent;
Saurav Das423fe2b2015-12-04 10:52:59 -080053import org.onosproject.net.flowobjective.ObjectiveEvent.Type;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070054import org.onosproject.net.group.GroupService;
alshabib77b88482015-04-07 15:47:50 -070055import org.slf4j.Logger;
56import org.slf4j.LoggerFactory;
57
Saurav Das24431192016-03-07 19:13:00 -080058import java.util.ArrayList;
Saurav Das24431192016-03-07 19:13:00 -080059import java.util.List;
alshabib77b88482015-04-07 15:47:50 -070060import java.util.Map;
Saurav Das8a0732e2015-11-20 15:27:53 -080061import java.util.Objects;
alshabib2a441c62015-04-13 18:39:38 -070062import java.util.Set;
Jonathan Hart17d00452015-04-21 17:10:00 -070063import java.util.concurrent.ExecutorService;
alshabib77b88482015-04-07 15:47:50 -070064
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -070065import static com.google.common.base.Preconditions.checkNotNull;
Thomas Vachuska866b46a2015-04-30 00:26:55 -070066import static java.util.concurrent.Executors.newFixedThreadPool;
Jonathan Hart17d00452015-04-21 17:10:00 -070067import static org.onlab.util.Tools.groupedThreads;
Changhoon Yoon541ef712015-05-23 17:18:34 +090068import static org.onosproject.security.AppGuard.checkPermission;
Thomas Vachuskad27097c2016-06-14 19:10:41 -070069import static org.onosproject.security.AppPermission.Type.FLOWRULE_WRITE;
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 Vachuskad27097c2016-06-14 19:10:41 -0700124 private final Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap();
alshabib2a441c62015-04-13 18:39:38 -0700125
Saurav Das24431192016-03-07 19:13:00 -0800126 // local store to track which nextObjectives were sent to which device
127 // for debugging purposes
128 private Map<Integer, DeviceId> nextToDevice = Maps.newConcurrentMap();
129
Jonathan Hart17d00452015-04-21 17:10:00 -0700130 private ExecutorService executorService;
alshabib2a441c62015-04-13 18:39:38 -0700131
alshabib77b88482015-04-07 15:47:50 -0700132 @Activate
133 protected void activate() {
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700134 executorService = newFixedThreadPool(4, groupedThreads("onos/objective-installer", "%d", log));
alshabib2a441c62015-04-13 18:39:38 -0700135 flowObjectiveStore.setDelegate(delegate);
alshabib77b88482015-04-07 15:47:50 -0700136 mastershipService.addListener(mastershipListener);
alshabibaebe7752015-04-07 17:45:42 -0700137 deviceService.addListener(deviceListener);
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700138 deviceService.getDevices().forEach(device -> setupPipelineHandler(device.id()));
alshabib77b88482015-04-07 15:47:50 -0700139 log.info("Started");
140 }
141
142 @Deactivate
143 protected void deactivate() {
alshabib2a441c62015-04-13 18:39:38 -0700144 flowObjectiveStore.unsetDelegate(delegate);
alshabib77b88482015-04-07 15:47:50 -0700145 mastershipService.removeListener(mastershipListener);
alshabibaebe7752015-04-07 17:45:42 -0700146 deviceService.removeListener(deviceListener);
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700147 executorService.shutdown();
148 pipeliners.clear();
149 driverHandlers.clear();
Saurav Das24431192016-03-07 19:13:00 -0800150 nextToDevice.clear();
alshabib77b88482015-04-07 15:47:50 -0700151 log.info("Stopped");
152 }
153
Jonathan Hart17d00452015-04-21 17:10:00 -0700154 /**
155 * Task that passes the flow objective down to the driver. The task will
156 * make a few attempts to find the appropriate driver, then eventually give
157 * up and report an error if no suitable driver could be found.
158 */
159 private class ObjectiveInstaller implements Runnable {
160 private final DeviceId deviceId;
161 private final Objective objective;
162
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -0700163 private final int numAttempts;
Jonathan Hart17d00452015-04-21 17:10:00 -0700164
165 public ObjectiveInstaller(DeviceId deviceId, Objective objective) {
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -0700166 this(deviceId, objective, 1);
167 }
168
169 public ObjectiveInstaller(DeviceId deviceId, Objective objective, int attemps) {
170 this.deviceId = checkNotNull(deviceId);
171 this.objective = checkNotNull(objective);
172 this.numAttempts = checkNotNull(attemps);
alshabib910aff12015-04-09 16:55:57 -0700173 }
alshabib77b88482015-04-07 15:47:50 -0700174
Jonathan Hart17d00452015-04-21 17:10:00 -0700175 @Override
176 public void run() {
177 try {
Jonathan Hart17d00452015-04-21 17:10:00 -0700178 Pipeliner pipeliner = getDevicePipeliner(deviceId);
179
180 if (pipeliner != null) {
181 if (objective instanceof NextObjective) {
182 pipeliner.next((NextObjective) objective);
183 } else if (objective instanceof ForwardingObjective) {
184 pipeliner.forward((ForwardingObjective) objective);
185 } else {
186 pipeliner.filter((FilteringObjective) objective);
187 }
Andrea Campanella1f8188d2016-02-29 13:24:54 -0800188 //Attempts to check if pipeliner is null for retry attempts
Jonathan Hart17d00452015-04-21 17:10:00 -0700189 } else if (numAttempts < INSTALL_RETRY_ATTEMPTS) {
Saurav Das3d038262015-04-23 12:36:58 -0700190 Thread.sleep(INSTALL_RETRY_INTERVAL);
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700191 executorService.execute(new ObjectiveInstaller(deviceId, objective, numAttempts + 1));
Jonathan Hart17d00452015-04-21 17:10:00 -0700192 } else {
193 // Otherwise we've tried a few times and failed, report an
194 // error back to the user.
195 objective.context().ifPresent(
Andrea Campanella1f8188d2016-02-29 13:24:54 -0800196 c -> c.onError(objective, ObjectiveError.NOPIPELINER));
Jonathan Hart17d00452015-04-21 17:10:00 -0700197 }
Andrea Campanella1f8188d2016-02-29 13:24:54 -0800198 //Excpetion thrown
Jonathan Hart17d00452015-04-21 17:10:00 -0700199 } catch (Exception e) {
200 log.warn("Exception while installing flow objective", e);
201 }
202 }
203 }
204
205 @Override
206 public void filter(DeviceId deviceId, FilteringObjective filteringObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900207 checkPermission(FLOWRULE_WRITE);
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700208 executorService.execute(new ObjectiveInstaller(deviceId, filteringObjective));
alshabib77b88482015-04-07 15:47:50 -0700209 }
210
211 @Override
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700212 public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900213 checkPermission(FLOWRULE_WRITE);
alshabib2a441c62015-04-13 18:39:38 -0700214 if (queueObjective(deviceId, forwardingObjective)) {
215 return;
alshabib910aff12015-04-09 16:55:57 -0700216 }
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700217 executorService.execute(new ObjectiveInstaller(deviceId, forwardingObjective));
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700218 }
219
alshabib2a441c62015-04-13 18:39:38 -0700220 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700221 public void next(DeviceId deviceId, NextObjective nextObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900222 checkPermission(FLOWRULE_WRITE);
Saurav Das24431192016-03-07 19:13:00 -0800223 nextToDevice.put(nextObjective.id(), deviceId);
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700224 executorService.execute(new ObjectiveInstaller(deviceId, nextObjective));
alshabib2a441c62015-04-13 18:39:38 -0700225 }
226
alshabibf6ea9e62015-04-21 17:08:26 -0700227 @Override
228 public int allocateNextId() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900229 checkPermission(FLOWRULE_WRITE);
alshabibf6ea9e62015-04-21 17:08:26 -0700230 return flowObjectiveStore.allocateNextId();
231 }
232
Xin Jin313708b2015-07-09 13:43:04 -0700233 @Override
234 public void initPolicy(String policy) {}
235
alshabib2a441c62015-04-13 18:39:38 -0700236 private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) {
Thomas Vachuskad27097c2016-06-14 19:10:41 -0700237 if (fwd.nextId() == null ||
238 flowObjectiveStore.getNextGroup(fwd.nextId()) != null) {
239 // fast path
240 return false;
alshabib2a441c62015-04-13 18:39:38 -0700241 }
Thomas Vachuskad27097c2016-06-14 19:10:41 -0700242 boolean queued = false;
243 synchronized (pendingForwards) {
244 // double check the flow objective store, because this block could run
245 // after a notification arrives
246 if (flowObjectiveStore.getNextGroup(fwd.nextId()) == null) {
247 pendingForwards.compute(fwd.nextId(), (id, pending) -> {
248 PendingNext next = new PendingNext(deviceId, fwd);
249 if (pending == null) {
250 return Sets.newHashSet(next);
251 } else {
252 pending.add(next);
253 return pending;
254 }
255 });
256 queued = true;
257 }
258 }
259 if (queued) {
260 log.debug("Queued forwarding objective {} for nextId {} meant for device {}",
261 fwd.id(), fwd.nextId(), deviceId);
262 }
263 return queued;
alshabib2a441c62015-04-13 18:39:38 -0700264 }
265
alshabib910aff12015-04-09 16:55:57 -0700266 // Retrieves the device pipeline behaviour from the cache.
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700267 private Pipeliner getDevicePipeliner(DeviceId deviceId) {
Thomas Vachuska94c3cf42015-07-20 13:01:12 -0700268 return pipeliners.get(deviceId);
alshabib77b88482015-04-07 15:47:50 -0700269 }
270
alshabib2a441c62015-04-13 18:39:38 -0700271 private void setupPipelineHandler(DeviceId deviceId) {
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700272 if (defaultDriverService == null) {
273 // We're not ready to go to work yet.
274 return;
275 }
276
Jonathan Hart17d00452015-04-21 17:10:00 -0700277 // Attempt to lookup the handler in the cache
278 DriverHandler handler = driverHandlers.get(deviceId);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700279 cTime = now();
280
Jonathan Hart17d00452015-04-21 17:10:00 -0700281 if (handler == null) {
282 try {
283 // Otherwise create it and if it has pipeline behaviour, cache it
284 handler = driverService.createHandler(deviceId);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700285 dTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700286 if (!handler.driver().hasBehaviour(Pipeliner.class)) {
287 log.warn("Pipeline behaviour not supported for device {}",
288 deviceId);
alshabib2a441c62015-04-13 18:39:38 -0700289 return;
290 }
Jonathan Hart17d00452015-04-21 17:10:00 -0700291 } catch (ItemNotFoundException e) {
292 log.warn("No applicable driver for device {}", deviceId);
293 return;
alshabib2a441c62015-04-13 18:39:38 -0700294 }
295
Jonathan Hart17d00452015-04-21 17:10:00 -0700296 driverHandlers.put(deviceId, handler);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700297 eTime = now();
alshabib2a441c62015-04-13 18:39:38 -0700298 }
Jonathan Hart17d00452015-04-21 17:10:00 -0700299
300 // Always (re)initialize the pipeline behaviour
301 log.info("Driver {} bound to device {} ... initializing driver",
302 handler.driver().name(), deviceId);
Thomas Vachuska0121a612015-07-21 11:18:09 -0700303 hTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700304 Pipeliner pipeliner = handler.behaviour(Pipeliner.class);
Thomas Vachuska94c3cf42015-07-20 13:01:12 -0700305 hbTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700306 pipeliner.init(deviceId, context);
307 pipeliners.putIfAbsent(deviceId, pipeliner);
alshabib2a441c62015-04-13 18:39:38 -0700308 }
alshabibaebe7752015-04-07 17:45:42 -0700309
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700310 // Triggers driver setup when the local node becomes a device master.
alshabib77b88482015-04-07 15:47:50 -0700311 private class InnerMastershipListener implements MastershipListener {
312 @Override
313 public void event(MastershipEvent event) {
314 switch (event.type()) {
alshabib77b88482015-04-07 15:47:50 -0700315 case MASTER_CHANGED:
Madan Jampani0174f452015-05-29 11:52:05 -0700316 log.debug("mastership changed on device {}", event.subject());
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700317 start = now();
Saurav Das3d038262015-04-23 12:36:58 -0700318 if (deviceService.isAvailable(event.subject())) {
319 setupPipelineHandler(event.subject());
320 }
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700321 stopWatch();
alshabib4313d102015-04-08 18:55:08 -0700322 break;
323 case BACKUPS_CHANGED:
alshabib77b88482015-04-07 15:47:50 -0700324 break;
325 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700326 break;
alshabib77b88482015-04-07 15:47:50 -0700327 }
328 }
alshabibaebe7752015-04-07 17:45:42 -0700329 }
alshabib77b88482015-04-07 15:47:50 -0700330
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700331 // Triggers driver setup when a device is (re)detected.
alshabibaebe7752015-04-07 17:45:42 -0700332 private class InnerDeviceListener implements DeviceListener {
333 @Override
334 public void event(DeviceEvent event) {
335 switch (event.type()) {
336 case DEVICE_ADDED:
337 case DEVICE_AVAILABILITY_CHANGED:
Madan Jampani0174f452015-05-29 11:52:05 -0700338 log.debug("Device either added or availability changed {}",
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700339 event.subject().id());
340 start = now();
alshabib4313d102015-04-08 18:55:08 -0700341 if (deviceService.isAvailable(event.subject().id())) {
Madan Jampani0174f452015-05-29 11:52:05 -0700342 log.debug("Device is now available {}", event.subject().id());
alshabib4313d102015-04-08 18:55:08 -0700343 setupPipelineHandler(event.subject().id());
344 }
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700345 stopWatch();
alshabib4313d102015-04-08 18:55:08 -0700346 break;
347 case DEVICE_UPDATED:
348 break;
349 case DEVICE_REMOVED:
350 break;
351 case DEVICE_SUSPENDED:
352 break;
353 case PORT_ADDED:
354 break;
355 case PORT_UPDATED:
356 break;
357 case PORT_REMOVED:
alshabibaebe7752015-04-07 17:45:42 -0700358 break;
359 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700360 break;
alshabibaebe7752015-04-07 17:45:42 -0700361 }
alshabib77b88482015-04-07 15:47:50 -0700362 }
363 }
alshabibaebe7752015-04-07 17:45:42 -0700364
Thomas Vachuska174bb912015-07-16 21:27:14 -0700365 // Temporary mechanism to monitor pipeliner setup time-cost; there are
366 // intermittent time where this takes in excess of 2 seconds. Why?
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700367 private long start = 0, totals = 0, count = 0;
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700368 private long cTime, dTime, eTime, hTime, hbTime;
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700369 private static final long LIMIT = 500;
Thomas Vachuska174bb912015-07-16 21:27:14 -0700370
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700371 private long now() {
Thomas Vachuska174bb912015-07-16 21:27:14 -0700372 return System.currentTimeMillis();
373 }
374
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700375 private void stopWatch() {
Thomas Vachuska174bb912015-07-16 21:27:14 -0700376 long duration = System.currentTimeMillis() - start;
377 totals += duration;
378 count += 1;
379 if (duration > LIMIT) {
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700380 log.info("Pipeline setup took {} ms; avg {} ms; cTime={}, dTime={}, eTime={}, hTime={}, hbTime={}",
381 duration, totals / count, diff(cTime), diff(dTime), diff(eTime), diff(hTime), diff(hbTime));
Thomas Vachuska174bb912015-07-16 21:27:14 -0700382 }
383 }
384
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700385 private long diff(long bTime) {
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700386 long diff = bTime - start;
387 return diff < 0 ? 0 : diff;
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700388 }
389
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700390 // Processing context for initializing pipeline driver behaviours.
391 private class InnerPipelineContext implements PipelinerContext {
392 @Override
393 public ServiceDirectory directory() {
394 return serviceDirectory;
alshabibaebe7752015-04-07 17:45:42 -0700395 }
alshabib2a441c62015-04-13 18:39:38 -0700396
397 @Override
398 public FlowObjectiveStore store() {
399 return flowObjectiveStore;
400 }
alshabib2a441c62015-04-13 18:39:38 -0700401 }
402
403 private class InternalStoreDelegate implements FlowObjectiveStoreDelegate {
404 @Override
405 public void notify(ObjectiveEvent event) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800406 if (event.type() == Type.ADD) {
407 log.debug("Received notification of obj event {}", event);
Thomas Vachuskad27097c2016-06-14 19:10:41 -0700408 Set<PendingNext> pending;
409 synchronized (pendingForwards) {
410 // needs to be synchronized for queueObjective lookup
411 pending = pendingForwards.remove(event.subject());
412 }
alshabib2a441c62015-04-13 18:39:38 -0700413
Saurav Das423fe2b2015-12-04 10:52:59 -0800414 if (pending == null) {
Saurav Das25190812016-05-27 13:54:07 -0700415 log.debug("Nothing pending for this obj event {}", event);
Saurav Das423fe2b2015-12-04 10:52:59 -0800416 return;
417 }
418
Saurav Das49cb5a12016-01-16 22:54:07 -0800419 log.debug("Processing {} pending forwarding objectives for nextId {}",
420 pending.size(), event.subject());
Saurav Das423fe2b2015-12-04 10:52:59 -0800421 pending.forEach(p -> getDevicePipeliner(p.deviceId())
422 .forward(p.forwardingObjective()));
alshabib2a441c62015-04-13 18:39:38 -0700423 }
alshabib2a441c62015-04-13 18:39:38 -0700424 }
425 }
426
427 /**
428 * Data class used to hold a pending forwarding objective that could not
429 * be processed because the associated next object was not present.
430 */
431 private class PendingNext {
432 private final DeviceId deviceId;
433 private final ForwardingObjective fwd;
434
435 public PendingNext(DeviceId deviceId, ForwardingObjective fwd) {
436 this.deviceId = deviceId;
437 this.fwd = fwd;
438 }
439
440 public DeviceId deviceId() {
441 return deviceId;
442 }
443
444 public ForwardingObjective forwardingObjective() {
445 return fwd;
446 }
Saurav Das8a0732e2015-11-20 15:27:53 -0800447
448 @Override
449 public int hashCode() {
450 return Objects.hash(deviceId, fwd);
451 }
452
453 @Override
454 public boolean equals(final Object obj) {
455 if (this == obj) {
456 return true;
457 }
458 if (!(obj instanceof PendingNext)) {
459 return false;
460 }
461 final PendingNext other = (PendingNext) obj;
462 if (this.deviceId.equals(other.deviceId) &&
463 this.fwd.equals(other.fwd)) {
464 return true;
465 }
466 return false;
467 }
alshabibaebe7752015-04-07 17:45:42 -0700468 }
Saurav Das24431192016-03-07 19:13:00 -0800469
470 @Override
471 public List<String> getNextMappings() {
472 List<String> mappings = new ArrayList<>();
473 Map<Integer, NextGroup> allnexts = flowObjectiveStore.getAllGroups();
Saurav Das25190812016-05-27 13:54:07 -0700474 // XXX if the NextGroup after de-serialization actually stored info of the deviceId
Saurav Das24431192016-03-07 19:13:00 -0800475 // then info on any nextObj could be retrieved from one controller instance.
476 // Right now the drivers on one instance can only fetch for next-ids that came
477 // to them.
478 // Also, we still need to send the right next-id to the right driver as potentially
479 // there can be different drivers for different devices. But on that account,
480 // no instance should be decoding for another instance's nextIds.
481
482 for (Map.Entry<Integer, NextGroup> e : allnexts.entrySet()) {
483 // get the device this next Objective was sent to
484 DeviceId deviceId = nextToDevice.get(e.getKey());
485 mappings.add("NextId " + e.getKey() + ": " +
486 ((deviceId != null) ? deviceId : "nextId not in this onos instance"));
487 if (deviceId != null) {
488 // this instance of the controller sent the nextObj to a driver
489 Pipeliner pipeliner = getDevicePipeliner(deviceId);
490 List<String> nextMappings = pipeliner.getNextMappings(e.getValue());
491 if (nextMappings != null) {
492 mappings.addAll(nextMappings);
493 }
494 }
495 }
496 return mappings;
497 }
Saurav Dasb5c236e2016-06-07 10:08:06 -0700498
499 @Override
500 public List<String> getPendingNexts() {
501 List<String> pendingNexts = new ArrayList<>();
502 for (Integer nextId : pendingForwards.keySet()) {
503 Set<PendingNext> pnext = pendingForwards.get(nextId);
504 StringBuffer pend = new StringBuffer();
505 pend.append("Next Id: ").append(Integer.toString(nextId))
506 .append(" :: ");
507 for (PendingNext pn : pnext) {
508 pend.append(Integer.toString(pn.forwardingObjective().id()))
509 .append(" ");
510 }
511 pendingNexts.add(pend.toString());
512 }
513 return pendingNexts;
514 }
alshabib77b88482015-04-07 15:47:50 -0700515}