blob: b7d1cd8a0c0b0084046c73c0082b3a15dc67f781 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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;
Yi Tseng809b5d72017-08-16 14:00:37 -070035import org.onosproject.net.driver.Driver;
36import org.onosproject.net.driver.DriverService;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080037import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080038import org.onosproject.net.flow.TrafficSelector;
Charles Chan874900e2016-12-09 16:55:39 -080039import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart17d00452015-04-21 17:10:00 -070040import org.onosproject.net.flowobjective.DefaultForwardingObjective;
41import org.onosproject.net.flowobjective.FlowObjectiveService;
42import org.onosproject.net.flowobjective.ForwardingObjective;
43import org.onosproject.net.flowobjective.Objective;
44import org.onosproject.net.flowobjective.ObjectiveContext;
45import org.onosproject.net.flowobjective.ObjectiveError;
alshabib42947782015-03-31 14:59:06 -070046import org.onosproject.net.packet.DefaultPacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080047import org.onosproject.net.packet.OutboundPacket;
48import org.onosproject.net.packet.PacketContext;
49import org.onosproject.net.packet.PacketEvent;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080050import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080051import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska924cda42015-09-22 12:11:27 -070052import org.onosproject.net.packet.PacketProcessorEntry;
Brian O'Connorabafb502014-12-02 22:26:20 -080053import org.onosproject.net.packet.PacketProvider;
54import org.onosproject.net.packet.PacketProviderRegistry;
55import org.onosproject.net.packet.PacketProviderService;
alshabib42947782015-03-31 14:59:06 -070056import org.onosproject.net.packet.PacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080057import org.onosproject.net.packet.PacketService;
58import org.onosproject.net.packet.PacketStore;
59import org.onosproject.net.packet.PacketStoreDelegate;
60import org.onosproject.net.provider.AbstractProviderRegistry;
61import org.onosproject.net.provider.AbstractProviderService;
alshabib7674db42014-09-12 23:40:46 -070062import org.slf4j.Logger;
63
Thomas Vachuska7f171b22015-08-21 12:49:08 -070064import java.util.List;
alshabib19e2cea2015-12-07 11:31:49 -080065import java.util.Optional;
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";
Yi Tseng809b5d72017-08-16 14:00:37 -070092 private static final String SUPPORT_PACKET_REQUEST_PROPERTY = "supportPacketRequest";
Thomas Vachuska27bee092015-06-23 19:03:10 -070093
Jonathan Hart4f60f982014-10-27 08:11:17 -070094 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
95
alshabib7674db42014-09-12 23:40:46 -070096 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -080097 protected CoreService coreService;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070098
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800100 protected ClusterService clusterService;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800103 protected DeviceService deviceService;
alshabib7674db42014-09-12 23:40:46 -0700104
Jonathan Hart4f60f982014-10-27 08:11:17 -0700105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Yi Tseng809b5d72017-08-16 14:00:37 -0700106 protected DriverService driverService;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800109 protected PacketStore store;
Jonathan Hart4f60f982014-10-27 08:11:17 -0700110
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hartdbaed992016-09-08 22:04:33 -0700112 protected FlowObjectiveService objectiveService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700113
Madan Jampanic626f1e2015-05-29 13:53:38 -0700114 private ExecutorService eventHandlingExecutor;
115
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800116 private final DeviceListener deviceListener = new InternalDeviceListener();
117
Thomas Vachuska924cda42015-09-22 12:11:27 -0700118 private final List<ProcessorEntry> processors = Lists.newCopyOnWriteArrayList();
alshabib7674db42014-09-12 23:40:46 -0700119
Thomas Vachuska42676812017-10-03 15:12:41 -0700120 private final PacketDriverProvider defaultProvider = new PacketDriverProvider();
Andrea Campanella5b240532016-02-05 09:44:41 -0800121
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700122 private ApplicationId appId;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800123 private NodeId localNodeId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700124
alshabib7674db42014-09-12 23:40:46 -0700125 @Activate
126 public void activate() {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700127 eventHandlingExecutor = Executors.newSingleThreadExecutor(
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700128 groupedThreads("onos/net/packet", "event-handler", log));
Madan Jampani6f8b7022015-12-07 16:59:59 -0800129 localNodeId = clusterService.getLocalNode().id();
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700130 appId = coreService.getAppId(CoreService.CORE_APP_NAME);
Jonathan Hart4f60f982014-10-27 08:11:17 -0700131 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800132 deviceService.addListener(deviceListener);
Andrea Campanella5b240532016-02-05 09:44:41 -0800133 defaultProvider.init(deviceService);
Charles Chanaa7e9732018-04-06 17:03:23 -0700134 store.existingRequests().forEach(request -> {
135 if (request.deviceId().isPresent()) {
136 Device device = deviceService.getDevice(request.deviceId().get());
137 if (device != null) {
138 pushRule(device, request);
139 } else {
140 log.info("Device is not ready yet. Skip processing packet requests {}", request);
141 }
142 } else {
143 pushToAllDevices(request);
144 }
145 });
alshabib7674db42014-09-12 23:40:46 -0700146 log.info("Started");
147 }
148
149 @Deactivate
150 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700151 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800152 deviceService.removeListener(deviceListener);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700153 eventHandlingExecutor.shutdown();
alshabib7674db42014-09-12 23:40:46 -0700154 log.info("Stopped");
155 }
156
157 @Override
Andrea Campanella5b240532016-02-05 09:44:41 -0800158 protected PacketProvider defaultProvider() {
159 return defaultProvider;
160 }
161
162 @Override
alshabib7674db42014-09-12 23:40:46 -0700163 public void addProcessor(PacketProcessor processor, int priority) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900164 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700165 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700166 ProcessorEntry entry = new ProcessorEntry(processor, priority);
167
168 // Insert the new processor according to its priority.
169 int i = 0;
170 for (; i < processors.size(); i++) {
171 if (priority < processors.get(i).priority()) {
172 break;
173 }
174 }
175 processors.add(i, entry);
alshabib7674db42014-09-12 23:40:46 -0700176 }
177
178 @Override
179 public void removeProcessor(PacketProcessor processor) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900180 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700181 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700182
183 // Remove the processor entry.
184 for (int i = 0; i < processors.size(); i++) {
185 if (processors.get(i).processor() == processor) {
186 processors.remove(i);
187 break;
188 }
189 }
alshabib7674db42014-09-12 23:40:46 -0700190 }
191
192 @Override
Thomas Vachuska924cda42015-09-22 12:11:27 -0700193 public List<PacketProcessorEntry> getProcessors() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900194 checkPermission(PACKET_READ);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700195 return ImmutableList.copyOf(processors);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700196 }
197
198 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800199 public void requestPackets(TrafficSelector selector, PacketPriority priority,
200 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900201 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700202 checkNotNull(selector, ERROR_NULL_SELECTOR);
203 checkNotNull(appId, ERROR_NULL_APP_ID);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800204
alshabib19e2cea2015-12-07 11:31:49 -0800205 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000206 localNodeId, Optional.empty());
Brian O'Connor21b028e2015-10-08 22:50:02 -0700207 store.requestPackets(request);
Saurav Dasc313c402015-02-27 10:09:47 -0800208 }
209
210 @Override
alshabib19e2cea2015-12-07 11:31:49 -0800211 public void requestPackets(TrafficSelector selector, PacketPriority priority,
212 ApplicationId appId, Optional<DeviceId> deviceId) {
213 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700214 checkNotNull(selector, ERROR_NULL_SELECTOR);
215 checkNotNull(appId, ERROR_NULL_APP_ID);
216 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800217
218 PacketRequest request =
219 new DefaultPacketRequest(selector, priority, appId,
220 localNodeId, deviceId);
221
222 store.requestPackets(request);
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000223
alshabib19e2cea2015-12-07 11:31:49 -0800224 }
225
226 @Override
Thomas Vachuska27bee092015-06-23 19:03:10 -0700227 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
228 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900229 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700230 checkNotNull(selector, ERROR_NULL_SELECTOR);
231 checkNotNull(appId, ERROR_NULL_APP_ID);
Saurav Dasc313c402015-02-27 10:09:47 -0800232
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000233
alshabib19e2cea2015-12-07 11:31:49 -0800234 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000235 localNodeId, Optional.empty());
alshabib19e2cea2015-12-07 11:31:49 -0800236 store.cancelPackets(request);
237 }
238
239 @Override
240 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
241 ApplicationId appId, Optional<DeviceId> deviceId) {
242 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700243 checkNotNull(selector, ERROR_NULL_SELECTOR);
244 checkNotNull(appId, ERROR_NULL_APP_ID);
245 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800246
247 PacketRequest request = new DefaultPacketRequest(selector, priority,
248 appId, localNodeId,
249 deviceId);
Brian O'Connor21b028e2015-10-08 22:50:02 -0700250 store.cancelPackets(request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800251 }
252
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700253 @Override
254 public List<PacketRequest> getRequests() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900255 checkPermission(PACKET_READ);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700256 return store.existingRequests();
257 }
258
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800259 /**
Thomas Vachuska924cda42015-09-22 12:11:27 -0700260 * Pushes all rules to the specified device.
261 *
262 * @param device device on which to install packet request flows
263 */
264 private void pushRulesToDevice(Device device) {
265 log.debug("Pushing packet requests to device {}", device.id());
266 for (PacketRequest request : store.existingRequests()) {
alshabib19e2cea2015-12-07 11:31:49 -0800267 if (!request.deviceId().isPresent()) {
268 pushRule(device, request);
269 } else if (request.deviceId().get().equals(device.id())) {
270 pushRule(device, request);
271 }
272
Thomas Vachuska924cda42015-09-22 12:11:27 -0700273 }
274 }
275
276 /**
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800277 * Pushes a packet request flow rule to all devices.
278 *
279 * @param request the packet request
280 */
281 private void pushToAllDevices(PacketRequest request) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700282 log.debug("Pushing packet request {} to all devices", request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800283 for (Device device : deviceService.getDevices()) {
Yi Tseng809b5d72017-08-16 14:00:37 -0700284 Driver driver = driverService.getDriver(device.id());
285 if (driver != null &&
286 Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -0700287 pushRule(device, request);
288 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800289 }
290 }
291
292 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700293 * Removes packet request flow rule from all devices.
294 *
295 * @param request the packet request
296 */
297 private void removeFromAllDevices(PacketRequest request) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700298 deviceService.getAvailableDevices().forEach(d -> removeRule(d, request));
Thomas Vachuska27bee092015-06-23 19:03:10 -0700299 }
300
301 /**
302 * Pushes packet intercept flow rules to the device.
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800303 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700304 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800305 * @param request the packet request
306 */
307 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700308 if (!device.type().equals(Device.Type.SWITCH)) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800309 return;
310 }
311
Carmelo Cascone0761cd32018-08-29 19:22:50 -0700312 if (!deviceService.isAvailable(device.id())) {
313 return;
314 }
315
Thomas Vachuska27bee092015-06-23 19:03:10 -0700316 ForwardingObjective forwarding = createBuilder(request)
Jonathan Hart17d00452015-04-21 17:10:00 -0700317 .add(new ObjectiveContext() {
318 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700319 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700320 log.warn("Failed to install packet request {} to {}: {}",
321 request, device.id(), error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700322 }
323 });
324
325 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800326 }
327
Thomas Vachuska27bee092015-06-23 19:03:10 -0700328 /**
329 * Removes packet intercept flow rules from the device.
330 *
331 * @param device the device to remove the rules deom
332 * @param request the packet request
333 */
334 private void removeRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700335 if (!device.type().equals(Device.Type.SWITCH)) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700336 return;
337 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700338 ForwardingObjective forwarding = createBuilder(request)
339 .remove(new ObjectiveContext() {
340 @Override
341 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700342 log.warn("Failed to withdraw packet request {} from {}: {}",
343 request, device.id(), error);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700344 }
345 });
Thomas Vachuska27bee092015-06-23 19:03:10 -0700346 objectiveService.forward(device.id(), forwarding);
347 }
348
349 private DefaultForwardingObjective.Builder createBuilder(PacketRequest request) {
DongRyeol Chace65cc02018-07-23 15:02:28 +0900350 ApplicationId requestedAppId = coreService.getAppId(request.appId().name()); // Validate app id
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000351 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
352 .punt()
353 .wipeDeferred()
354 .build();
Charles Chan874900e2016-12-09 16:55:39 -0800355
Thomas Vachuska27bee092015-06-23 19:03:10 -0700356 return DefaultForwardingObjective.builder()
357 .withPriority(request.priority().priorityValue())
358 .withSelector(request.selector())
DongRyeol Chace65cc02018-07-23 15:02:28 +0900359 .fromApp(requestedAppId == null ? appId : requestedAppId)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700360 .withFlag(ForwardingObjective.Flag.VERSATILE)
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000361 .withTreatment(treatment)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700362 .makePermanent();
363 }
364
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800365 @Override
alshabib7674db42014-09-12 23:40:46 -0700366 public void emit(OutboundPacket packet) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900367 checkPermission(PACKET_WRITE);
tomc370ebd2014-09-16 01:25:21 -0700368 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700369 store.emit(packet);
370 }
371
372 private void localEmit(OutboundPacket packet) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700373 Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800374 if (device == null) {
375 return;
376 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700377 PacketProvider packetProvider = getProvider(device.providerId());
alshabib3d643ec2014-10-22 18:33:00 -0700378 if (packetProvider != null) {
379 packetProvider.emit(packet);
380 }
alshabib7674db42014-09-12 23:40:46 -0700381 }
382
383 @Override
tomc370ebd2014-09-16 01:25:21 -0700384 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700385 return new InternalPacketProviderService(provider);
386 }
387
Thomas Vachuska924cda42015-09-22 12:11:27 -0700388 /**
389 * Personalized packet provider service issued to the supplied provider.
390 */
alshabib7674db42014-09-12 23:40:46 -0700391 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700392 extends AbstractProviderService<PacketProvider>
393 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700394
395 protected InternalPacketProviderService(PacketProvider provider) {
396 super(provider);
397 }
398
399 @Override
400 public void processPacket(PacketContext context) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800401 // TODO filter packets sent to processors based on registrations
Thomas Vachuska924cda42015-09-22 12:11:27 -0700402 for (ProcessorEntry entry : processors) {
Jonathan Hartf5638302015-11-16 10:56:20 -0800403 try {
Jonathan Hart34a14f72018-01-25 09:34:33 -0800404 if (log.isTraceEnabled()) {
405 log.trace("Starting packet processing by {}",
406 entry.processor().getClass().getName());
407 }
408
Jonathan Hartf5638302015-11-16 10:56:20 -0800409 long start = System.nanoTime();
410 entry.processor().process(context);
411 entry.addNanos(System.nanoTime() - start);
Jonathan Hart34a14f72018-01-25 09:34:33 -0800412
413 if (log.isTraceEnabled()) {
414 log.trace("Finished packet processing by {}",
415 entry.processor().getClass().getName());
416 }
Jonathan Hartf5638302015-11-16 10:56:20 -0800417 } catch (Exception e) {
418 log.warn("Packet processor {} threw an exception", entry.processor(), e);
419 }
alshabib7674db42014-09-12 23:40:46 -0700420 }
421 }
422
423 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700424
alshabib19e2cea2015-12-07 11:31:49 -0800425
Jonathan Hart4f60f982014-10-27 08:11:17 -0700426 /**
427 * Internal callback from the packet store.
428 */
Andrea Campanella5b240532016-02-05 09:44:41 -0800429 protected class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700430 @Override
431 public void notify(PacketEvent event) {
432 localEmit(event.subject());
433 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700434
435 @Override
436 public void requestPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800437 DeviceId deviceid = request.deviceId().orElse(null);
438
439 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900440 Device device = deviceService.getDevice(deviceid);
441
442 if (device != null) {
443 pushRule(deviceService.getDevice(deviceid), request);
444 }
alshabib19e2cea2015-12-07 11:31:49 -0800445 } else {
446 pushToAllDevices(request);
447 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700448 }
449
450 @Override
451 public void cancelPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800452 DeviceId deviceid = request.deviceId().orElse(null);
453
454 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900455 Device device = deviceService.getDevice(deviceid);
456
457 if (device != null) {
458 removeRule(deviceService.getDevice(deviceid), request);
459 }
alshabib19e2cea2015-12-07 11:31:49 -0800460 } else {
461 removeFromAllDevices(request);
462 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700463 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700464 }
465
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800466 /**
467 * Internal listener for device service events.
468 */
469 private class InternalDeviceListener implements DeviceListener {
Thomas Vachuska42676812017-10-03 15:12:41 -0700470
471 @Override
472 public boolean isRelevant(DeviceEvent event) {
473 return event.type() == DeviceEvent.Type.DEVICE_ADDED ||
474 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
475 }
476
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800477 @Override
478 public void event(DeviceEvent event) {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700479 eventHandlingExecutor.execute(() -> {
480 try {
Ray Milkeyfa89f2a2017-11-30 13:52:54 -0800481 if (driverService == null) {
482 // Event came in after the driver service shut down, nothing to be done
483 return;
484 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700485 Device device = event.subject();
Yi Tseng809b5d72017-08-16 14:00:37 -0700486 Driver driver = driverService.getDriver(device.id());
487 if (driver == null) {
488 return;
489 }
490 if (!Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
491 return;
492 }
493 if (!deviceService.isAvailable(event.subject().id())) {
494 return;
495 }
Thomas Vachuska42676812017-10-03 15:12:41 -0700496 pushRulesToDevice(device);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700497 } catch (Exception e) {
498 log.warn("Failed to process {}", event, e);
499 }
500 });
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800501 }
502 }
503
Thomas Vachuska924cda42015-09-22 12:11:27 -0700504 /**
505 * Entity for tracking stats for a packet processor.
506 */
507 private class ProcessorEntry implements PacketProcessorEntry {
508 private final PacketProcessor processor;
509 private final int priority;
510 private long invocations = 0;
511 private long nanos = 0;
512
513 public ProcessorEntry(PacketProcessor processor, int priority) {
514 this.processor = processor;
515 this.priority = priority;
516 }
517
518 @Override
519 public PacketProcessor processor() {
520 return processor;
521 }
522
523 @Override
524 public int priority() {
525 return priority;
526 }
527
528 @Override
529 public long invocations() {
530 return invocations;
531 }
532
533 @Override
534 public long totalNanos() {
535 return nanos;
536 }
537
538 @Override
539 public long averageNanos() {
540 return invocations > 0 ? nanos / invocations : 0;
541 }
542
543 void addNanos(long nanos) {
544 this.nanos += nanos;
545 this.invocations++;
546 }
547 }
alshabibae857582014-09-12 23:53:10 -0700548}