blob: ff63efecf4b5fcf25cac5ef51dbc571f163a7550 [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;
Madan Jampani6f8b7022015-12-07 16:59:59 -080020import org.onosproject.cluster.ClusterService;
21import org.onosproject.cluster.NodeId;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080022import org.onosproject.core.ApplicationId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070023import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080024import org.onosproject.net.Device;
alshabib19e2cea2015-12-07 11:31:49 -080025import org.onosproject.net.DeviceId;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080026import org.onosproject.net.device.DeviceEvent;
27import org.onosproject.net.device.DeviceListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.net.device.DeviceService;
Yi Tseng809b5d72017-08-16 14:00:37 -070029import org.onosproject.net.driver.Driver;
30import org.onosproject.net.driver.DriverService;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080031import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080032import org.onosproject.net.flow.TrafficSelector;
Charles Chan874900e2016-12-09 16:55:39 -080033import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart17d00452015-04-21 17:10:00 -070034import org.onosproject.net.flowobjective.DefaultForwardingObjective;
35import org.onosproject.net.flowobjective.FlowObjectiveService;
36import org.onosproject.net.flowobjective.ForwardingObjective;
37import org.onosproject.net.flowobjective.Objective;
38import org.onosproject.net.flowobjective.ObjectiveContext;
39import org.onosproject.net.flowobjective.ObjectiveError;
alshabib42947782015-03-31 14:59:06 -070040import org.onosproject.net.packet.DefaultPacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.packet.OutboundPacket;
42import org.onosproject.net.packet.PacketContext;
43import org.onosproject.net.packet.PacketEvent;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080044import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080045import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska924cda42015-09-22 12:11:27 -070046import org.onosproject.net.packet.PacketProcessorEntry;
Brian O'Connorabafb502014-12-02 22:26:20 -080047import org.onosproject.net.packet.PacketProvider;
48import org.onosproject.net.packet.PacketProviderRegistry;
49import org.onosproject.net.packet.PacketProviderService;
alshabib42947782015-03-31 14:59:06 -070050import org.onosproject.net.packet.PacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080051import org.onosproject.net.packet.PacketService;
52import org.onosproject.net.packet.PacketStore;
53import org.onosproject.net.packet.PacketStoreDelegate;
54import org.onosproject.net.provider.AbstractProviderRegistry;
55import org.onosproject.net.provider.AbstractProviderService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070056import org.osgi.service.component.annotations.Activate;
57import org.osgi.service.component.annotations.Component;
58import org.osgi.service.component.annotations.Deactivate;
59import org.osgi.service.component.annotations.Reference;
60import org.osgi.service.component.annotations.ReferenceCardinality;
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;
Madan Jampanic626f1e2015-05-29 13:53:38 -070065import java.util.concurrent.ExecutorService;
66import java.util.concurrent.Executors;
alshabib089bb772015-03-03 18:26:26 -080067
68import static com.google.common.base.Preconditions.checkNotNull;
Madan Jampanic626f1e2015-05-29 13:53:38 -070069import static org.onlab.util.Tools.groupedThreads;
Changhoon Yoon541ef712015-05-23 17:18:34 +090070import static org.onosproject.security.AppGuard.checkPermission;
Jonathan Hartdbaed992016-09-08 22:04:33 -070071import static org.onosproject.security.AppPermission.Type.PACKET_EVENT;
72import static org.onosproject.security.AppPermission.Type.PACKET_READ;
73import static org.onosproject.security.AppPermission.Type.PACKET_WRITE;
Thomas Vachuska7f171b22015-08-21 12:49:08 -070074import static org.slf4j.LoggerFactory.getLogger;
alshabib089bb772015-03-03 18:26:26 -080075
alshabib7674db42014-09-12 23:40:46 -070076/**
77 * Provides a basic implementation of the packet SB & NB APIs.
alshabib7674db42014-09-12 23:40:46 -070078 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070079@Component(immediate = true, service = { PacketService.class, PacketProviderRegistry.class })
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";
Yi Tseng809b5d72017-08-16 14:00:37 -070090 private static final String SUPPORT_PACKET_REQUEST_PROPERTY = "supportPacketRequest";
Thomas Vachuska27bee092015-06-23 19:03:10 -070091
Jonathan Hart4f60f982014-10-27 08:11:17 -070092 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
93
Ray Milkeyd84f89b2018-08-17 14:54:17 -070094 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -080095 protected CoreService coreService;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070096
Ray Milkeyd84f89b2018-08-17 14:54:17 -070097 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -080098 protected ClusterService clusterService;
Madan Jampani6f8b7022015-12-07 16:59:59 -080099
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700100 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800101 protected DeviceService deviceService;
alshabib7674db42014-09-12 23:40:46 -0700102
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700103 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng809b5d72017-08-16 14:00:37 -0700104 protected DriverService driverService;
105
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700106 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800107 protected PacketStore store;
Jonathan Hart4f60f982014-10-27 08:11:17 -0700108
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700109 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hartdbaed992016-09-08 22:04:33 -0700110 protected FlowObjectiveService objectiveService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700111
Madan Jampanic626f1e2015-05-29 13:53:38 -0700112 private ExecutorService eventHandlingExecutor;
113
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800114 private final DeviceListener deviceListener = new InternalDeviceListener();
115
Thomas Vachuska924cda42015-09-22 12:11:27 -0700116 private final List<ProcessorEntry> processors = Lists.newCopyOnWriteArrayList();
alshabib7674db42014-09-12 23:40:46 -0700117
Thomas Vachuska42676812017-10-03 15:12:41 -0700118 private final PacketDriverProvider defaultProvider = new PacketDriverProvider();
Andrea Campanella5b240532016-02-05 09:44:41 -0800119
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700120 private ApplicationId appId;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800121 private NodeId localNodeId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700122
alshabib7674db42014-09-12 23:40:46 -0700123 @Activate
124 public void activate() {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700125 eventHandlingExecutor = Executors.newSingleThreadExecutor(
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700126 groupedThreads("onos/net/packet", "event-handler", log));
Madan Jampani6f8b7022015-12-07 16:59:59 -0800127 localNodeId = clusterService.getLocalNode().id();
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700128 appId = coreService.getAppId(CoreService.CORE_APP_NAME);
Jonathan Hart4f60f982014-10-27 08:11:17 -0700129 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800130 deviceService.addListener(deviceListener);
Andrea Campanella5b240532016-02-05 09:44:41 -0800131 defaultProvider.init(deviceService);
Charles Chanaa7e9732018-04-06 17:03:23 -0700132 store.existingRequests().forEach(request -> {
133 if (request.deviceId().isPresent()) {
134 Device device = deviceService.getDevice(request.deviceId().get());
135 if (device != null) {
136 pushRule(device, request);
137 } else {
138 log.info("Device is not ready yet. Skip processing packet requests {}", request);
139 }
140 } else {
141 pushToAllDevices(request);
142 }
143 });
alshabib7674db42014-09-12 23:40:46 -0700144 log.info("Started");
145 }
146
147 @Deactivate
148 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700149 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800150 deviceService.removeListener(deviceListener);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700151 eventHandlingExecutor.shutdown();
alshabib7674db42014-09-12 23:40:46 -0700152 log.info("Stopped");
153 }
154
155 @Override
Andrea Campanella5b240532016-02-05 09:44:41 -0800156 protected PacketProvider defaultProvider() {
157 return defaultProvider;
158 }
159
160 @Override
alshabib7674db42014-09-12 23:40:46 -0700161 public void addProcessor(PacketProcessor processor, int priority) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900162 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700163 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700164 ProcessorEntry entry = new ProcessorEntry(processor, priority);
165
166 // Insert the new processor according to its priority.
167 int i = 0;
168 for (; i < processors.size(); i++) {
169 if (priority < processors.get(i).priority()) {
170 break;
171 }
172 }
173 processors.add(i, entry);
alshabib7674db42014-09-12 23:40:46 -0700174 }
175
176 @Override
177 public void removeProcessor(PacketProcessor processor) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900178 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700179 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700180
181 // Remove the processor entry.
182 for (int i = 0; i < processors.size(); i++) {
183 if (processors.get(i).processor() == processor) {
184 processors.remove(i);
185 break;
186 }
187 }
alshabib7674db42014-09-12 23:40:46 -0700188 }
189
190 @Override
Thomas Vachuska924cda42015-09-22 12:11:27 -0700191 public List<PacketProcessorEntry> getProcessors() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900192 checkPermission(PACKET_READ);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700193 return ImmutableList.copyOf(processors);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700194 }
195
196 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800197 public void requestPackets(TrafficSelector selector, PacketPriority priority,
198 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900199 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700200 checkNotNull(selector, ERROR_NULL_SELECTOR);
201 checkNotNull(appId, ERROR_NULL_APP_ID);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800202
alshabib19e2cea2015-12-07 11:31:49 -0800203 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000204 localNodeId, Optional.empty());
Brian O'Connor21b028e2015-10-08 22:50:02 -0700205 store.requestPackets(request);
Saurav Dasc313c402015-02-27 10:09:47 -0800206 }
207
208 @Override
alshabib19e2cea2015-12-07 11:31:49 -0800209 public void requestPackets(TrafficSelector selector, PacketPriority priority,
210 ApplicationId appId, Optional<DeviceId> deviceId) {
211 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700212 checkNotNull(selector, ERROR_NULL_SELECTOR);
213 checkNotNull(appId, ERROR_NULL_APP_ID);
214 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800215
216 PacketRequest request =
217 new DefaultPacketRequest(selector, priority, appId,
218 localNodeId, deviceId);
219
220 store.requestPackets(request);
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000221
alshabib19e2cea2015-12-07 11:31:49 -0800222 }
223
224 @Override
Thomas Vachuska27bee092015-06-23 19:03:10 -0700225 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
226 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900227 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700228 checkNotNull(selector, ERROR_NULL_SELECTOR);
229 checkNotNull(appId, ERROR_NULL_APP_ID);
Saurav Dasc313c402015-02-27 10:09:47 -0800230
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000231
alshabib19e2cea2015-12-07 11:31:49 -0800232 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000233 localNodeId, Optional.empty());
alshabib19e2cea2015-12-07 11:31:49 -0800234 store.cancelPackets(request);
235 }
236
237 @Override
238 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
239 ApplicationId appId, Optional<DeviceId> deviceId) {
240 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700241 checkNotNull(selector, ERROR_NULL_SELECTOR);
242 checkNotNull(appId, ERROR_NULL_APP_ID);
243 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800244
245 PacketRequest request = new DefaultPacketRequest(selector, priority,
246 appId, localNodeId,
247 deviceId);
Brian O'Connor21b028e2015-10-08 22:50:02 -0700248 store.cancelPackets(request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800249 }
250
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700251 @Override
252 public List<PacketRequest> getRequests() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900253 checkPermission(PACKET_READ);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700254 return store.existingRequests();
255 }
256
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800257 /**
Thomas Vachuska924cda42015-09-22 12:11:27 -0700258 * Pushes all rules to the specified device.
259 *
260 * @param device device on which to install packet request flows
261 */
262 private void pushRulesToDevice(Device device) {
263 log.debug("Pushing packet requests to device {}", device.id());
264 for (PacketRequest request : store.existingRequests()) {
alshabib19e2cea2015-12-07 11:31:49 -0800265 if (!request.deviceId().isPresent()) {
266 pushRule(device, request);
267 } else if (request.deviceId().get().equals(device.id())) {
268 pushRule(device, request);
269 }
270
Thomas Vachuska924cda42015-09-22 12:11:27 -0700271 }
272 }
273
274 /**
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800275 * Pushes a packet request flow rule to all devices.
276 *
277 * @param request the packet request
278 */
279 private void pushToAllDevices(PacketRequest request) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700280 log.debug("Pushing packet request {} to all devices", request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800281 for (Device device : deviceService.getDevices()) {
Yi Tseng809b5d72017-08-16 14:00:37 -0700282 Driver driver = driverService.getDriver(device.id());
283 if (driver != null &&
284 Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -0700285 pushRule(device, request);
286 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800287 }
288 }
289
290 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700291 * Removes packet request flow rule from all devices.
292 *
293 * @param request the packet request
294 */
295 private void removeFromAllDevices(PacketRequest request) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700296 deviceService.getAvailableDevices().forEach(d -> removeRule(d, request));
Thomas Vachuska27bee092015-06-23 19:03:10 -0700297 }
298
299 /**
300 * Pushes packet intercept flow rules to the device.
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800301 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700302 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800303 * @param request the packet request
304 */
305 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700306 if (!device.type().equals(Device.Type.SWITCH)) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800307 return;
308 }
309
Carmelo Cascone0761cd32018-08-29 19:22:50 -0700310 if (!deviceService.isAvailable(device.id())) {
311 return;
312 }
313
Thomas Vachuska27bee092015-06-23 19:03:10 -0700314 ForwardingObjective forwarding = createBuilder(request)
Jonathan Hart17d00452015-04-21 17:10:00 -0700315 .add(new ObjectiveContext() {
316 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700317 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700318 log.warn("Failed to install packet request {} to {}: {}",
319 request, device.id(), error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700320 }
321 });
322
323 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800324 }
325
Thomas Vachuska27bee092015-06-23 19:03:10 -0700326 /**
327 * Removes packet intercept flow rules from the device.
328 *
329 * @param device the device to remove the rules deom
330 * @param request the packet request
331 */
332 private void removeRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700333 if (!device.type().equals(Device.Type.SWITCH)) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700334 return;
335 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700336 ForwardingObjective forwarding = createBuilder(request)
337 .remove(new ObjectiveContext() {
338 @Override
339 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700340 log.warn("Failed to withdraw packet request {} from {}: {}",
341 request, device.id(), error);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700342 }
343 });
Thomas Vachuska27bee092015-06-23 19:03:10 -0700344 objectiveService.forward(device.id(), forwarding);
345 }
346
347 private DefaultForwardingObjective.Builder createBuilder(PacketRequest request) {
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000348 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
349 .punt()
350 .wipeDeferred()
351 .build();
Charles Chan874900e2016-12-09 16:55:39 -0800352
Thomas Vachuska27bee092015-06-23 19:03:10 -0700353 return DefaultForwardingObjective.builder()
354 .withPriority(request.priority().priorityValue())
355 .withSelector(request.selector())
Ray Milkeyd1751942018-11-13 13:32:10 -0800356 .fromApp(appId)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700357 .withFlag(ForwardingObjective.Flag.VERSATILE)
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000358 .withTreatment(treatment)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700359 .makePermanent();
360 }
361
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800362 @Override
alshabib7674db42014-09-12 23:40:46 -0700363 public void emit(OutboundPacket packet) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900364 checkPermission(PACKET_WRITE);
tomc370ebd2014-09-16 01:25:21 -0700365 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700366 store.emit(packet);
367 }
368
369 private void localEmit(OutboundPacket packet) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700370 Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800371 if (device == null) {
372 return;
373 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700374 PacketProvider packetProvider = getProvider(device.providerId());
alshabib3d643ec2014-10-22 18:33:00 -0700375 if (packetProvider != null) {
376 packetProvider.emit(packet);
377 }
alshabib7674db42014-09-12 23:40:46 -0700378 }
379
380 @Override
tomc370ebd2014-09-16 01:25:21 -0700381 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700382 return new InternalPacketProviderService(provider);
383 }
384
Thomas Vachuska924cda42015-09-22 12:11:27 -0700385 /**
386 * Personalized packet provider service issued to the supplied provider.
387 */
alshabib7674db42014-09-12 23:40:46 -0700388 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700389 extends AbstractProviderService<PacketProvider>
390 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700391
392 protected InternalPacketProviderService(PacketProvider provider) {
393 super(provider);
394 }
395
396 @Override
397 public void processPacket(PacketContext context) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800398 // TODO filter packets sent to processors based on registrations
Thomas Vachuska924cda42015-09-22 12:11:27 -0700399 for (ProcessorEntry entry : processors) {
Jonathan Hartf5638302015-11-16 10:56:20 -0800400 try {
Jonathan Hart34a14f72018-01-25 09:34:33 -0800401 if (log.isTraceEnabled()) {
402 log.trace("Starting packet processing by {}",
403 entry.processor().getClass().getName());
404 }
405
Jonathan Hartf5638302015-11-16 10:56:20 -0800406 long start = System.nanoTime();
407 entry.processor().process(context);
408 entry.addNanos(System.nanoTime() - start);
Jonathan Hart34a14f72018-01-25 09:34:33 -0800409
410 if (log.isTraceEnabled()) {
411 log.trace("Finished packet processing by {}",
412 entry.processor().getClass().getName());
413 }
Jonathan Hartf5638302015-11-16 10:56:20 -0800414 } catch (Exception e) {
415 log.warn("Packet processor {} threw an exception", entry.processor(), e);
416 }
alshabib7674db42014-09-12 23:40:46 -0700417 }
418 }
419
420 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700421
alshabib19e2cea2015-12-07 11:31:49 -0800422
Jonathan Hart4f60f982014-10-27 08:11:17 -0700423 /**
424 * Internal callback from the packet store.
425 */
Andrea Campanella5b240532016-02-05 09:44:41 -0800426 protected class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700427 @Override
428 public void notify(PacketEvent event) {
429 localEmit(event.subject());
430 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700431
432 @Override
433 public void requestPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800434 DeviceId deviceid = request.deviceId().orElse(null);
435
436 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900437 Device device = deviceService.getDevice(deviceid);
438
439 if (device != null) {
440 pushRule(deviceService.getDevice(deviceid), request);
441 }
alshabib19e2cea2015-12-07 11:31:49 -0800442 } else {
443 pushToAllDevices(request);
444 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700445 }
446
447 @Override
448 public void cancelPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800449 DeviceId deviceid = request.deviceId().orElse(null);
450
451 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900452 Device device = deviceService.getDevice(deviceid);
453
454 if (device != null) {
455 removeRule(deviceService.getDevice(deviceid), request);
456 }
alshabib19e2cea2015-12-07 11:31:49 -0800457 } else {
458 removeFromAllDevices(request);
459 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700460 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700461 }
462
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800463 /**
464 * Internal listener for device service events.
465 */
466 private class InternalDeviceListener implements DeviceListener {
Thomas Vachuska42676812017-10-03 15:12:41 -0700467
468 @Override
469 public boolean isRelevant(DeviceEvent event) {
470 return event.type() == DeviceEvent.Type.DEVICE_ADDED ||
471 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
472 }
473
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800474 @Override
475 public void event(DeviceEvent event) {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700476 eventHandlingExecutor.execute(() -> {
477 try {
Ray Milkeyfa89f2a2017-11-30 13:52:54 -0800478 if (driverService == null) {
479 // Event came in after the driver service shut down, nothing to be done
480 return;
481 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700482 Device device = event.subject();
Yi Tseng809b5d72017-08-16 14:00:37 -0700483 Driver driver = driverService.getDriver(device.id());
484 if (driver == null) {
485 return;
486 }
487 if (!Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
488 return;
489 }
490 if (!deviceService.isAvailable(event.subject().id())) {
491 return;
492 }
Thomas Vachuska42676812017-10-03 15:12:41 -0700493 pushRulesToDevice(device);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700494 } catch (Exception e) {
495 log.warn("Failed to process {}", event, e);
496 }
497 });
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800498 }
499 }
500
Thomas Vachuska924cda42015-09-22 12:11:27 -0700501 /**
502 * Entity for tracking stats for a packet processor.
503 */
504 private class ProcessorEntry implements PacketProcessorEntry {
505 private final PacketProcessor processor;
506 private final int priority;
507 private long invocations = 0;
508 private long nanos = 0;
509
510 public ProcessorEntry(PacketProcessor processor, int priority) {
511 this.processor = processor;
512 this.priority = priority;
513 }
514
515 @Override
516 public PacketProcessor processor() {
517 return processor;
518 }
519
520 @Override
521 public int priority() {
522 return priority;
523 }
524
525 @Override
526 public long invocations() {
527 return invocations;
528 }
529
530 @Override
531 public long totalNanos() {
532 return nanos;
533 }
534
535 @Override
536 public long averageNanos() {
537 return invocations > 0 ? nanos / invocations : 0;
538 }
539
540 void addNanos(long nanos) {
541 this.nanos += nanos;
542 this.invocations++;
543 }
544 }
alshabibae857582014-09-12 23:53:10 -0700545}