blob: 1fe10a5cd0229a229107a0a11273f0bc110a60bb [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.packet.impl;
alshabib7674db42014-09-12 23:40:46 -070017
Thomas Vachuska924cda42015-09-22 12:11:27 -070018import com.google.common.collect.ImmutableList;
19import com.google.common.collect.Lists;
alshabib7674db42014-09-12 23:40:46 -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;
Madan Jampani6f8b7022015-12-07 16:59:59 -080026import org.onosproject.cluster.ClusterService;
27import org.onosproject.cluster.NodeId;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080028import org.onosproject.core.ApplicationId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070029import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.Device;
alshabib19e2cea2015-12-07 11:31:49 -080031import org.onosproject.net.DeviceId;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080032import org.onosproject.net.device.DeviceEvent;
33import org.onosproject.net.device.DeviceListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.device.DeviceService;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080035import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080036import org.onosproject.net.flow.TrafficSelector;
Charles Chan874900e2016-12-09 16:55:39 -080037import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart17d00452015-04-21 17:10:00 -070038import org.onosproject.net.flowobjective.DefaultForwardingObjective;
39import org.onosproject.net.flowobjective.FlowObjectiveService;
40import org.onosproject.net.flowobjective.ForwardingObjective;
41import org.onosproject.net.flowobjective.Objective;
42import org.onosproject.net.flowobjective.ObjectiveContext;
43import org.onosproject.net.flowobjective.ObjectiveError;
alshabib42947782015-03-31 14:59:06 -070044import org.onosproject.net.packet.DefaultPacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080045import org.onosproject.net.packet.OutboundPacket;
46import org.onosproject.net.packet.PacketContext;
47import org.onosproject.net.packet.PacketEvent;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080048import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska924cda42015-09-22 12:11:27 -070050import org.onosproject.net.packet.PacketProcessorEntry;
Brian O'Connorabafb502014-12-02 22:26:20 -080051import org.onosproject.net.packet.PacketProvider;
52import org.onosproject.net.packet.PacketProviderRegistry;
53import org.onosproject.net.packet.PacketProviderService;
alshabib42947782015-03-31 14:59:06 -070054import org.onosproject.net.packet.PacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080055import org.onosproject.net.packet.PacketService;
56import org.onosproject.net.packet.PacketStore;
57import org.onosproject.net.packet.PacketStoreDelegate;
58import org.onosproject.net.provider.AbstractProviderRegistry;
59import org.onosproject.net.provider.AbstractProviderService;
alshabib7674db42014-09-12 23:40:46 -070060import org.slf4j.Logger;
61
Thomas Vachuska7f171b22015-08-21 12:49:08 -070062import java.util.List;
alshabib19e2cea2015-12-07 11:31:49 -080063import java.util.Optional;
Madan Jampanic626f1e2015-05-29 13:53:38 -070064import java.util.concurrent.ExecutorService;
65import java.util.concurrent.Executors;
alshabib089bb772015-03-03 18:26:26 -080066
67import static com.google.common.base.Preconditions.checkNotNull;
Madan Jampanic626f1e2015-05-29 13:53:38 -070068import static org.onlab.util.Tools.groupedThreads;
Changhoon Yoon541ef712015-05-23 17:18:34 +090069import static org.onosproject.security.AppGuard.checkPermission;
Jonathan Hartdbaed992016-09-08 22:04:33 -070070import static org.onosproject.security.AppPermission.Type.PACKET_EVENT;
71import static org.onosproject.security.AppPermission.Type.PACKET_READ;
72import static org.onosproject.security.AppPermission.Type.PACKET_WRITE;
Thomas Vachuska7f171b22015-08-21 12:49:08 -070073import static org.slf4j.LoggerFactory.getLogger;
alshabib089bb772015-03-03 18:26:26 -080074
alshabib7674db42014-09-12 23:40:46 -070075/**
76 * Provides a basic implementation of the packet SB & NB APIs.
alshabib7674db42014-09-12 23:40:46 -070077 */
78@Component(immediate = true)
79@Service
tom202175a2014-09-19 19:00:11 -070080public class PacketManager
Thomas Vachuska6cba4952015-04-22 12:38:22 -070081 extends AbstractProviderRegistry<PacketProvider, PacketProviderService>
82 implements PacketService, PacketProviderRegistry {
alshabib7674db42014-09-12 23:40:46 -070083
84 private final Logger log = getLogger(getClass());
85
Jonathan Hartdbaed992016-09-08 22:04:33 -070086 private static final String ERROR_NULL_PROCESSOR = "Processor cannot be null";
87 private static final String ERROR_NULL_SELECTOR = "Selector cannot be null";
88 private static final String ERROR_NULL_APP_ID = "Application ID cannot be null";
89 private static final String ERROR_NULL_DEVICE_ID = "Device ID cannot be null";
Thomas Vachuska27bee092015-06-23 19:03:10 -070090
Jonathan Hart4f60f982014-10-27 08:11:17 -070091 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
92
alshabib7674db42014-09-12 23:40:46 -070093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -080094 protected CoreService coreService;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070095
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -080097 protected ClusterService clusterService;
Madan Jampani6f8b7022015-12-07 16:59:59 -080098
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800100 protected DeviceService deviceService;
alshabib7674db42014-09-12 23:40:46 -0700101
Jonathan Hart4f60f982014-10-27 08:11:17 -0700102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800103 protected PacketStore store;
Jonathan Hart4f60f982014-10-27 08:11:17 -0700104
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hartdbaed992016-09-08 22:04:33 -0700106 protected FlowObjectiveService objectiveService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700107
Madan Jampanic626f1e2015-05-29 13:53:38 -0700108 private ExecutorService eventHandlingExecutor;
109
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800110 private final DeviceListener deviceListener = new InternalDeviceListener();
111
Thomas Vachuska924cda42015-09-22 12:11:27 -0700112 private final List<ProcessorEntry> processors = Lists.newCopyOnWriteArrayList();
alshabib7674db42014-09-12 23:40:46 -0700113
Andrea Campanella5b240532016-02-05 09:44:41 -0800114 private final PacketDriverProvider defaultProvider = new PacketDriverProvider();
115
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700116 private ApplicationId appId;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800117 private NodeId localNodeId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700118
alshabib7674db42014-09-12 23:40:46 -0700119 @Activate
120 public void activate() {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700121 eventHandlingExecutor = Executors.newSingleThreadExecutor(
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700122 groupedThreads("onos/net/packet", "event-handler", log));
Madan Jampani6f8b7022015-12-07 16:59:59 -0800123 localNodeId = clusterService.getLocalNode().id();
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700124 appId = coreService.getAppId(CoreService.CORE_APP_NAME);
Jonathan Hart4f60f982014-10-27 08:11:17 -0700125 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800126 deviceService.addListener(deviceListener);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700127 store.existingRequests().forEach(this::pushToAllDevices);
Andrea Campanella5b240532016-02-05 09:44:41 -0800128 defaultProvider.init(deviceService);
alshabib7674db42014-09-12 23:40:46 -0700129 log.info("Started");
130 }
131
132 @Deactivate
133 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700134 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800135 deviceService.removeListener(deviceListener);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700136 eventHandlingExecutor.shutdown();
alshabib7674db42014-09-12 23:40:46 -0700137 log.info("Stopped");
138 }
139
140 @Override
Andrea Campanella5b240532016-02-05 09:44:41 -0800141 protected PacketProvider defaultProvider() {
142 return defaultProvider;
143 }
144
145 @Override
alshabib7674db42014-09-12 23:40:46 -0700146 public void addProcessor(PacketProcessor processor, int priority) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900147 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700148 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700149 ProcessorEntry entry = new ProcessorEntry(processor, priority);
150
151 // Insert the new processor according to its priority.
152 int i = 0;
153 for (; i < processors.size(); i++) {
154 if (priority < processors.get(i).priority()) {
155 break;
156 }
157 }
158 processors.add(i, entry);
alshabib7674db42014-09-12 23:40:46 -0700159 }
160
161 @Override
162 public void removeProcessor(PacketProcessor processor) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900163 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700164 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700165
166 // Remove the processor entry.
167 for (int i = 0; i < processors.size(); i++) {
168 if (processors.get(i).processor() == processor) {
169 processors.remove(i);
170 break;
171 }
172 }
alshabib7674db42014-09-12 23:40:46 -0700173 }
174
175 @Override
Thomas Vachuska924cda42015-09-22 12:11:27 -0700176 public List<PacketProcessorEntry> getProcessors() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900177 checkPermission(PACKET_READ);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700178 return ImmutableList.copyOf(processors);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700179 }
180
181 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800182 public void requestPackets(TrafficSelector selector, PacketPriority priority,
183 ApplicationId appId) {
Charles Chan874900e2016-12-09 16:55:39 -0800184 this.requestPackets(selector, priority, appId, false);
185 }
186
187 @Override
188 public void requestPackets(TrafficSelector selector, PacketPriority priority,
189 ApplicationId appId, boolean copy) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900190 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700191 checkNotNull(selector, ERROR_NULL_SELECTOR);
192 checkNotNull(appId, ERROR_NULL_APP_ID);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800193
alshabib19e2cea2015-12-07 11:31:49 -0800194 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Charles Chan874900e2016-12-09 16:55:39 -0800195 localNodeId, Optional.empty(), copy);
196
Brian O'Connor21b028e2015-10-08 22:50:02 -0700197 store.requestPackets(request);
Saurav Dasc313c402015-02-27 10:09:47 -0800198 }
199
200 @Override
alshabib19e2cea2015-12-07 11:31:49 -0800201 public void requestPackets(TrafficSelector selector, PacketPriority priority,
202 ApplicationId appId, Optional<DeviceId> deviceId) {
203 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700204 checkNotNull(selector, ERROR_NULL_SELECTOR);
205 checkNotNull(appId, ERROR_NULL_APP_ID);
206 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800207
208 PacketRequest request =
209 new DefaultPacketRequest(selector, priority, appId,
210 localNodeId, deviceId);
211
212 store.requestPackets(request);
alshabib19e2cea2015-12-07 11:31:49 -0800213 }
214
215 @Override
Thomas Vachuska27bee092015-06-23 19:03:10 -0700216 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
217 ApplicationId appId) {
Charles Chan874900e2016-12-09 16:55:39 -0800218 this.cancelPackets(selector, priority, appId, false);
219 }
220
221 @Override
222 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
223 ApplicationId appId, boolean copy) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900224 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700225 checkNotNull(selector, ERROR_NULL_SELECTOR);
226 checkNotNull(appId, ERROR_NULL_APP_ID);
Saurav Dasc313c402015-02-27 10:09:47 -0800227
alshabib19e2cea2015-12-07 11:31:49 -0800228 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Charles Chan874900e2016-12-09 16:55:39 -0800229 localNodeId, Optional.empty(), copy);
alshabib19e2cea2015-12-07 11:31:49 -0800230 store.cancelPackets(request);
231 }
232
233 @Override
234 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
235 ApplicationId appId, Optional<DeviceId> deviceId) {
236 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700237 checkNotNull(selector, ERROR_NULL_SELECTOR);
238 checkNotNull(appId, ERROR_NULL_APP_ID);
239 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800240
241 PacketRequest request = new DefaultPacketRequest(selector, priority,
242 appId, localNodeId,
243 deviceId);
Brian O'Connor21b028e2015-10-08 22:50:02 -0700244 store.cancelPackets(request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800245 }
246
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700247 @Override
248 public List<PacketRequest> getRequests() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900249 checkPermission(PACKET_READ);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700250 return store.existingRequests();
251 }
252
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800253 /**
Thomas Vachuska924cda42015-09-22 12:11:27 -0700254 * Pushes all rules to the specified device.
255 *
256 * @param device device on which to install packet request flows
257 */
258 private void pushRulesToDevice(Device device) {
259 log.debug("Pushing packet requests to device {}", device.id());
260 for (PacketRequest request : store.existingRequests()) {
alshabib19e2cea2015-12-07 11:31:49 -0800261 if (!request.deviceId().isPresent()) {
262 pushRule(device, request);
263 } else if (request.deviceId().get().equals(device.id())) {
264 pushRule(device, request);
265 }
266
Thomas Vachuska924cda42015-09-22 12:11:27 -0700267 }
268 }
269
270 /**
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800271 * Pushes a packet request flow rule to all devices.
272 *
273 * @param request the packet request
274 */
275 private void pushToAllDevices(PacketRequest request) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700276 log.debug("Pushing packet request {} to all devices", request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800277 for (Device device : deviceService.getDevices()) {
alshabib42947782015-03-31 14:59:06 -0700278 pushRule(device, request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800279 }
280 }
281
282 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700283 * Removes packet request flow rule from all devices.
284 *
285 * @param request the packet request
286 */
287 private void removeFromAllDevices(PacketRequest request) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700288 deviceService.getAvailableDevices().forEach(d -> removeRule(d, request));
Thomas Vachuska27bee092015-06-23 19:03:10 -0700289 }
290
291 /**
292 * Pushes packet intercept flow rules to the device.
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800293 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700294 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800295 * @param request the packet request
296 */
297 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700298 if (!device.type().equals(Device.Type.SWITCH)) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800299 return;
300 }
301
Thomas Vachuska27bee092015-06-23 19:03:10 -0700302 ForwardingObjective forwarding = createBuilder(request)
Jonathan Hart17d00452015-04-21 17:10:00 -0700303 .add(new ObjectiveContext() {
304 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700305 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700306 log.warn("Failed to install packet request {} to {}: {}",
307 request, device.id(), error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700308 }
309 });
310
311 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800312 }
313
Thomas Vachuska27bee092015-06-23 19:03:10 -0700314 /**
315 * Removes packet intercept flow rules from the device.
316 *
317 * @param device the device to remove the rules deom
318 * @param request the packet request
319 */
320 private void removeRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700321 if (!device.type().equals(Device.Type.SWITCH)) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700322 return;
323 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700324 ForwardingObjective forwarding = createBuilder(request)
325 .remove(new ObjectiveContext() {
326 @Override
327 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700328 log.warn("Failed to withdraw packet request {} from {}: {}",
329 request, device.id(), error);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700330 }
331 });
Thomas Vachuska27bee092015-06-23 19:03:10 -0700332 objectiveService.forward(device.id(), forwarding);
333 }
334
335 private DefaultForwardingObjective.Builder createBuilder(PacketRequest request) {
Charles Chan874900e2016-12-09 16:55:39 -0800336 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
337 tBuilder.punt();
338 if (!request.copy()) {
339 tBuilder.wipeDeferred();
340 }
341
Thomas Vachuska27bee092015-06-23 19:03:10 -0700342 return DefaultForwardingObjective.builder()
343 .withPriority(request.priority().priorityValue())
344 .withSelector(request.selector())
345 .fromApp(appId)
346 .withFlag(ForwardingObjective.Flag.VERSATILE)
Charles Chan874900e2016-12-09 16:55:39 -0800347 .withTreatment(tBuilder.build())
Thomas Vachuska27bee092015-06-23 19:03:10 -0700348 .makePermanent();
349 }
350
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800351 @Override
alshabib7674db42014-09-12 23:40:46 -0700352 public void emit(OutboundPacket packet) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900353 checkPermission(PACKET_WRITE);
tomc370ebd2014-09-16 01:25:21 -0700354 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700355 store.emit(packet);
356 }
357
358 private void localEmit(OutboundPacket packet) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700359 Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800360 if (device == null) {
361 return;
362 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700363 PacketProvider packetProvider = getProvider(device.providerId());
alshabib3d643ec2014-10-22 18:33:00 -0700364 if (packetProvider != null) {
365 packetProvider.emit(packet);
366 }
alshabib7674db42014-09-12 23:40:46 -0700367 }
368
369 @Override
tomc370ebd2014-09-16 01:25:21 -0700370 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700371 return new InternalPacketProviderService(provider);
372 }
373
Thomas Vachuska924cda42015-09-22 12:11:27 -0700374 /**
375 * Personalized packet provider service issued to the supplied provider.
376 */
alshabib7674db42014-09-12 23:40:46 -0700377 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700378 extends AbstractProviderService<PacketProvider>
379 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700380
381 protected InternalPacketProviderService(PacketProvider provider) {
382 super(provider);
383 }
384
385 @Override
386 public void processPacket(PacketContext context) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800387 // TODO filter packets sent to processors based on registrations
Thomas Vachuska924cda42015-09-22 12:11:27 -0700388 for (ProcessorEntry entry : processors) {
Jonathan Hartf5638302015-11-16 10:56:20 -0800389 try {
390 long start = System.nanoTime();
391 entry.processor().process(context);
392 entry.addNanos(System.nanoTime() - start);
393 } catch (Exception e) {
394 log.warn("Packet processor {} threw an exception", entry.processor(), e);
395 }
alshabib7674db42014-09-12 23:40:46 -0700396 }
397 }
398
399 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700400
alshabib19e2cea2015-12-07 11:31:49 -0800401
Jonathan Hart4f60f982014-10-27 08:11:17 -0700402 /**
403 * Internal callback from the packet store.
404 */
Andrea Campanella5b240532016-02-05 09:44:41 -0800405 protected class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700406 @Override
407 public void notify(PacketEvent event) {
408 localEmit(event.subject());
409 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700410
411 @Override
412 public void requestPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800413 DeviceId deviceid = request.deviceId().orElse(null);
414
415 if (deviceid != null) {
416 pushRule(deviceService.getDevice(deviceid), request);
417 } else {
418 pushToAllDevices(request);
419 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700420 }
421
422 @Override
423 public void cancelPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800424 DeviceId deviceid = request.deviceId().orElse(null);
425
426 if (deviceid != null) {
427 removeRule(deviceService.getDevice(deviceid), request);
428 } else {
429 removeFromAllDevices(request);
430 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700431 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700432 }
433
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800434 /**
435 * Internal listener for device service events.
436 */
437 private class InternalDeviceListener implements DeviceListener {
438 @Override
439 public void event(DeviceEvent event) {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700440 eventHandlingExecutor.execute(() -> {
441 try {
442 Device device = event.subject();
443 switch (event.type()) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700444 case DEVICE_ADDED:
445 case DEVICE_AVAILABILITY_CHANGED:
446 if (deviceService.isAvailable(event.subject().id())) {
447 pushRulesToDevice(device);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700448 }
Thomas Vachuska924cda42015-09-22 12:11:27 -0700449 break;
450 default:
451 break;
sangho864a9db22015-04-28 12:06:31 -0700452 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700453 } catch (Exception e) {
454 log.warn("Failed to process {}", event, e);
455 }
456 });
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800457 }
458 }
459
Thomas Vachuska924cda42015-09-22 12:11:27 -0700460 /**
461 * Entity for tracking stats for a packet processor.
462 */
463 private class ProcessorEntry implements PacketProcessorEntry {
464 private final PacketProcessor processor;
465 private final int priority;
466 private long invocations = 0;
467 private long nanos = 0;
468
469 public ProcessorEntry(PacketProcessor processor, int priority) {
470 this.processor = processor;
471 this.priority = priority;
472 }
473
474 @Override
475 public PacketProcessor processor() {
476 return processor;
477 }
478
479 @Override
480 public int priority() {
481 return priority;
482 }
483
484 @Override
485 public long invocations() {
486 return invocations;
487 }
488
489 @Override
490 public long totalNanos() {
491 return nanos;
492 }
493
494 @Override
495 public long averageNanos() {
496 return invocations > 0 ? nanos / invocations : 0;
497 }
498
499 void addNanos(long nanos) {
500 this.nanos += nanos;
501 this.invocations++;
502 }
503 }
alshabibae857582014-09-12 23:53:10 -0700504}