blob: cac3717e3c20b6da0a7096ea8087b041ade45f6f [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;
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;
Saurav Das24431192016-03-07 19:13:00 -080033import org.onosproject.net.behaviour.NextGroup;
alshabib77b88482015-04-07 15:47:50 -070034import org.onosproject.net.behaviour.Pipeliner;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070035import org.onosproject.net.behaviour.PipelinerContext;
alshabibaebe7752015-04-07 17:45:42 -070036import org.onosproject.net.device.DeviceEvent;
37import org.onosproject.net.device.DeviceListener;
alshabib77b88482015-04-07 15:47:50 -070038import org.onosproject.net.device.DeviceService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -070039import org.onosproject.net.driver.DefaultDriverProviderService;
alshabib77b88482015-04-07 15:47:50 -070040import org.onosproject.net.driver.DriverHandler;
41import org.onosproject.net.driver.DriverService;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070042import org.onosproject.net.flow.FlowRuleService;
alshabib77b88482015-04-07 15:47:50 -070043import org.onosproject.net.flowobjective.FilteringObjective;
44import org.onosproject.net.flowobjective.FlowObjectiveService;
alshabib2a441c62015-04-13 18:39:38 -070045import org.onosproject.net.flowobjective.FlowObjectiveStore;
46import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
alshabib77b88482015-04-07 15:47:50 -070047import org.onosproject.net.flowobjective.ForwardingObjective;
48import org.onosproject.net.flowobjective.NextObjective;
alshabib910aff12015-04-09 16:55:57 -070049import org.onosproject.net.flowobjective.Objective;
Jonathan Hart17d00452015-04-21 17:10:00 -070050import org.onosproject.net.flowobjective.ObjectiveError;
alshabib2a441c62015-04-13 18:39:38 -070051import org.onosproject.net.flowobjective.ObjectiveEvent;
Saurav Das423fe2b2015-12-04 10:52:59 -080052import org.onosproject.net.flowobjective.ObjectiveEvent.Type;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070053import org.onosproject.net.group.GroupService;
alshabib77b88482015-04-07 15:47:50 -070054import org.slf4j.Logger;
55import org.slf4j.LoggerFactory;
56
Saurav Das24431192016-03-07 19:13:00 -080057import java.util.ArrayList;
Saurav Das4ce45962015-11-24 23:21:05 -080058import java.util.Collections;
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;
Saurav Das4ce45962015-11-24 23:21:05 -080063import java.util.concurrent.ConcurrentHashMap;
Jonathan Hart17d00452015-04-21 17:10:00 -070064import java.util.concurrent.ExecutorService;
alshabib77b88482015-04-07 15:47:50 -070065
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -070066import static com.google.common.base.Preconditions.checkNotNull;
Thomas Vachuska866b46a2015-04-30 00:26:55 -070067import static java.util.concurrent.Executors.newFixedThreadPool;
Jonathan Hart17d00452015-04-21 17:10:00 -070068import static org.onlab.util.Tools.groupedThreads;
Changhoon Yoon541ef712015-05-23 17:18:34 +090069import static org.onosproject.security.AppGuard.checkPermission;
Changhoon Yoonb856b812015-08-10 03:47:19 +090070import static org.onosproject.security.AppPermission.Type.*;
71
Changhoon Yoon541ef712015-05-23 17:18:34 +090072
alshabib77b88482015-04-07 15:47:50 -070073
74/**
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070075 * Provides implementation of the flow objective programming service.
alshabib77b88482015-04-07 15:47:50 -070076 */
alshabib2a441c62015-04-13 18:39:38 -070077@Component(immediate = true)
alshabib77b88482015-04-07 15:47:50 -070078@Service
79public class FlowObjectiveManager implements FlowObjectiveService {
80
Saurav Dasbd7f7422015-04-23 16:31:47 -070081 public static final int INSTALL_RETRY_ATTEMPTS = 5;
Jonathan Hart17d00452015-04-21 17:10:00 -070082 public static final long INSTALL_RETRY_INTERVAL = 1000; // ms
alshabib77b88482015-04-07 15:47:50 -070083
Jonathan Hart17d00452015-04-21 17:10:00 -070084 private final Logger log = LoggerFactory.getLogger(getClass());
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070085
alshabib77b88482015-04-07 15:47:50 -070086 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected DriverService driverService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected DeviceService deviceService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected MastershipService mastershipService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected ClusterService clusterService;
97
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070098 // Note: The following dependencies are added on behalf of the pipeline
99 // driver behaviours to assure these services are available for their
100 // initialization.
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected FlowRuleService flowRuleService;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected GroupService groupService;
106
alshabib2a441c62015-04-13 18:39:38 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected FlowObjectiveStore flowObjectiveStore;
109
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700110 // Note: This must remain an optional dependency to allow re-install of default drivers.
111 // Note: For now disabled until we can move to OPTIONAL_UNARY dependency
112 // @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected DefaultDriverProviderService defaultDriverService;
115
alshabib2a441c62015-04-13 18:39:38 -0700116 private final FlowObjectiveStoreDelegate delegate = new InternalStoreDelegate();
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700117
118 private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap();
alshabib910aff12015-04-09 16:55:57 -0700119 private final Map<DeviceId, Pipeliner> pipeliners = Maps.newConcurrentMap();
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700120
121 private final PipelinerContext context = new InnerPipelineContext();
122 private final MastershipListener mastershipListener = new InnerMastershipListener();
123 private final DeviceListener deviceListener = new InnerDeviceListener();
124
alshabib77b88482015-04-07 15:47:50 -0700125 protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
alshabib910aff12015-04-09 16:55:57 -0700126
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700127 private Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap();
alshabib2a441c62015-04-13 18:39:38 -0700128
Saurav Das24431192016-03-07 19:13:00 -0800129 // local store to track which nextObjectives were sent to which device
130 // for debugging purposes
131 private Map<Integer, DeviceId> nextToDevice = Maps.newConcurrentMap();
132
Jonathan Hart17d00452015-04-21 17:10:00 -0700133 private ExecutorService executorService;
alshabib2a441c62015-04-13 18:39:38 -0700134
alshabib77b88482015-04-07 15:47:50 -0700135 @Activate
136 protected void activate() {
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700137 executorService = newFixedThreadPool(4, groupedThreads("onos/objective-installer", "%d"));
alshabib2a441c62015-04-13 18:39:38 -0700138 flowObjectiveStore.setDelegate(delegate);
alshabib77b88482015-04-07 15:47:50 -0700139 mastershipService.addListener(mastershipListener);
alshabibaebe7752015-04-07 17:45:42 -0700140 deviceService.addListener(deviceListener);
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700141 deviceService.getDevices().forEach(device -> setupPipelineHandler(device.id()));
alshabib77b88482015-04-07 15:47:50 -0700142 log.info("Started");
143 }
144
145 @Deactivate
146 protected void deactivate() {
alshabib2a441c62015-04-13 18:39:38 -0700147 flowObjectiveStore.unsetDelegate(delegate);
alshabib77b88482015-04-07 15:47:50 -0700148 mastershipService.removeListener(mastershipListener);
alshabibaebe7752015-04-07 17:45:42 -0700149 deviceService.removeListener(deviceListener);
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700150 executorService.shutdown();
151 pipeliners.clear();
152 driverHandlers.clear();
Saurav Das24431192016-03-07 19:13:00 -0800153 nextToDevice.clear();
alshabib77b88482015-04-07 15:47:50 -0700154 log.info("Stopped");
155 }
156
Jonathan Hart17d00452015-04-21 17:10:00 -0700157 /**
158 * Task that passes the flow objective down to the driver. The task will
159 * make a few attempts to find the appropriate driver, then eventually give
160 * up and report an error if no suitable driver could be found.
161 */
162 private class ObjectiveInstaller implements Runnable {
163 private final DeviceId deviceId;
164 private final Objective objective;
165
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -0700166 private final int numAttempts;
Jonathan Hart17d00452015-04-21 17:10:00 -0700167
168 public ObjectiveInstaller(DeviceId deviceId, Objective objective) {
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -0700169 this(deviceId, objective, 1);
170 }
171
172 public ObjectiveInstaller(DeviceId deviceId, Objective objective, int attemps) {
173 this.deviceId = checkNotNull(deviceId);
174 this.objective = checkNotNull(objective);
175 this.numAttempts = checkNotNull(attemps);
alshabib910aff12015-04-09 16:55:57 -0700176 }
alshabib77b88482015-04-07 15:47:50 -0700177
Jonathan Hart17d00452015-04-21 17:10:00 -0700178 @Override
179 public void run() {
180 try {
Jonathan Hart17d00452015-04-21 17:10:00 -0700181 Pipeliner pipeliner = getDevicePipeliner(deviceId);
182
183 if (pipeliner != null) {
184 if (objective instanceof NextObjective) {
185 pipeliner.next((NextObjective) objective);
186 } else if (objective instanceof ForwardingObjective) {
187 pipeliner.forward((ForwardingObjective) objective);
188 } else {
189 pipeliner.filter((FilteringObjective) objective);
190 }
Andrea Campanella1f8188d2016-02-29 13:24:54 -0800191 //Attempts to check if pipeliner is null for retry attempts
Jonathan Hart17d00452015-04-21 17:10:00 -0700192 } else if (numAttempts < INSTALL_RETRY_ATTEMPTS) {
Saurav Das3d038262015-04-23 12:36:58 -0700193 Thread.sleep(INSTALL_RETRY_INTERVAL);
Sho SHIMIZUf45d85d2015-07-01 14:39:11 -0700194 executorService.submit(new ObjectiveInstaller(deviceId, objective, numAttempts + 1));
Jonathan Hart17d00452015-04-21 17:10:00 -0700195 } else {
196 // Otherwise we've tried a few times and failed, report an
197 // error back to the user.
198 objective.context().ifPresent(
Andrea Campanella1f8188d2016-02-29 13:24:54 -0800199 c -> c.onError(objective, ObjectiveError.NOPIPELINER));
Jonathan Hart17d00452015-04-21 17:10:00 -0700200 }
Andrea Campanella1f8188d2016-02-29 13:24:54 -0800201 //Excpetion thrown
Jonathan Hart17d00452015-04-21 17:10:00 -0700202 } catch (Exception e) {
203 log.warn("Exception while installing flow objective", e);
204 }
205 }
206 }
207
208 @Override
209 public void filter(DeviceId deviceId, FilteringObjective filteringObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900210 checkPermission(FLOWRULE_WRITE);
Jonathan Hart17d00452015-04-21 17:10:00 -0700211 executorService.submit(new ObjectiveInstaller(deviceId, filteringObjective));
alshabib77b88482015-04-07 15:47:50 -0700212 }
213
214 @Override
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700215 public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900216 checkPermission(FLOWRULE_WRITE);
alshabib2a441c62015-04-13 18:39:38 -0700217 if (queueObjective(deviceId, forwardingObjective)) {
218 return;
alshabib910aff12015-04-09 16:55:57 -0700219 }
Jonathan Hart17d00452015-04-21 17:10:00 -0700220 executorService.submit(new ObjectiveInstaller(deviceId, forwardingObjective));
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700221 }
222
alshabib2a441c62015-04-13 18:39:38 -0700223 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700224 public void next(DeviceId deviceId, NextObjective nextObjective) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900225 checkPermission(FLOWRULE_WRITE);
Saurav Das24431192016-03-07 19:13:00 -0800226 nextToDevice.put(nextObjective.id(), deviceId);
Jonathan Hart17d00452015-04-21 17:10:00 -0700227 executorService.submit(new ObjectiveInstaller(deviceId, nextObjective));
alshabib2a441c62015-04-13 18:39:38 -0700228 }
229
alshabibf6ea9e62015-04-21 17:08:26 -0700230 @Override
231 public int allocateNextId() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900232 checkPermission(FLOWRULE_WRITE);
alshabibf6ea9e62015-04-21 17:08:26 -0700233 return flowObjectiveStore.allocateNextId();
234 }
235
Xin Jin313708b2015-07-09 13:43:04 -0700236 @Override
237 public void initPolicy(String policy) {}
238
alshabib2a441c62015-04-13 18:39:38 -0700239 private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) {
240 if (fwd.nextId() != null &&
241 flowObjectiveStore.getNextGroup(fwd.nextId()) == null) {
Saurav Das3ea46622015-04-22 14:01:34 -0700242 log.trace("Queuing forwarding objective for nextId {}", fwd.nextId());
Saurav Das8a0732e2015-11-20 15:27:53 -0800243 // TODO: change to computeIfAbsent
Saurav Das4ce45962015-11-24 23:21:05 -0800244 Set<PendingNext> newset = Collections.newSetFromMap(
245 new ConcurrentHashMap<PendingNext, Boolean>());
246 newset.add(new PendingNext(deviceId, fwd));
247 Set<PendingNext> pnext = pendingForwards.putIfAbsent(fwd.nextId(), newset);
Saurav Das8a0732e2015-11-20 15:27:53 -0800248 if (pnext != null) {
249 pnext.add(new PendingNext(deviceId, fwd));
alshabib2a441c62015-04-13 18:39:38 -0700250 }
251 return true;
252 }
253 return false;
254 }
255
alshabib910aff12015-04-09 16:55:57 -0700256 // Retrieves the device pipeline behaviour from the cache.
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700257 private Pipeliner getDevicePipeliner(DeviceId deviceId) {
Thomas Vachuska94c3cf42015-07-20 13:01:12 -0700258 return pipeliners.get(deviceId);
alshabib77b88482015-04-07 15:47:50 -0700259 }
260
alshabib2a441c62015-04-13 18:39:38 -0700261 private void setupPipelineHandler(DeviceId deviceId) {
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700262 if (defaultDriverService == null) {
263 // We're not ready to go to work yet.
264 return;
265 }
266
Jonathan Hart17d00452015-04-21 17:10:00 -0700267 // Attempt to lookup the handler in the cache
268 DriverHandler handler = driverHandlers.get(deviceId);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700269 cTime = now();
270
Jonathan Hart17d00452015-04-21 17:10:00 -0700271 if (handler == null) {
272 try {
273 // Otherwise create it and if it has pipeline behaviour, cache it
274 handler = driverService.createHandler(deviceId);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700275 dTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700276 if (!handler.driver().hasBehaviour(Pipeliner.class)) {
277 log.warn("Pipeline behaviour not supported for device {}",
278 deviceId);
alshabib2a441c62015-04-13 18:39:38 -0700279 return;
280 }
Jonathan Hart17d00452015-04-21 17:10:00 -0700281 } catch (ItemNotFoundException e) {
282 log.warn("No applicable driver for device {}", deviceId);
283 return;
alshabib2a441c62015-04-13 18:39:38 -0700284 }
285
Jonathan Hart17d00452015-04-21 17:10:00 -0700286 driverHandlers.put(deviceId, handler);
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700287 eTime = now();
alshabib2a441c62015-04-13 18:39:38 -0700288 }
Jonathan Hart17d00452015-04-21 17:10:00 -0700289
290 // Always (re)initialize the pipeline behaviour
291 log.info("Driver {} bound to device {} ... initializing driver",
292 handler.driver().name(), deviceId);
Thomas Vachuska0121a612015-07-21 11:18:09 -0700293 hTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700294 Pipeliner pipeliner = handler.behaviour(Pipeliner.class);
Thomas Vachuska94c3cf42015-07-20 13:01:12 -0700295 hbTime = now();
Jonathan Hart17d00452015-04-21 17:10:00 -0700296 pipeliner.init(deviceId, context);
297 pipeliners.putIfAbsent(deviceId, pipeliner);
alshabib2a441c62015-04-13 18:39:38 -0700298 }
alshabibaebe7752015-04-07 17:45:42 -0700299
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700300 // Triggers driver setup when the local node becomes a device master.
alshabib77b88482015-04-07 15:47:50 -0700301 private class InnerMastershipListener implements MastershipListener {
302 @Override
303 public void event(MastershipEvent event) {
304 switch (event.type()) {
alshabib77b88482015-04-07 15:47:50 -0700305 case MASTER_CHANGED:
Madan Jampani0174f452015-05-29 11:52:05 -0700306 log.debug("mastership changed on device {}", event.subject());
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700307 start = now();
Saurav Das3d038262015-04-23 12:36:58 -0700308 if (deviceService.isAvailable(event.subject())) {
309 setupPipelineHandler(event.subject());
310 }
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700311 stopWatch();
alshabib4313d102015-04-08 18:55:08 -0700312 break;
313 case BACKUPS_CHANGED:
alshabib77b88482015-04-07 15:47:50 -0700314 break;
315 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700316 break;
alshabib77b88482015-04-07 15:47:50 -0700317 }
318 }
alshabibaebe7752015-04-07 17:45:42 -0700319 }
alshabib77b88482015-04-07 15:47:50 -0700320
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700321 // Triggers driver setup when a device is (re)detected.
alshabibaebe7752015-04-07 17:45:42 -0700322 private class InnerDeviceListener implements DeviceListener {
323 @Override
324 public void event(DeviceEvent event) {
325 switch (event.type()) {
326 case DEVICE_ADDED:
327 case DEVICE_AVAILABILITY_CHANGED:
Madan Jampani0174f452015-05-29 11:52:05 -0700328 log.debug("Device either added or availability changed {}",
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700329 event.subject().id());
330 start = now();
alshabib4313d102015-04-08 18:55:08 -0700331 if (deviceService.isAvailable(event.subject().id())) {
Madan Jampani0174f452015-05-29 11:52:05 -0700332 log.debug("Device is now available {}", event.subject().id());
alshabib4313d102015-04-08 18:55:08 -0700333 setupPipelineHandler(event.subject().id());
334 }
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700335 stopWatch();
alshabib4313d102015-04-08 18:55:08 -0700336 break;
337 case DEVICE_UPDATED:
338 break;
339 case DEVICE_REMOVED:
340 break;
341 case DEVICE_SUSPENDED:
342 break;
343 case PORT_ADDED:
344 break;
345 case PORT_UPDATED:
346 break;
347 case PORT_REMOVED:
alshabibaebe7752015-04-07 17:45:42 -0700348 break;
349 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700350 break;
alshabibaebe7752015-04-07 17:45:42 -0700351 }
alshabib77b88482015-04-07 15:47:50 -0700352 }
353 }
alshabibaebe7752015-04-07 17:45:42 -0700354
Thomas Vachuska174bb912015-07-16 21:27:14 -0700355 // Temporary mechanism to monitor pipeliner setup time-cost; there are
356 // intermittent time where this takes in excess of 2 seconds. Why?
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700357 private long start = 0, totals = 0, count = 0;
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700358 private long cTime, dTime, eTime, hTime, hbTime;
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700359 private static final long LIMIT = 500;
Thomas Vachuska174bb912015-07-16 21:27:14 -0700360
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700361 private long now() {
Thomas Vachuska174bb912015-07-16 21:27:14 -0700362 return System.currentTimeMillis();
363 }
364
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700365 private void stopWatch() {
Thomas Vachuska174bb912015-07-16 21:27:14 -0700366 long duration = System.currentTimeMillis() - start;
367 totals += duration;
368 count += 1;
369 if (duration > LIMIT) {
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700370 log.info("Pipeline setup took {} ms; avg {} ms; cTime={}, dTime={}, eTime={}, hTime={}, hbTime={}",
371 duration, totals / count, diff(cTime), diff(dTime), diff(eTime), diff(hTime), diff(hbTime));
Thomas Vachuska174bb912015-07-16 21:27:14 -0700372 }
373 }
374
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700375 private long diff(long bTime) {
Thomas Vachuskab19bffb2015-07-22 10:56:16 -0700376 long diff = bTime - start;
377 return diff < 0 ? 0 : diff;
Thomas Vachuska9c9ff7c2015-07-20 10:38:59 -0700378 }
379
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700380 // Processing context for initializing pipeline driver behaviours.
381 private class InnerPipelineContext implements PipelinerContext {
382 @Override
383 public ServiceDirectory directory() {
384 return serviceDirectory;
alshabibaebe7752015-04-07 17:45:42 -0700385 }
alshabib2a441c62015-04-13 18:39:38 -0700386
387 @Override
388 public FlowObjectiveStore store() {
389 return flowObjectiveStore;
390 }
alshabib2a441c62015-04-13 18:39:38 -0700391 }
392
393 private class InternalStoreDelegate implements FlowObjectiveStoreDelegate {
394 @Override
395 public void notify(ObjectiveEvent event) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800396 if (event.type() == Type.ADD) {
397 log.debug("Received notification of obj event {}", event);
398 Set<PendingNext> pending = pendingForwards.remove(event.subject());
alshabib2a441c62015-04-13 18:39:38 -0700399
Saurav Das423fe2b2015-12-04 10:52:59 -0800400 if (pending == null) {
Saurav Das49cb5a12016-01-16 22:54:07 -0800401 log.warn("Nothing pending for this obj event {}", event);
Saurav Das423fe2b2015-12-04 10:52:59 -0800402 return;
403 }
404
Saurav Das49cb5a12016-01-16 22:54:07 -0800405 log.debug("Processing {} pending forwarding objectives for nextId {}",
406 pending.size(), event.subject());
Saurav Das423fe2b2015-12-04 10:52:59 -0800407 pending.forEach(p -> getDevicePipeliner(p.deviceId())
408 .forward(p.forwardingObjective()));
alshabib2a441c62015-04-13 18:39:38 -0700409 }
alshabib2a441c62015-04-13 18:39:38 -0700410 }
411 }
412
413 /**
414 * Data class used to hold a pending forwarding objective that could not
415 * be processed because the associated next object was not present.
416 */
417 private class PendingNext {
418 private final DeviceId deviceId;
419 private final ForwardingObjective fwd;
420
421 public PendingNext(DeviceId deviceId, ForwardingObjective fwd) {
422 this.deviceId = deviceId;
423 this.fwd = fwd;
424 }
425
426 public DeviceId deviceId() {
427 return deviceId;
428 }
429
430 public ForwardingObjective forwardingObjective() {
431 return fwd;
432 }
Saurav Das8a0732e2015-11-20 15:27:53 -0800433
434 @Override
435 public int hashCode() {
436 return Objects.hash(deviceId, fwd);
437 }
438
439 @Override
440 public boolean equals(final Object obj) {
441 if (this == obj) {
442 return true;
443 }
444 if (!(obj instanceof PendingNext)) {
445 return false;
446 }
447 final PendingNext other = (PendingNext) obj;
448 if (this.deviceId.equals(other.deviceId) &&
449 this.fwd.equals(other.fwd)) {
450 return true;
451 }
452 return false;
453 }
alshabibaebe7752015-04-07 17:45:42 -0700454 }
Saurav Das24431192016-03-07 19:13:00 -0800455
456 @Override
457 public List<String> getNextMappings() {
458 List<String> mappings = new ArrayList<>();
459 Map<Integer, NextGroup> allnexts = flowObjectiveStore.getAllGroups();
460 // XXX if the NextGroup upon decoding stored info of the deviceId
461 // then info on any nextObj could be retrieved from one controller instance.
462 // Right now the drivers on one instance can only fetch for next-ids that came
463 // to them.
464 // Also, we still need to send the right next-id to the right driver as potentially
465 // there can be different drivers for different devices. But on that account,
466 // no instance should be decoding for another instance's nextIds.
467
468 for (Map.Entry<Integer, NextGroup> e : allnexts.entrySet()) {
469 // get the device this next Objective was sent to
470 DeviceId deviceId = nextToDevice.get(e.getKey());
471 mappings.add("NextId " + e.getKey() + ": " +
472 ((deviceId != null) ? deviceId : "nextId not in this onos instance"));
473 if (deviceId != null) {
474 // this instance of the controller sent the nextObj to a driver
475 Pipeliner pipeliner = getDevicePipeliner(deviceId);
476 List<String> nextMappings = pipeliner.getNextMappings(e.getValue());
477 if (nextMappings != null) {
478 mappings.addAll(nextMappings);
479 }
480 }
481 }
482 return mappings;
483 }
alshabib77b88482015-04-07 15:47:50 -0700484}