blob: 4e5c20d29354c06c7a5cb5b562b5a22e59befaa8 [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;
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -070019import com.google.common.collect.ImmutableSet;
Thomas Vachuska924cda42015-09-22 12:11:27 -070020import com.google.common.collect.Lists;
alshabib7674db42014-09-12 23:40:46 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
Madan Jampani6f8b7022015-12-07 16:59:59 -080027import org.onosproject.cluster.ClusterService;
28import org.onosproject.cluster.NodeId;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080029import org.onosproject.core.ApplicationId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070030import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.Device;
alshabib19e2cea2015-12-07 11:31:49 -080032import org.onosproject.net.DeviceId;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080033import org.onosproject.net.device.DeviceEvent;
34import org.onosproject.net.device.DeviceListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.device.DeviceService;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080036import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080037import org.onosproject.net.flow.TrafficSelector;
Charles Chan874900e2016-12-09 16:55:39 -080038import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart17d00452015-04-21 17:10:00 -070039import org.onosproject.net.flowobjective.DefaultForwardingObjective;
40import org.onosproject.net.flowobjective.FlowObjectiveService;
41import org.onosproject.net.flowobjective.ForwardingObjective;
42import org.onosproject.net.flowobjective.Objective;
43import org.onosproject.net.flowobjective.ObjectiveContext;
44import org.onosproject.net.flowobjective.ObjectiveError;
alshabib42947782015-03-31 14:59:06 -070045import org.onosproject.net.packet.DefaultPacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080046import org.onosproject.net.packet.OutboundPacket;
47import org.onosproject.net.packet.PacketContext;
48import org.onosproject.net.packet.PacketEvent;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080049import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080050import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska924cda42015-09-22 12:11:27 -070051import org.onosproject.net.packet.PacketProcessorEntry;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.packet.PacketProvider;
53import org.onosproject.net.packet.PacketProviderRegistry;
54import org.onosproject.net.packet.PacketProviderService;
alshabib42947782015-03-31 14:59:06 -070055import org.onosproject.net.packet.PacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080056import org.onosproject.net.packet.PacketService;
57import org.onosproject.net.packet.PacketStore;
58import org.onosproject.net.packet.PacketStoreDelegate;
59import org.onosproject.net.provider.AbstractProviderRegistry;
60import org.onosproject.net.provider.AbstractProviderService;
alshabib7674db42014-09-12 23:40:46 -070061import org.slf4j.Logger;
62
Thomas Vachuska7f171b22015-08-21 12:49:08 -070063import java.util.List;
alshabib19e2cea2015-12-07 11:31:49 -080064import java.util.Optional;
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -070065import java.util.Set;
Madan Jampanic626f1e2015-05-29 13:53:38 -070066import java.util.concurrent.ExecutorService;
67import java.util.concurrent.Executors;
alshabib089bb772015-03-03 18:26:26 -080068
69import static com.google.common.base.Preconditions.checkNotNull;
Madan Jampanic626f1e2015-05-29 13:53:38 -070070import static org.onlab.util.Tools.groupedThreads;
Changhoon Yoon541ef712015-05-23 17:18:34 +090071import static org.onosproject.security.AppGuard.checkPermission;
Jonathan Hartdbaed992016-09-08 22:04:33 -070072import static org.onosproject.security.AppPermission.Type.PACKET_EVENT;
73import static org.onosproject.security.AppPermission.Type.PACKET_READ;
74import static org.onosproject.security.AppPermission.Type.PACKET_WRITE;
Thomas Vachuska7f171b22015-08-21 12:49:08 -070075import static org.slf4j.LoggerFactory.getLogger;
alshabib089bb772015-03-03 18:26:26 -080076
alshabib7674db42014-09-12 23:40:46 -070077/**
78 * Provides a basic implementation of the packet SB & NB APIs.
alshabib7674db42014-09-12 23:40:46 -070079 */
80@Component(immediate = true)
81@Service
tom202175a2014-09-19 19:00:11 -070082public class PacketManager
Thomas Vachuska6cba4952015-04-22 12:38:22 -070083 extends AbstractProviderRegistry<PacketProvider, PacketProviderService>
84 implements PacketService, PacketProviderRegistry {
alshabib7674db42014-09-12 23:40:46 -070085
86 private final Logger log = getLogger(getClass());
87
Jonathan Hartdbaed992016-09-08 22:04:33 -070088 private static final String ERROR_NULL_PROCESSOR = "Processor cannot be null";
89 private static final String ERROR_NULL_SELECTOR = "Selector cannot be null";
90 private static final String ERROR_NULL_APP_ID = "Application ID cannot be null";
91 private static final String ERROR_NULL_DEVICE_ID = "Device ID cannot be null";
Thomas Vachuska27bee092015-06-23 19:03:10 -070092
Jonathan Hart4f60f982014-10-27 08:11:17 -070093 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
94
alshabib7674db42014-09-12 23:40:46 -070095 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -080096 protected CoreService coreService;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070097
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -080099 protected ClusterService clusterService;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800102 protected DeviceService deviceService;
alshabib7674db42014-09-12 23:40:46 -0700103
Jonathan Hart4f60f982014-10-27 08:11:17 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800105 protected PacketStore store;
Jonathan Hart4f60f982014-10-27 08:11:17 -0700106
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hartdbaed992016-09-08 22:04:33 -0700108 protected FlowObjectiveService objectiveService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700109
Madan Jampanic626f1e2015-05-29 13:53:38 -0700110 private ExecutorService eventHandlingExecutor;
111
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800112 private final DeviceListener deviceListener = new InternalDeviceListener();
113
Thomas Vachuska924cda42015-09-22 12:11:27 -0700114 private final List<ProcessorEntry> processors = Lists.newCopyOnWriteArrayList();
alshabib7674db42014-09-12 23:40:46 -0700115
Andrea Campanella5b240532016-02-05 09:44:41 -0800116 private final PacketDriverProvider defaultProvider = new PacketDriverProvider();
117
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700118 private ApplicationId appId;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800119 private NodeId localNodeId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700120
alshabib7674db42014-09-12 23:40:46 -0700121 @Activate
122 public void activate() {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700123 eventHandlingExecutor = Executors.newSingleThreadExecutor(
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700124 groupedThreads("onos/net/packet", "event-handler", log));
Madan Jampani6f8b7022015-12-07 16:59:59 -0800125 localNodeId = clusterService.getLocalNode().id();
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700126 appId = coreService.getAppId(CoreService.CORE_APP_NAME);
Jonathan Hart4f60f982014-10-27 08:11:17 -0700127 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800128 deviceService.addListener(deviceListener);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700129 store.existingRequests().forEach(this::pushToAllDevices);
Andrea Campanella5b240532016-02-05 09:44:41 -0800130 defaultProvider.init(deviceService);
alshabib7674db42014-09-12 23:40:46 -0700131 log.info("Started");
132 }
133
134 @Deactivate
135 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700136 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800137 deviceService.removeListener(deviceListener);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700138 eventHandlingExecutor.shutdown();
alshabib7674db42014-09-12 23:40:46 -0700139 log.info("Stopped");
140 }
141
142 @Override
Andrea Campanella5b240532016-02-05 09:44:41 -0800143 protected PacketProvider defaultProvider() {
144 return defaultProvider;
145 }
146
147 @Override
alshabib7674db42014-09-12 23:40:46 -0700148 public void addProcessor(PacketProcessor processor, int priority) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900149 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700150 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700151 ProcessorEntry entry = new ProcessorEntry(processor, priority);
152
153 // Insert the new processor according to its priority.
154 int i = 0;
155 for (; i < processors.size(); i++) {
156 if (priority < processors.get(i).priority()) {
157 break;
158 }
159 }
160 processors.add(i, entry);
alshabib7674db42014-09-12 23:40:46 -0700161 }
162
163 @Override
164 public void removeProcessor(PacketProcessor processor) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900165 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700166 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700167
168 // Remove the processor entry.
169 for (int i = 0; i < processors.size(); i++) {
170 if (processors.get(i).processor() == processor) {
171 processors.remove(i);
172 break;
173 }
174 }
alshabib7674db42014-09-12 23:40:46 -0700175 }
176
177 @Override
Thomas Vachuska924cda42015-09-22 12:11:27 -0700178 public List<PacketProcessorEntry> getProcessors() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900179 checkPermission(PACKET_READ);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700180 return ImmutableList.copyOf(processors);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700181 }
182
183 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800184 public void requestPackets(TrafficSelector selector, PacketPriority priority,
185 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900186 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700187 checkNotNull(selector, ERROR_NULL_SELECTOR);
188 checkNotNull(appId, ERROR_NULL_APP_ID);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800189
alshabib19e2cea2015-12-07 11:31:49 -0800190 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000191 localNodeId, Optional.empty());
Brian O'Connor21b028e2015-10-08 22:50:02 -0700192 store.requestPackets(request);
Saurav Dasc313c402015-02-27 10:09:47 -0800193 }
194
195 @Override
alshabib19e2cea2015-12-07 11:31:49 -0800196 public void requestPackets(TrafficSelector selector, PacketPriority priority,
197 ApplicationId appId, Optional<DeviceId> deviceId) {
198 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700199 checkNotNull(selector, ERROR_NULL_SELECTOR);
200 checkNotNull(appId, ERROR_NULL_APP_ID);
201 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800202
203 PacketRequest request =
204 new DefaultPacketRequest(selector, priority, appId,
205 localNodeId, deviceId);
206
207 store.requestPackets(request);
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000208
alshabib19e2cea2015-12-07 11:31:49 -0800209 }
210
211 @Override
Thomas Vachuska27bee092015-06-23 19:03:10 -0700212 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
213 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900214 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700215 checkNotNull(selector, ERROR_NULL_SELECTOR);
216 checkNotNull(appId, ERROR_NULL_APP_ID);
Saurav Dasc313c402015-02-27 10:09:47 -0800217
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000218
alshabib19e2cea2015-12-07 11:31:49 -0800219 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000220 localNodeId, Optional.empty());
alshabib19e2cea2015-12-07 11:31:49 -0800221 store.cancelPackets(request);
222 }
223
224 @Override
225 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
226 ApplicationId appId, Optional<DeviceId> deviceId) {
227 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700228 checkNotNull(selector, ERROR_NULL_SELECTOR);
229 checkNotNull(appId, ERROR_NULL_APP_ID);
230 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800231
232 PacketRequest request = new DefaultPacketRequest(selector, priority,
233 appId, localNodeId,
234 deviceId);
Brian O'Connor21b028e2015-10-08 22:50:02 -0700235 store.cancelPackets(request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800236 }
237
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700238 @Override
239 public List<PacketRequest> getRequests() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900240 checkPermission(PACKET_READ);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700241 return store.existingRequests();
242 }
243
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800244 /**
Thomas Vachuska924cda42015-09-22 12:11:27 -0700245 * Pushes all rules to the specified device.
246 *
247 * @param device device on which to install packet request flows
248 */
249 private void pushRulesToDevice(Device device) {
250 log.debug("Pushing packet requests to device {}", device.id());
251 for (PacketRequest request : store.existingRequests()) {
alshabib19e2cea2015-12-07 11:31:49 -0800252 if (!request.deviceId().isPresent()) {
253 pushRule(device, request);
254 } else if (request.deviceId().get().equals(device.id())) {
255 pushRule(device, request);
256 }
257
Thomas Vachuska924cda42015-09-22 12:11:27 -0700258 }
259 }
260
261 /**
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -0700262 * Set of DeviceId scheme which supports packet requests.
263 */
264 private static final Set<String> SUPPORTED = ImmutableSet.of("of");
265
266 /**
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800267 * Pushes a packet request flow rule to all devices.
268 *
269 * @param request the packet request
270 */
271 private void pushToAllDevices(PacketRequest request) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700272 log.debug("Pushing packet request {} to all devices", request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800273 for (Device device : deviceService.getDevices()) {
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -0700274 // TODO properly test capability via driver, defining behaviour
275 if (SUPPORTED.contains(device.id().uri().getScheme())) {
276 pushRule(device, request);
277 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800278 }
279 }
280
281 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700282 * Removes packet request flow rule from all devices.
283 *
284 * @param request the packet request
285 */
286 private void removeFromAllDevices(PacketRequest request) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700287 deviceService.getAvailableDevices().forEach(d -> removeRule(d, request));
Thomas Vachuska27bee092015-06-23 19:03:10 -0700288 }
289
290 /**
291 * Pushes packet intercept flow rules to the device.
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800292 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700293 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800294 * @param request the packet request
295 */
296 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700297 if (!device.type().equals(Device.Type.SWITCH)) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800298 return;
299 }
300
Thomas Vachuska27bee092015-06-23 19:03:10 -0700301 ForwardingObjective forwarding = createBuilder(request)
Jonathan Hart17d00452015-04-21 17:10:00 -0700302 .add(new ObjectiveContext() {
303 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700304 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700305 log.warn("Failed to install packet request {} to {}: {}",
306 request, device.id(), error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700307 }
308 });
309
310 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800311 }
312
Thomas Vachuska27bee092015-06-23 19:03:10 -0700313 /**
314 * Removes packet intercept flow rules from the device.
315 *
316 * @param device the device to remove the rules deom
317 * @param request the packet request
318 */
319 private void removeRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700320 if (!device.type().equals(Device.Type.SWITCH)) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700321 return;
322 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700323 ForwardingObjective forwarding = createBuilder(request)
324 .remove(new ObjectiveContext() {
325 @Override
326 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700327 log.warn("Failed to withdraw packet request {} from {}: {}",
328 request, device.id(), error);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700329 }
330 });
Thomas Vachuska27bee092015-06-23 19:03:10 -0700331 objectiveService.forward(device.id(), forwarding);
332 }
333
334 private DefaultForwardingObjective.Builder createBuilder(PacketRequest request) {
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000335 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
336 .punt()
337 .wipeDeferred()
338 .build();
Charles Chan874900e2016-12-09 16:55:39 -0800339
Thomas Vachuska27bee092015-06-23 19:03:10 -0700340 return DefaultForwardingObjective.builder()
341 .withPriority(request.priority().priorityValue())
342 .withSelector(request.selector())
343 .fromApp(appId)
344 .withFlag(ForwardingObjective.Flag.VERSATILE)
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000345 .withTreatment(treatment)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700346 .makePermanent();
347 }
348
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800349 @Override
alshabib7674db42014-09-12 23:40:46 -0700350 public void emit(OutboundPacket packet) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900351 checkPermission(PACKET_WRITE);
tomc370ebd2014-09-16 01:25:21 -0700352 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700353 store.emit(packet);
354 }
355
356 private void localEmit(OutboundPacket packet) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700357 Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800358 if (device == null) {
359 return;
360 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700361 PacketProvider packetProvider = getProvider(device.providerId());
alshabib3d643ec2014-10-22 18:33:00 -0700362 if (packetProvider != null) {
363 packetProvider.emit(packet);
364 }
alshabib7674db42014-09-12 23:40:46 -0700365 }
366
367 @Override
tomc370ebd2014-09-16 01:25:21 -0700368 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700369 return new InternalPacketProviderService(provider);
370 }
371
Thomas Vachuska924cda42015-09-22 12:11:27 -0700372 /**
373 * Personalized packet provider service issued to the supplied provider.
374 */
alshabib7674db42014-09-12 23:40:46 -0700375 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700376 extends AbstractProviderService<PacketProvider>
377 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700378
379 protected InternalPacketProviderService(PacketProvider provider) {
380 super(provider);
381 }
382
383 @Override
384 public void processPacket(PacketContext context) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800385 // TODO filter packets sent to processors based on registrations
Thomas Vachuska924cda42015-09-22 12:11:27 -0700386 for (ProcessorEntry entry : processors) {
Jonathan Hartf5638302015-11-16 10:56:20 -0800387 try {
388 long start = System.nanoTime();
389 entry.processor().process(context);
390 entry.addNanos(System.nanoTime() - start);
391 } catch (Exception e) {
392 log.warn("Packet processor {} threw an exception", entry.processor(), e);
393 }
alshabib7674db42014-09-12 23:40:46 -0700394 }
395 }
396
397 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700398
alshabib19e2cea2015-12-07 11:31:49 -0800399
Jonathan Hart4f60f982014-10-27 08:11:17 -0700400 /**
401 * Internal callback from the packet store.
402 */
Andrea Campanella5b240532016-02-05 09:44:41 -0800403 protected class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700404 @Override
405 public void notify(PacketEvent event) {
406 localEmit(event.subject());
407 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700408
409 @Override
410 public void requestPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800411 DeviceId deviceid = request.deviceId().orElse(null);
412
413 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900414 Device device = deviceService.getDevice(deviceid);
415
416 if (device != null) {
417 pushRule(deviceService.getDevice(deviceid), request);
418 }
alshabib19e2cea2015-12-07 11:31:49 -0800419 } else {
420 pushToAllDevices(request);
421 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700422 }
423
424 @Override
425 public void cancelPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800426 DeviceId deviceid = request.deviceId().orElse(null);
427
428 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900429 Device device = deviceService.getDevice(deviceid);
430
431 if (device != null) {
432 removeRule(deviceService.getDevice(deviceid), request);
433 }
alshabib19e2cea2015-12-07 11:31:49 -0800434 } else {
435 removeFromAllDevices(request);
436 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700437 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700438 }
439
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800440 /**
441 * Internal listener for device service events.
442 */
443 private class InternalDeviceListener implements DeviceListener {
444 @Override
445 public void event(DeviceEvent event) {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700446 eventHandlingExecutor.execute(() -> {
447 try {
448 Device device = event.subject();
449 switch (event.type()) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700450 case DEVICE_ADDED:
451 case DEVICE_AVAILABILITY_CHANGED:
452 if (deviceService.isAvailable(event.subject().id())) {
453 pushRulesToDevice(device);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700454 }
Thomas Vachuska924cda42015-09-22 12:11:27 -0700455 break;
456 default:
457 break;
sangho864a9db22015-04-28 12:06:31 -0700458 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700459 } catch (Exception e) {
460 log.warn("Failed to process {}", event, e);
461 }
462 });
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800463 }
464 }
465
Thomas Vachuska924cda42015-09-22 12:11:27 -0700466 /**
467 * Entity for tracking stats for a packet processor.
468 */
469 private class ProcessorEntry implements PacketProcessorEntry {
470 private final PacketProcessor processor;
471 private final int priority;
472 private long invocations = 0;
473 private long nanos = 0;
474
475 public ProcessorEntry(PacketProcessor processor, int priority) {
476 this.processor = processor;
477 this.priority = priority;
478 }
479
480 @Override
481 public PacketProcessor processor() {
482 return processor;
483 }
484
485 @Override
486 public int priority() {
487 return priority;
488 }
489
490 @Override
491 public long invocations() {
492 return invocations;
493 }
494
495 @Override
496 public long totalNanos() {
497 return nanos;
498 }
499
500 @Override
501 public long averageNanos() {
502 return invocations > 0 ? nanos / invocations : 0;
503 }
504
505 void addNanos(long nanos) {
506 this.nanos += nanos;
507 this.invocations++;
508 }
509 }
alshabibae857582014-09-12 23:53:10 -0700510}