blob: 38cfd7656a5e2c6fa4202a62315c86eeabbcc2db [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;
Harshada Chaundkardcd1b142019-03-25 17:27:44 -040062import org.onosproject.net.packet.PacketInFilter;
63import org.onosproject.net.packet.PacketInFilter.FilterAction;
alshabib7674db42014-09-12 23:40:46 -070064import org.slf4j.Logger;
65
Thomas Vachuska7f171b22015-08-21 12:49:08 -070066import java.util.List;
alshabib19e2cea2015-12-07 11:31:49 -080067import java.util.Optional;
Madan Jampanic626f1e2015-05-29 13:53:38 -070068import java.util.concurrent.ExecutorService;
69import java.util.concurrent.Executors;
Harshada Chaundkardcd1b142019-03-25 17:27:44 -040070import java.util.concurrent.CopyOnWriteArrayList;
71
72
alshabib089bb772015-03-03 18:26:26 -080073
74import static com.google.common.base.Preconditions.checkNotNull;
Madan Jampanic626f1e2015-05-29 13:53:38 -070075import static org.onlab.util.Tools.groupedThreads;
Changhoon Yoon541ef712015-05-23 17:18:34 +090076import static org.onosproject.security.AppGuard.checkPermission;
Jonathan Hartdbaed992016-09-08 22:04:33 -070077import static org.onosproject.security.AppPermission.Type.PACKET_EVENT;
78import static org.onosproject.security.AppPermission.Type.PACKET_READ;
79import static org.onosproject.security.AppPermission.Type.PACKET_WRITE;
Thomas Vachuska7f171b22015-08-21 12:49:08 -070080import static org.slf4j.LoggerFactory.getLogger;
alshabib089bb772015-03-03 18:26:26 -080081
alshabib7674db42014-09-12 23:40:46 -070082/**
83 * Provides a basic implementation of the packet SB & NB APIs.
alshabib7674db42014-09-12 23:40:46 -070084 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070085@Component(immediate = true, service = { PacketService.class, PacketProviderRegistry.class })
tom202175a2014-09-19 19:00:11 -070086public class PacketManager
Thomas Vachuska6cba4952015-04-22 12:38:22 -070087 extends AbstractProviderRegistry<PacketProvider, PacketProviderService>
88 implements PacketService, PacketProviderRegistry {
alshabib7674db42014-09-12 23:40:46 -070089
90 private final Logger log = getLogger(getClass());
91
Jonathan Hartdbaed992016-09-08 22:04:33 -070092 private static final String ERROR_NULL_PROCESSOR = "Processor cannot be null";
93 private static final String ERROR_NULL_SELECTOR = "Selector cannot be null";
94 private static final String ERROR_NULL_APP_ID = "Application ID cannot be null";
95 private static final String ERROR_NULL_DEVICE_ID = "Device ID cannot be null";
Yi Tseng809b5d72017-08-16 14:00:37 -070096 private static final String SUPPORT_PACKET_REQUEST_PROPERTY = "supportPacketRequest";
Thomas Vachuska27bee092015-06-23 19:03:10 -070097
Jonathan Hart4f60f982014-10-27 08:11:17 -070098 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
99
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700100 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800101 protected CoreService coreService;
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700102
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700103 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800104 protected ClusterService clusterService;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800105
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700106 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800107 protected DeviceService deviceService;
alshabib7674db42014-09-12 23:40:46 -0700108
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700109 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng809b5d72017-08-16 14:00:37 -0700110 protected DriverService driverService;
111
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700112 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanella5b240532016-02-05 09:44:41 -0800113 protected PacketStore store;
Jonathan Hart4f60f982014-10-27 08:11:17 -0700114
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700115 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hartdbaed992016-09-08 22:04:33 -0700116 protected FlowObjectiveService objectiveService;
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700117
Madan Jampanic626f1e2015-05-29 13:53:38 -0700118 private ExecutorService eventHandlingExecutor;
119
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800120 private final DeviceListener deviceListener = new InternalDeviceListener();
121
Thomas Vachuska924cda42015-09-22 12:11:27 -0700122 private final List<ProcessorEntry> processors = Lists.newCopyOnWriteArrayList();
alshabib7674db42014-09-12 23:40:46 -0700123
Thomas Vachuska42676812017-10-03 15:12:41 -0700124 private final PacketDriverProvider defaultProvider = new PacketDriverProvider();
Andrea Campanella5b240532016-02-05 09:44:41 -0800125
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700126 private ApplicationId appId;
Madan Jampani6f8b7022015-12-07 16:59:59 -0800127 private NodeId localNodeId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700128
Harshada Chaundkardcd1b142019-03-25 17:27:44 -0400129 private List<PacketInFilter> filters = new CopyOnWriteArrayList<>();
130
alshabib7674db42014-09-12 23:40:46 -0700131 @Activate
132 public void activate() {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700133 eventHandlingExecutor = Executors.newSingleThreadExecutor(
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700134 groupedThreads("onos/net/packet", "event-handler", log));
Madan Jampani6f8b7022015-12-07 16:59:59 -0800135 localNodeId = clusterService.getLocalNode().id();
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700136 appId = coreService.getAppId(CoreService.CORE_APP_NAME);
Jonathan Hart4f60f982014-10-27 08:11:17 -0700137 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800138 deviceService.addListener(deviceListener);
Andrea Campanella5b240532016-02-05 09:44:41 -0800139 defaultProvider.init(deviceService);
Charles Chanaa7e9732018-04-06 17:03:23 -0700140 store.existingRequests().forEach(request -> {
141 if (request.deviceId().isPresent()) {
142 Device device = deviceService.getDevice(request.deviceId().get());
143 if (device != null) {
144 pushRule(device, request);
145 } else {
Thomas Vachuskab73ca6d2018-12-13 10:08:00 -0800146 log.info("Device is not ready yet; not processing packet request {}", request);
Charles Chanaa7e9732018-04-06 17:03:23 -0700147 }
148 } else {
149 pushToAllDevices(request);
150 }
151 });
alshabib7674db42014-09-12 23:40:46 -0700152 log.info("Started");
153 }
154
155 @Deactivate
156 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700157 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800158 deviceService.removeListener(deviceListener);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700159 eventHandlingExecutor.shutdown();
alshabib7674db42014-09-12 23:40:46 -0700160 log.info("Stopped");
161 }
162
163 @Override
Andrea Campanella5b240532016-02-05 09:44:41 -0800164 protected PacketProvider defaultProvider() {
165 return defaultProvider;
166 }
167
168 @Override
alshabib7674db42014-09-12 23:40:46 -0700169 public void addProcessor(PacketProcessor processor, int priority) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900170 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700171 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700172 ProcessorEntry entry = new ProcessorEntry(processor, priority);
173
174 // Insert the new processor according to its priority.
175 int i = 0;
176 for (; i < processors.size(); i++) {
177 if (priority < processors.get(i).priority()) {
178 break;
179 }
180 }
181 processors.add(i, entry);
alshabib7674db42014-09-12 23:40:46 -0700182 }
183
184 @Override
185 public void removeProcessor(PacketProcessor processor) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900186 checkPermission(PACKET_EVENT);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700187 checkNotNull(processor, ERROR_NULL_PROCESSOR);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700188
189 // Remove the processor entry.
190 for (int i = 0; i < processors.size(); i++) {
191 if (processors.get(i).processor() == processor) {
192 processors.remove(i);
193 break;
194 }
195 }
alshabib7674db42014-09-12 23:40:46 -0700196 }
197
198 @Override
Harshada Chaundkardcd1b142019-03-25 17:27:44 -0400199 public void addFilter(PacketInFilter filter) {
200 filters.add(filter);
201 }
202
203 @Override
204 public void removeFilter(PacketInFilter filter) {
205 filters.remove(filter);
206 }
207
208 @Override
Thomas Vachuska924cda42015-09-22 12:11:27 -0700209 public List<PacketProcessorEntry> getProcessors() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900210 checkPermission(PACKET_READ);
Thomas Vachuska924cda42015-09-22 12:11:27 -0700211 return ImmutableList.copyOf(processors);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700212 }
213
214 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800215 public void requestPackets(TrafficSelector selector, PacketPriority priority,
216 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900217 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700218 checkNotNull(selector, ERROR_NULL_SELECTOR);
219 checkNotNull(appId, ERROR_NULL_APP_ID);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800220
alshabib19e2cea2015-12-07 11:31:49 -0800221 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000222 localNodeId, Optional.empty());
Brian O'Connor21b028e2015-10-08 22:50:02 -0700223 store.requestPackets(request);
Saurav Dasc313c402015-02-27 10:09:47 -0800224 }
225
226 @Override
alshabib19e2cea2015-12-07 11:31:49 -0800227 public void requestPackets(TrafficSelector selector, PacketPriority priority,
228 ApplicationId appId, Optional<DeviceId> deviceId) {
229 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700230 checkNotNull(selector, ERROR_NULL_SELECTOR);
231 checkNotNull(appId, ERROR_NULL_APP_ID);
232 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800233
234 PacketRequest request =
235 new DefaultPacketRequest(selector, priority, appId,
236 localNodeId, deviceId);
237
238 store.requestPackets(request);
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000239
alshabib19e2cea2015-12-07 11:31:49 -0800240 }
241
242 @Override
Thomas Vachuska27bee092015-06-23 19:03:10 -0700243 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
244 ApplicationId appId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900245 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700246 checkNotNull(selector, ERROR_NULL_SELECTOR);
247 checkNotNull(appId, ERROR_NULL_APP_ID);
Saurav Dasc313c402015-02-27 10:09:47 -0800248
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000249
alshabib19e2cea2015-12-07 11:31:49 -0800250 PacketRequest request = new DefaultPacketRequest(selector, priority, appId,
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000251 localNodeId, Optional.empty());
alshabib19e2cea2015-12-07 11:31:49 -0800252 store.cancelPackets(request);
253 }
254
255 @Override
256 public void cancelPackets(TrafficSelector selector, PacketPriority priority,
257 ApplicationId appId, Optional<DeviceId> deviceId) {
258 checkPermission(PACKET_READ);
Jonathan Hartdbaed992016-09-08 22:04:33 -0700259 checkNotNull(selector, ERROR_NULL_SELECTOR);
260 checkNotNull(appId, ERROR_NULL_APP_ID);
261 checkNotNull(deviceId, ERROR_NULL_DEVICE_ID);
alshabib19e2cea2015-12-07 11:31:49 -0800262
263 PacketRequest request = new DefaultPacketRequest(selector, priority,
264 appId, localNodeId,
265 deviceId);
Brian O'Connor21b028e2015-10-08 22:50:02 -0700266 store.cancelPackets(request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800267 }
268
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700269 @Override
270 public List<PacketRequest> getRequests() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900271 checkPermission(PACKET_READ);
Thomas Vachuska7f171b22015-08-21 12:49:08 -0700272 return store.existingRequests();
273 }
274
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800275 /**
Thomas Vachuska924cda42015-09-22 12:11:27 -0700276 * Pushes all rules to the specified device.
277 *
278 * @param device device on which to install packet request flows
279 */
280 private void pushRulesToDevice(Device device) {
281 log.debug("Pushing packet requests to device {}", device.id());
282 for (PacketRequest request : store.existingRequests()) {
alshabib19e2cea2015-12-07 11:31:49 -0800283 if (!request.deviceId().isPresent()) {
284 pushRule(device, request);
285 } else if (request.deviceId().get().equals(device.id())) {
286 pushRule(device, request);
287 }
Thomas Vachuska924cda42015-09-22 12:11:27 -0700288 }
289 }
290
291 /**
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800292 * Pushes a packet request flow rule to all devices.
293 *
294 * @param request the packet request
295 */
296 private void pushToAllDevices(PacketRequest request) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700297 log.debug("Pushing packet request {} to all devices", request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800298 for (Device device : deviceService.getDevices()) {
Thomas Vachuskab73ca6d2018-12-13 10:08:00 -0800299 try {
300 Driver driver = driverService.getDriver(device.id());
301 if (driver != null &&
302 Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
303 pushRule(device, request);
304 }
305 } catch (ItemNotFoundException e) {
306 log.warn("Device driver not found for {}; not processing packet request {}",
307 device.id(), request);
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -0700308 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800309 }
310 }
311
312 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700313 * Removes packet request flow rule from all devices.
314 *
315 * @param request the packet request
316 */
317 private void removeFromAllDevices(PacketRequest request) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700318 deviceService.getAvailableDevices().forEach(d -> removeRule(d, request));
Thomas Vachuska27bee092015-06-23 19:03:10 -0700319 }
320
321 /**
322 * Pushes packet intercept flow rules to the device.
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800323 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700324 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800325 * @param request the packet request
326 */
327 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700328 if (!device.type().equals(Device.Type.SWITCH)) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800329 return;
330 }
331
Carmelo Cascone0761cd32018-08-29 19:22:50 -0700332 if (!deviceService.isAvailable(device.id())) {
333 return;
334 }
335
Thomas Vachuska27bee092015-06-23 19:03:10 -0700336 ForwardingObjective forwarding = createBuilder(request)
Jonathan Hart17d00452015-04-21 17:10:00 -0700337 .add(new ObjectiveContext() {
338 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700339 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700340 log.warn("Failed to install packet request {} to {}: {}",
341 request, device.id(), error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700342 }
343 });
344
345 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800346 }
347
Thomas Vachuska27bee092015-06-23 19:03:10 -0700348 /**
349 * Removes packet intercept flow rules from the device.
350 *
351 * @param device the device to remove the rules deom
352 * @param request the packet request
353 */
354 private void removeRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700355 if (!device.type().equals(Device.Type.SWITCH)) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700356 return;
357 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700358 ForwardingObjective forwarding = createBuilder(request)
359 .remove(new ObjectiveContext() {
360 @Override
361 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700362 log.warn("Failed to withdraw packet request {} from {}: {}",
363 request, device.id(), error);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700364 }
365 });
Thomas Vachuska27bee092015-06-23 19:03:10 -0700366 objectiveService.forward(device.id(), forwarding);
367 }
368
369 private DefaultForwardingObjective.Builder createBuilder(PacketRequest request) {
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000370 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
371 .punt()
372 .wipeDeferred()
373 .build();
Charles Chan874900e2016-12-09 16:55:39 -0800374
Thomas Vachuska27bee092015-06-23 19:03:10 -0700375 return DefaultForwardingObjective.builder()
376 .withPriority(request.priority().priorityValue())
377 .withSelector(request.selector())
Ray Milkeyd1751942018-11-13 13:32:10 -0800378 .fromApp(appId)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700379 .withFlag(ForwardingObjective.Flag.VERSATILE)
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000380 .withTreatment(treatment)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700381 .makePermanent();
382 }
383
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800384 @Override
alshabib7674db42014-09-12 23:40:46 -0700385 public void emit(OutboundPacket packet) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900386 checkPermission(PACKET_WRITE);
tomc370ebd2014-09-16 01:25:21 -0700387 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700388 store.emit(packet);
389 }
390
Harshada Chaundkardcd1b142019-03-25 17:27:44 -0400391 @Override
392 public List<PacketInFilter> getFilters() {
393 return ImmutableList.copyOf(filters);
394 }
395
396 @Override
397 public void clearFilters() {
398 for (PacketInFilter filter: filters) {
399 filter.stop();
400 }
401 filters.clear();
402 }
403
Jonathan Hart4f60f982014-10-27 08:11:17 -0700404 private void localEmit(OutboundPacket packet) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700405 Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800406 if (device == null) {
407 return;
408 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700409 PacketProvider packetProvider = getProvider(device.providerId());
alshabib3d643ec2014-10-22 18:33:00 -0700410 if (packetProvider != null) {
411 packetProvider.emit(packet);
412 }
alshabib7674db42014-09-12 23:40:46 -0700413 }
414
415 @Override
tomc370ebd2014-09-16 01:25:21 -0700416 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700417 return new InternalPacketProviderService(provider);
418 }
419
Thomas Vachuska924cda42015-09-22 12:11:27 -0700420 /**
421 * Personalized packet provider service issued to the supplied provider.
422 */
alshabib7674db42014-09-12 23:40:46 -0700423 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700424 extends AbstractProviderService<PacketProvider>
425 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700426
427 protected InternalPacketProviderService(PacketProvider provider) {
428 super(provider);
429 }
430
Harshada Chaundkardcd1b142019-03-25 17:27:44 -0400431 /**
432 * Loops through all packet filters and checks if the filter is
433 * enabled and allowed to be processed.
434 * It increments the counter to track the pending packets to be
435 * processed based on the filter selected.
436 *
437 * @param context PackerContext holding the packet information
438 * @return FilterAction Action decided for the based on the filter applied
439 */
440 private FilterAction prePacketProcess(PacketContext context) {
441 FilterAction filterAction = FilterAction.FILTER_INVALID;
442 for (PacketInFilter filter: filters) {
443 filterAction = filter.preProcess(context);
444 if (filterAction == FilterAction.FILTER_DISABLED) {
445 if (log.isTraceEnabled()) {
446 log.trace("{}: filter is disabled during pre processing", filter.name());
447 }
448 continue;
449 }
450 if (filterAction == FilterAction.PACKET_DENY) {
451 if (log.isTraceEnabled()) {
452 log.trace("{}: overflow counter after dropping packet is: {}", filter.name(),
453 filter.droppedPackets());
454 }
455 break;
456 }
457 if (filterAction == FilterAction.PACKET_ALLOW) {
458 if (log.isTraceEnabled()) {
459 log.trace("{}: counter after picked for processing is: {}", filter.name(),
460 filter.pendingPackets());
461 }
462 break;
463 }
464 }
465 return filterAction;
466 }
467
alshabib7674db42014-09-12 23:40:46 -0700468 @Override
469 public void processPacket(PacketContext context) {
Harshada Chaundkardcd1b142019-03-25 17:27:44 -0400470 FilterAction filterAction = prePacketProcess(context);
471
472 if (filterAction == FilterAction.PACKET_DENY) {
473 if (log.isTraceEnabled()) {
474 log.trace("The packet is dropped as crossed the maxcount");
475 }
476 return;
477 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800478 // TODO filter packets sent to processors based on registrations
Thomas Vachuska924cda42015-09-22 12:11:27 -0700479 for (ProcessorEntry entry : processors) {
Jonathan Hartf5638302015-11-16 10:56:20 -0800480 try {
Jonathan Hart34a14f72018-01-25 09:34:33 -0800481 if (log.isTraceEnabled()) {
482 log.trace("Starting packet processing by {}",
483 entry.processor().getClass().getName());
484 }
485
Jonathan Hartf5638302015-11-16 10:56:20 -0800486 long start = System.nanoTime();
487 entry.processor().process(context);
488 entry.addNanos(System.nanoTime() - start);
Jonathan Hart34a14f72018-01-25 09:34:33 -0800489
490 if (log.isTraceEnabled()) {
491 log.trace("Finished packet processing by {}",
492 entry.processor().getClass().getName());
493 }
Jonathan Hartf5638302015-11-16 10:56:20 -0800494 } catch (Exception e) {
495 log.warn("Packet processor {} threw an exception", entry.processor(), e);
496 }
alshabib7674db42014-09-12 23:40:46 -0700497 }
498 }
499
500 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700501
alshabib19e2cea2015-12-07 11:31:49 -0800502
Jonathan Hart4f60f982014-10-27 08:11:17 -0700503 /**
504 * Internal callback from the packet store.
505 */
Andrea Campanella5b240532016-02-05 09:44:41 -0800506 protected class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700507 @Override
508 public void notify(PacketEvent event) {
509 localEmit(event.subject());
510 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700511
512 @Override
513 public void requestPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800514 DeviceId deviceid = request.deviceId().orElse(null);
515
516 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900517 Device device = deviceService.getDevice(deviceid);
518
519 if (device != null) {
520 pushRule(deviceService.getDevice(deviceid), request);
521 }
alshabib19e2cea2015-12-07 11:31:49 -0800522 } else {
523 pushToAllDevices(request);
524 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700525 }
526
527 @Override
528 public void cancelPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800529 DeviceId deviceid = request.deviceId().orElse(null);
530
531 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900532 Device device = deviceService.getDevice(deviceid);
533
534 if (device != null) {
535 removeRule(deviceService.getDevice(deviceid), request);
536 }
alshabib19e2cea2015-12-07 11:31:49 -0800537 } else {
538 removeFromAllDevices(request);
539 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700540 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700541 }
542
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800543 /**
544 * Internal listener for device service events.
545 */
546 private class InternalDeviceListener implements DeviceListener {
Thomas Vachuska42676812017-10-03 15:12:41 -0700547
548 @Override
549 public boolean isRelevant(DeviceEvent event) {
550 return event.type() == DeviceEvent.Type.DEVICE_ADDED ||
551 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
552 }
553
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800554 @Override
555 public void event(DeviceEvent event) {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700556 eventHandlingExecutor.execute(() -> {
557 try {
Ray Milkeyfa89f2a2017-11-30 13:52:54 -0800558 if (driverService == null) {
559 // Event came in after the driver service shut down, nothing to be done
560 return;
561 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700562 Device device = event.subject();
Yi Tseng809b5d72017-08-16 14:00:37 -0700563 Driver driver = driverService.getDriver(device.id());
564 if (driver == null) {
565 return;
566 }
567 if (!Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
568 return;
569 }
570 if (!deviceService.isAvailable(event.subject().id())) {
571 return;
572 }
Thomas Vachuska42676812017-10-03 15:12:41 -0700573 pushRulesToDevice(device);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700574 } catch (Exception e) {
Ray Milkey31b00482019-02-07 08:06:28 -0800575 log.warn("Failed to process {}: {}", event, e.getMessage());
Madan Jampanic626f1e2015-05-29 13:53:38 -0700576 }
577 });
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800578 }
579 }
580
Thomas Vachuska924cda42015-09-22 12:11:27 -0700581 /**
582 * Entity for tracking stats for a packet processor.
583 */
584 private class ProcessorEntry implements PacketProcessorEntry {
585 private final PacketProcessor processor;
586 private final int priority;
587 private long invocations = 0;
588 private long nanos = 0;
589
590 public ProcessorEntry(PacketProcessor processor, int priority) {
591 this.processor = processor;
592 this.priority = priority;
593 }
594
595 @Override
596 public PacketProcessor processor() {
597 return processor;
598 }
599
600 @Override
601 public int priority() {
602 return priority;
603 }
604
605 @Override
606 public long invocations() {
607 return invocations;
608 }
609
610 @Override
611 public long totalNanos() {
612 return nanos;
613 }
614
615 @Override
616 public long averageNanos() {
617 return invocations > 0 ? nanos / invocations : 0;
618 }
619
620 void addNanos(long nanos) {
621 this.nanos += nanos;
622 this.invocations++;
623 }
624 }
alshabibae857582014-09-12 23:53:10 -0700625}