blob: b9ac1a49c78208ddb4ec04a4adbf6d6cff629524 [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;
Thomas Vachuskab73ca6d2018-12-13 10:08:00 -080020import org.onlab.util.ItemNotFoundException;
Madan Jampani6f8b7022015-12-07 16:59:59 -080021import org.onosproject.cluster.ClusterService;
22import org.onosproject.cluster.NodeId;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080023import org.onosproject.core.ApplicationId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070024import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.net.Device;
alshabib19e2cea2015-12-07 11:31:49 -080026import org.onosproject.net.DeviceId;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080027import org.onosproject.net.device.DeviceEvent;
28import org.onosproject.net.device.DeviceListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.net.device.DeviceService;
Yi Tseng809b5d72017-08-16 14:00:37 -070030import org.onosproject.net.driver.Driver;
31import org.onosproject.net.driver.DriverService;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080032import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080033import org.onosproject.net.flow.TrafficSelector;
Charles Chan874900e2016-12-09 16:55:39 -080034import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart17d00452015-04-21 17:10:00 -070035import org.onosproject.net.flowobjective.DefaultForwardingObjective;
36import org.onosproject.net.flowobjective.FlowObjectiveService;
37import org.onosproject.net.flowobjective.ForwardingObjective;
38import org.onosproject.net.flowobjective.Objective;
39import org.onosproject.net.flowobjective.ObjectiveContext;
40import org.onosproject.net.flowobjective.ObjectiveError;
alshabib42947782015-03-31 14:59:06 -070041import org.onosproject.net.packet.DefaultPacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.packet.OutboundPacket;
43import org.onosproject.net.packet.PacketContext;
44import org.onosproject.net.packet.PacketEvent;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080045import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080046import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska924cda42015-09-22 12:11:27 -070047import org.onosproject.net.packet.PacketProcessorEntry;
Brian O'Connorabafb502014-12-02 22:26:20 -080048import org.onosproject.net.packet.PacketProvider;
49import org.onosproject.net.packet.PacketProviderRegistry;
50import org.onosproject.net.packet.PacketProviderService;
alshabib42947782015-03-31 14:59:06 -070051import org.onosproject.net.packet.PacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.packet.PacketService;
53import org.onosproject.net.packet.PacketStore;
54import org.onosproject.net.packet.PacketStoreDelegate;
55import org.onosproject.net.provider.AbstractProviderRegistry;
56import org.onosproject.net.provider.AbstractProviderService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070057import org.osgi.service.component.annotations.Activate;
58import org.osgi.service.component.annotations.Component;
59import org.osgi.service.component.annotations.Deactivate;
60import org.osgi.service.component.annotations.Reference;
61import org.osgi.service.component.annotations.ReferenceCardinality;
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 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070080@Component(immediate = true, service = { PacketService.class, PacketProviderRegistry.class })
tom202175a2014-09-19 19:00:11 -070081public class PacketManager
Thomas Vachuska6cba4952015-04-22 12:38:22 -070082 extends AbstractProviderRegistry<PacketProvider, PacketProviderService>
83 implements PacketService, PacketProviderRegistry {
alshabib7674db42014-09-12 23:40:46 -070084
85 private final Logger log = getLogger(getClass());
86
Jonathan Hartdbaed992016-09-08 22:04:33 -070087 private static final String ERROR_NULL_PROCESSOR = "Processor cannot be null";
88 private static final String ERROR_NULL_SELECTOR = "Selector cannot be null";
89 private static final String ERROR_NULL_APP_ID = "Application ID cannot be null";
90 private static final String ERROR_NULL_DEVICE_ID = "Device ID cannot be null";
Yi Tseng809b5d72017-08-16 14:00:37 -070091 private static final String SUPPORT_PACKET_REQUEST_PROPERTY = "supportPacketRequest";
Thomas Vachuska27bee092015-06-23 19:03:10 -070092
Jonathan Hart4f60f982014-10-27 08:11:17 -070093 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
94
Ray Milkeyd84f89b2018-08-17 14:54:17 -070095 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -080096 protected CoreService coreService;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070097
Ray Milkeyd84f89b2018-08-17 14:54:17 -070098 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -080099 protected ClusterService clusterService;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800100
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700101 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800102 protected DeviceService deviceService;
alshabib7674db42014-09-12 23:40:46 -0700103
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng809b5d72017-08-16 14:00:37 -0700105 protected DriverService driverService;
106
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800108 protected PacketStore store;
Jonathan Hart4f60f982014-10-27 08:11:17 -0700109
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700110 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hartdbaed992016-09-08 22:04:33 -0700111 protected FlowObjectiveService objectiveService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700112
Madan Jampanic626f1e2015-05-29 13:53:38 -0700113 private ExecutorService eventHandlingExecutor;
114
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800115 private final DeviceListener deviceListener = new InternalDeviceListener();
116
Thomas Vachuska924cda42015-09-22 12:11:27 -0700117 private final List<ProcessorEntry> processors = Lists.newCopyOnWriteArrayList();
alshabib7674db42014-09-12 23:40:46 -0700118
Thomas Vachuska42676812017-10-03 15:12:41 -0700119 private final PacketDriverProvider defaultProvider = new PacketDriverProvider();
Andrea Campanella5b240532016-02-05 09:44:41 -0800120
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700121 private ApplicationId appId;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800122 private NodeId localNodeId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700123
alshabib7674db42014-09-12 23:40:46 -0700124 @Activate
125 public void activate() {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700126 eventHandlingExecutor = Executors.newSingleThreadExecutor(
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700127 groupedThreads("onos/net/packet", "event-handler", log));
Madan Jampani6f8b7022015-12-07 16:59:59 -0800128 localNodeId = clusterService.getLocalNode().id();
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700129 appId = coreService.getAppId(CoreService.CORE_APP_NAME);
Jonathan Hart4f60f982014-10-27 08:11:17 -0700130 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800131 deviceService.addListener(deviceListener);
Andrea Campanella5b240532016-02-05 09:44:41 -0800132 defaultProvider.init(deviceService);
Charles Chanaa7e9732018-04-06 17:03:23 -0700133 store.existingRequests().forEach(request -> {
134 if (request.deviceId().isPresent()) {
135 Device device = deviceService.getDevice(request.deviceId().get());
136 if (device != null) {
137 pushRule(device, request);
138 } else {
Thomas Vachuskab73ca6d2018-12-13 10:08:00 -0800139 log.info("Device is not ready yet; not processing packet request {}", request);
Charles Chanaa7e9732018-04-06 17:03:23 -0700140 }
141 } else {
142 pushToAllDevices(request);
143 }
144 });
alshabib7674db42014-09-12 23:40:46 -0700145 log.info("Started");
146 }
147
148 @Deactivate
149 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700150 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800151 deviceService.removeListener(deviceListener);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700152 eventHandlingExecutor.shutdown();
alshabib7674db42014-09-12 23:40:46 -0700153 log.info("Stopped");
154 }
155
156 @Override
Andrea Campanella5b240532016-02-05 09:44:41 -0800157 protected PacketProvider defaultProvider() {
158 return defaultProvider;
159 }
160
161 @Override
alshabib7674db42014-09-12 23:40:46 -0700162 public void addProcessor(PacketProcessor processor, int priority) {
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 ProcessorEntry entry = new ProcessorEntry(processor, priority);
166
167 // Insert the new processor according to its priority.
168 int i = 0;
169 for (; i < processors.size(); i++) {
170 if (priority < processors.get(i).priority()) {
171 break;
172 }
173 }
174 processors.add(i, entry);
alshabib7674db42014-09-12 23:40:46 -0700175 }
176
177 @Override
178 public void removeProcessor(PacketProcessor processor) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900179 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700180 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700181
182 // Remove the processor entry.
183 for (int i = 0; i < processors.size(); i++) {
184 if (processors.get(i).processor() == processor) {
185 processors.remove(i);
186 break;
187 }
188 }
alshabib7674db42014-09-12 23:40:46 -0700189 }
190
191 @Override
Thomas Vachuska924cda42015-09-22 12:11:27 -0700192 public List<PacketProcessorEntry> getProcessors() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900193 checkPermission(PACKET_READ);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700194 return ImmutableList.copyOf(processors);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700195 }
196
197 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800198 public void requestPackets(TrafficSelector selector, PacketPriority priority,
199 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900200 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700201 checkNotNull(selector, ERROR_NULL_SELECTOR);
202 checkNotNull(appId, ERROR_NULL_APP_ID);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800203
alshabib19e2cea2015-12-07 11:31:49 -0800204 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000205 localNodeId, Optional.empty());
Brian O'Connor21b028e2015-10-08 22:50:02 -0700206 store.requestPackets(request);
Saurav Dasc313c402015-02-27 10:09:47 -0800207 }
208
209 @Override
alshabib19e2cea2015-12-07 11:31:49 -0800210 public void requestPackets(TrafficSelector selector, PacketPriority priority,
211 ApplicationId appId, Optional<DeviceId> deviceId) {
212 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700213 checkNotNull(selector, ERROR_NULL_SELECTOR);
214 checkNotNull(appId, ERROR_NULL_APP_ID);
215 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800216
217 PacketRequest request =
218 new DefaultPacketRequest(selector, priority, appId,
219 localNodeId, deviceId);
220
221 store.requestPackets(request);
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000222
alshabib19e2cea2015-12-07 11:31:49 -0800223 }
224
225 @Override
Thomas Vachuska27bee092015-06-23 19:03:10 -0700226 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
227 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900228 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700229 checkNotNull(selector, ERROR_NULL_SELECTOR);
230 checkNotNull(appId, ERROR_NULL_APP_ID);
Saurav Dasc313c402015-02-27 10:09:47 -0800231
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000232
alshabib19e2cea2015-12-07 11:31:49 -0800233 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000234 localNodeId, Optional.empty());
alshabib19e2cea2015-12-07 11:31:49 -0800235 store.cancelPackets(request);
236 }
237
238 @Override
239 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
240 ApplicationId appId, Optional<DeviceId> deviceId) {
241 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700242 checkNotNull(selector, ERROR_NULL_SELECTOR);
243 checkNotNull(appId, ERROR_NULL_APP_ID);
244 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800245
246 PacketRequest request = new DefaultPacketRequest(selector, priority,
247 appId, localNodeId,
248 deviceId);
Brian O'Connor21b028e2015-10-08 22:50:02 -0700249 store.cancelPackets(request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800250 }
251
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700252 @Override
253 public List<PacketRequest> getRequests() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900254 checkPermission(PACKET_READ);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700255 return store.existingRequests();
256 }
257
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800258 /**
Thomas Vachuska924cda42015-09-22 12:11:27 -0700259 * Pushes all rules to the specified device.
260 *
261 * @param device device on which to install packet request flows
262 */
263 private void pushRulesToDevice(Device device) {
264 log.debug("Pushing packet requests to device {}", device.id());
265 for (PacketRequest request : store.existingRequests()) {
alshabib19e2cea2015-12-07 11:31:49 -0800266 if (!request.deviceId().isPresent()) {
267 pushRule(device, request);
268 } else if (request.deviceId().get().equals(device.id())) {
269 pushRule(device, request);
270 }
271
Thomas Vachuska924cda42015-09-22 12:11:27 -0700272 }
273 }
274
275 /**
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800276 * Pushes a packet request flow rule to all devices.
277 *
278 * @param request the packet request
279 */
280 private void pushToAllDevices(PacketRequest request) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700281 log.debug("Pushing packet request {} to all devices", request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800282 for (Device device : deviceService.getDevices()) {
Thomas Vachuskab73ca6d2018-12-13 10:08:00 -0800283 try {
284 Driver driver = driverService.getDriver(device.id());
285 if (driver != null &&
286 Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
287 pushRule(device, request);
288 }
289 } catch (ItemNotFoundException e) {
290 log.warn("Device driver not found for {}; not processing packet request {}",
291 device.id(), request);
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -0700292 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800293 }
294 }
295
296 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700297 * Removes packet request flow rule from all devices.
298 *
299 * @param request the packet request
300 */
301 private void removeFromAllDevices(PacketRequest request) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700302 deviceService.getAvailableDevices().forEach(d -> removeRule(d, request));
Thomas Vachuska27bee092015-06-23 19:03:10 -0700303 }
304
305 /**
306 * Pushes packet intercept flow rules to the device.
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800307 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700308 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800309 * @param request the packet request
310 */
311 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700312 if (!device.type().equals(Device.Type.SWITCH)) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800313 return;
314 }
315
Carmelo Cascone0761cd32018-08-29 19:22:50 -0700316 if (!deviceService.isAvailable(device.id())) {
317 return;
318 }
319
Thomas Vachuska27bee092015-06-23 19:03:10 -0700320 ForwardingObjective forwarding = createBuilder(request)
Jonathan Hart17d00452015-04-21 17:10:00 -0700321 .add(new ObjectiveContext() {
322 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700323 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700324 log.warn("Failed to install packet request {} to {}: {}",
325 request, device.id(), error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700326 }
327 });
328
329 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800330 }
331
Thomas Vachuska27bee092015-06-23 19:03:10 -0700332 /**
333 * Removes packet intercept flow rules from the device.
334 *
335 * @param device the device to remove the rules deom
336 * @param request the packet request
337 */
338 private void removeRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700339 if (!device.type().equals(Device.Type.SWITCH)) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700340 return;
341 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700342 ForwardingObjective forwarding = createBuilder(request)
343 .remove(new ObjectiveContext() {
344 @Override
345 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700346 log.warn("Failed to withdraw packet request {} from {}: {}",
347 request, device.id(), error);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700348 }
349 });
Thomas Vachuska27bee092015-06-23 19:03:10 -0700350 objectiveService.forward(device.id(), forwarding);
351 }
352
353 private DefaultForwardingObjective.Builder createBuilder(PacketRequest request) {
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000354 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
355 .punt()
356 .wipeDeferred()
357 .build();
Charles Chan874900e2016-12-09 16:55:39 -0800358
Thomas Vachuska27bee092015-06-23 19:03:10 -0700359 return DefaultForwardingObjective.builder()
360 .withPriority(request.priority().priorityValue())
361 .withSelector(request.selector())
Ray Milkeyd1751942018-11-13 13:32:10 -0800362 .fromApp(appId)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700363 .withFlag(ForwardingObjective.Flag.VERSATILE)
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000364 .withTreatment(treatment)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700365 .makePermanent();
366 }
367
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800368 @Override
alshabib7674db42014-09-12 23:40:46 -0700369 public void emit(OutboundPacket packet) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900370 checkPermission(PACKET_WRITE);
tomc370ebd2014-09-16 01:25:21 -0700371 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700372 store.emit(packet);
373 }
374
375 private void localEmit(OutboundPacket packet) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700376 Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800377 if (device == null) {
378 return;
379 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700380 PacketProvider packetProvider = getProvider(device.providerId());
alshabib3d643ec2014-10-22 18:33:00 -0700381 if (packetProvider != null) {
382 packetProvider.emit(packet);
383 }
alshabib7674db42014-09-12 23:40:46 -0700384 }
385
386 @Override
tomc370ebd2014-09-16 01:25:21 -0700387 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700388 return new InternalPacketProviderService(provider);
389 }
390
Thomas Vachuska924cda42015-09-22 12:11:27 -0700391 /**
392 * Personalized packet provider service issued to the supplied provider.
393 */
alshabib7674db42014-09-12 23:40:46 -0700394 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700395 extends AbstractProviderService<PacketProvider>
396 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700397
398 protected InternalPacketProviderService(PacketProvider provider) {
399 super(provider);
400 }
401
402 @Override
403 public void processPacket(PacketContext context) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800404 // TODO filter packets sent to processors based on registrations
Thomas Vachuska924cda42015-09-22 12:11:27 -0700405 for (ProcessorEntry entry : processors) {
Jonathan Hartf5638302015-11-16 10:56:20 -0800406 try {
Jonathan Hart34a14f72018-01-25 09:34:33 -0800407 if (log.isTraceEnabled()) {
408 log.trace("Starting packet processing by {}",
409 entry.processor().getClass().getName());
410 }
411
Jonathan Hartf5638302015-11-16 10:56:20 -0800412 long start = System.nanoTime();
413 entry.processor().process(context);
414 entry.addNanos(System.nanoTime() - start);
Jonathan Hart34a14f72018-01-25 09:34:33 -0800415
416 if (log.isTraceEnabled()) {
417 log.trace("Finished packet processing by {}",
418 entry.processor().getClass().getName());
419 }
Jonathan Hartf5638302015-11-16 10:56:20 -0800420 } catch (Exception e) {
421 log.warn("Packet processor {} threw an exception", entry.processor(), e);
422 }
alshabib7674db42014-09-12 23:40:46 -0700423 }
424 }
425
426 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700427
alshabib19e2cea2015-12-07 11:31:49 -0800428
Jonathan Hart4f60f982014-10-27 08:11:17 -0700429 /**
430 * Internal callback from the packet store.
431 */
Andrea Campanella5b240532016-02-05 09:44:41 -0800432 protected class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700433 @Override
434 public void notify(PacketEvent event) {
435 localEmit(event.subject());
436 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700437
438 @Override
439 public void requestPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800440 DeviceId deviceid = request.deviceId().orElse(null);
441
442 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900443 Device device = deviceService.getDevice(deviceid);
444
445 if (device != null) {
446 pushRule(deviceService.getDevice(deviceid), request);
447 }
alshabib19e2cea2015-12-07 11:31:49 -0800448 } else {
449 pushToAllDevices(request);
450 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700451 }
452
453 @Override
454 public void cancelPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800455 DeviceId deviceid = request.deviceId().orElse(null);
456
457 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900458 Device device = deviceService.getDevice(deviceid);
459
460 if (device != null) {
461 removeRule(deviceService.getDevice(deviceid), request);
462 }
alshabib19e2cea2015-12-07 11:31:49 -0800463 } else {
464 removeFromAllDevices(request);
465 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700466 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700467 }
468
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800469 /**
470 * Internal listener for device service events.
471 */
472 private class InternalDeviceListener implements DeviceListener {
Thomas Vachuska42676812017-10-03 15:12:41 -0700473
474 @Override
475 public boolean isRelevant(DeviceEvent event) {
476 return event.type() == DeviceEvent.Type.DEVICE_ADDED ||
477 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
478 }
479
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800480 @Override
481 public void event(DeviceEvent event) {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700482 eventHandlingExecutor.execute(() -> {
483 try {
Ray Milkeyfa89f2a2017-11-30 13:52:54 -0800484 if (driverService == null) {
485 // Event came in after the driver service shut down, nothing to be done
486 return;
487 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700488 Device device = event.subject();
Yi Tseng809b5d72017-08-16 14:00:37 -0700489 Driver driver = driverService.getDriver(device.id());
490 if (driver == null) {
491 return;
492 }
493 if (!Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
494 return;
495 }
496 if (!deviceService.isAvailable(event.subject().id())) {
497 return;
498 }
Thomas Vachuska42676812017-10-03 15:12:41 -0700499 pushRulesToDevice(device);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700500 } catch (Exception e) {
Ray Milkey31b00482019-02-07 08:06:28 -0800501 log.warn("Failed to process {}: {}", event, e.getMessage());
Madan Jampanic626f1e2015-05-29 13:53:38 -0700502 }
503 });
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800504 }
505 }
506
Thomas Vachuska924cda42015-09-22 12:11:27 -0700507 /**
508 * Entity for tracking stats for a packet processor.
509 */
510 private class ProcessorEntry implements PacketProcessorEntry {
511 private final PacketProcessor processor;
512 private final int priority;
513 private long invocations = 0;
514 private long nanos = 0;
515
516 public ProcessorEntry(PacketProcessor processor, int priority) {
517 this.processor = processor;
518 this.priority = priority;
519 }
520
521 @Override
522 public PacketProcessor processor() {
523 return processor;
524 }
525
526 @Override
527 public int priority() {
528 return priority;
529 }
530
531 @Override
532 public long invocations() {
533 return invocations;
534 }
535
536 @Override
537 public long totalNanos() {
538 return nanos;
539 }
540
541 @Override
542 public long averageNanos() {
543 return invocations > 0 ? nanos / invocations : 0;
544 }
545
546 void addNanos(long nanos) {
547 this.nanos += nanos;
548 this.invocations++;
549 }
550 }
alshabibae857582014-09-12 23:53:10 -0700551}