blob: a020da7a1f2bb34619df822e58ca3c23c933c390 [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 }
288
Thomas Vachuska924cda42015-09-22 12:11:27 -0700289 }
290 }
291
292 /**
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800293 * Pushes a packet request flow rule to all devices.
294 *
295 * @param request the packet request
296 */
297 private void pushToAllDevices(PacketRequest request) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700298 log.debug("Pushing packet request {} to all devices", request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800299 for (Device device : deviceService.getDevices()) {
Thomas Vachuskab73ca6d2018-12-13 10:08:00 -0800300 try {
301 Driver driver = driverService.getDriver(device.id());
302 if (driver != null &&
303 Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
304 pushRule(device, request);
305 }
306 } catch (ItemNotFoundException e) {
307 log.warn("Device driver not found for {}; not processing packet request {}",
308 device.id(), request);
Yuta HIGUCHIe4cb8cf2017-05-01 22:18:28 -0700309 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800310 }
311 }
312
313 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700314 * Removes packet request flow rule from all devices.
315 *
316 * @param request the packet request
317 */
318 private void removeFromAllDevices(PacketRequest request) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700319 deviceService.getAvailableDevices().forEach(d -> removeRule(d, request));
Thomas Vachuska27bee092015-06-23 19:03:10 -0700320 }
321
322 /**
323 * Pushes packet intercept flow rules to the device.
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800324 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700325 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800326 * @param request the packet request
327 */
328 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700329 if (!device.type().equals(Device.Type.SWITCH)) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800330 return;
331 }
332
Carmelo Cascone0761cd32018-08-29 19:22:50 -0700333 if (!deviceService.isAvailable(device.id())) {
334 return;
335 }
336
Thomas Vachuska27bee092015-06-23 19:03:10 -0700337 ForwardingObjective forwarding = createBuilder(request)
Jonathan Hart17d00452015-04-21 17:10:00 -0700338 .add(new ObjectiveContext() {
339 @Override
Jonathan Hart17d00452015-04-21 17:10:00 -0700340 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700341 log.warn("Failed to install packet request {} to {}: {}",
342 request, device.id(), error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700343 }
344 });
345
346 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800347 }
348
Thomas Vachuska27bee092015-06-23 19:03:10 -0700349 /**
350 * Removes packet intercept flow rules from the device.
351 *
352 * @param device the device to remove the rules deom
353 * @param request the packet request
354 */
355 private void removeRule(Device device, PacketRequest request) {
Marc De Leenheerb9311372015-07-09 11:36:49 -0700356 if (!device.type().equals(Device.Type.SWITCH)) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700357 return;
358 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700359 ForwardingObjective forwarding = createBuilder(request)
360 .remove(new ObjectiveContext() {
361 @Override
362 public void onError(Objective objective, ObjectiveError error) {
Thomas Vachuska88fd6902015-08-04 10:08:34 -0700363 log.warn("Failed to withdraw packet request {} from {}: {}",
364 request, device.id(), error);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700365 }
366 });
Thomas Vachuska27bee092015-06-23 19:03:10 -0700367 objectiveService.forward(device.id(), forwarding);
368 }
369
370 private DefaultForwardingObjective.Builder createBuilder(PacketRequest request) {
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000371 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
372 .punt()
373 .wipeDeferred()
374 .build();
Charles Chan874900e2016-12-09 16:55:39 -0800375
Thomas Vachuska27bee092015-06-23 19:03:10 -0700376 return DefaultForwardingObjective.builder()
377 .withPriority(request.priority().priorityValue())
378 .withSelector(request.selector())
Ray Milkeyd1751942018-11-13 13:32:10 -0800379 .fromApp(appId)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700380 .withFlag(ForwardingObjective.Flag.VERSATILE)
Pier Luigi Ventre6fd1ca92017-01-13 03:15:50 +0000381 .withTreatment(treatment)
Thomas Vachuska27bee092015-06-23 19:03:10 -0700382 .makePermanent();
383 }
384
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800385 @Override
alshabib7674db42014-09-12 23:40:46 -0700386 public void emit(OutboundPacket packet) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900387 checkPermission(PACKET_WRITE);
tomc370ebd2014-09-16 01:25:21 -0700388 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700389 store.emit(packet);
390 }
391
Harshada Chaundkardcd1b142019-03-25 17:27:44 -0400392 @Override
393 public List<PacketInFilter> getFilters() {
394 return ImmutableList.copyOf(filters);
395 }
396
397 @Override
398 public void clearFilters() {
399 for (PacketInFilter filter: filters) {
400 filter.stop();
401 }
402 filters.clear();
403 }
404
Jonathan Hart4f60f982014-10-27 08:11:17 -0700405 private void localEmit(OutboundPacket packet) {
Thomas Vachuska924cda42015-09-22 12:11:27 -0700406 Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800407 if (device == null) {
408 return;
409 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700410 PacketProvider packetProvider = getProvider(device.providerId());
alshabib3d643ec2014-10-22 18:33:00 -0700411 if (packetProvider != null) {
412 packetProvider.emit(packet);
413 }
alshabib7674db42014-09-12 23:40:46 -0700414 }
415
416 @Override
tomc370ebd2014-09-16 01:25:21 -0700417 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700418 return new InternalPacketProviderService(provider);
419 }
420
Thomas Vachuska924cda42015-09-22 12:11:27 -0700421 /**
422 * Personalized packet provider service issued to the supplied provider.
423 */
alshabib7674db42014-09-12 23:40:46 -0700424 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700425 extends AbstractProviderService<PacketProvider>
426 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700427
428 protected InternalPacketProviderService(PacketProvider provider) {
429 super(provider);
430 }
431
Harshada Chaundkardcd1b142019-03-25 17:27:44 -0400432 /**
433 * Loops through all packet filters and checks if the filter is
434 * enabled and allowed to be processed.
435 * It increments the counter to track the pending packets to be
436 * processed based on the filter selected.
437 *
438 * @param context PackerContext holding the packet information
439 * @return FilterAction Action decided for the based on the filter applied
440 */
441 private FilterAction prePacketProcess(PacketContext context) {
442 FilterAction filterAction = FilterAction.FILTER_INVALID;
443 for (PacketInFilter filter: filters) {
444 filterAction = filter.preProcess(context);
445 if (filterAction == FilterAction.FILTER_DISABLED) {
446 if (log.isTraceEnabled()) {
447 log.trace("{}: filter is disabled during pre processing", filter.name());
448 }
449 continue;
450 }
451 if (filterAction == FilterAction.PACKET_DENY) {
452 if (log.isTraceEnabled()) {
453 log.trace("{}: overflow counter after dropping packet is: {}", filter.name(),
454 filter.droppedPackets());
455 }
456 break;
457 }
458 if (filterAction == FilterAction.PACKET_ALLOW) {
459 if (log.isTraceEnabled()) {
460 log.trace("{}: counter after picked for processing is: {}", filter.name(),
461 filter.pendingPackets());
462 }
463 break;
464 }
465 }
466 return filterAction;
467 }
468
alshabib7674db42014-09-12 23:40:46 -0700469 @Override
470 public void processPacket(PacketContext context) {
Harshada Chaundkardcd1b142019-03-25 17:27:44 -0400471 FilterAction filterAction = prePacketProcess(context);
472
473 if (filterAction == FilterAction.PACKET_DENY) {
474 if (log.isTraceEnabled()) {
475 log.trace("The packet is dropped as crossed the maxcount");
476 }
477 return;
478 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800479 // TODO filter packets sent to processors based on registrations
Thomas Vachuska924cda42015-09-22 12:11:27 -0700480 for (ProcessorEntry entry : processors) {
Jonathan Hartf5638302015-11-16 10:56:20 -0800481 try {
Jonathan Hart34a14f72018-01-25 09:34:33 -0800482 if (log.isTraceEnabled()) {
483 log.trace("Starting packet processing by {}",
484 entry.processor().getClass().getName());
485 }
486
Jonathan Hartf5638302015-11-16 10:56:20 -0800487 long start = System.nanoTime();
488 entry.processor().process(context);
489 entry.addNanos(System.nanoTime() - start);
Jonathan Hart34a14f72018-01-25 09:34:33 -0800490
491 if (log.isTraceEnabled()) {
492 log.trace("Finished packet processing by {}",
493 entry.processor().getClass().getName());
494 }
Jonathan Hartf5638302015-11-16 10:56:20 -0800495 } catch (Exception e) {
496 log.warn("Packet processor {} threw an exception", entry.processor(), e);
497 }
alshabib7674db42014-09-12 23:40:46 -0700498 }
499 }
500
501 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700502
alshabib19e2cea2015-12-07 11:31:49 -0800503
Jonathan Hart4f60f982014-10-27 08:11:17 -0700504 /**
505 * Internal callback from the packet store.
506 */
Andrea Campanella5b240532016-02-05 09:44:41 -0800507 protected class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700508 @Override
509 public void notify(PacketEvent event) {
510 localEmit(event.subject());
511 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700512
513 @Override
514 public void requestPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800515 DeviceId deviceid = request.deviceId().orElse(null);
516
517 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900518 Device device = deviceService.getDevice(deviceid);
519
520 if (device != null) {
521 pushRule(deviceService.getDevice(deviceid), request);
522 }
alshabib19e2cea2015-12-07 11:31:49 -0800523 } else {
524 pushToAllDevices(request);
525 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700526 }
527
528 @Override
529 public void cancelPackets(PacketRequest request) {
alshabib19e2cea2015-12-07 11:31:49 -0800530 DeviceId deviceid = request.deviceId().orElse(null);
531
532 if (deviceid != null) {
hyunho198657770642017-05-30 14:50:35 +0900533 Device device = deviceService.getDevice(deviceid);
534
535 if (device != null) {
536 removeRule(deviceService.getDevice(deviceid), request);
537 }
alshabib19e2cea2015-12-07 11:31:49 -0800538 } else {
539 removeFromAllDevices(request);
540 }
Brian O'Connor21b028e2015-10-08 22:50:02 -0700541 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700542 }
543
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800544 /**
545 * Internal listener for device service events.
546 */
547 private class InternalDeviceListener implements DeviceListener {
Thomas Vachuska42676812017-10-03 15:12:41 -0700548
549 @Override
550 public boolean isRelevant(DeviceEvent event) {
551 return event.type() == DeviceEvent.Type.DEVICE_ADDED ||
552 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
553 }
554
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800555 @Override
556 public void event(DeviceEvent event) {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700557 eventHandlingExecutor.execute(() -> {
558 try {
Ray Milkeyfa89f2a2017-11-30 13:52:54 -0800559 if (driverService == null) {
560 // Event came in after the driver service shut down, nothing to be done
561 return;
562 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700563 Device device = event.subject();
Yi Tseng809b5d72017-08-16 14:00:37 -0700564 Driver driver = driverService.getDriver(device.id());
565 if (driver == null) {
566 return;
567 }
568 if (!Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
569 return;
570 }
571 if (!deviceService.isAvailable(event.subject().id())) {
572 return;
573 }
Thomas Vachuska42676812017-10-03 15:12:41 -0700574 pushRulesToDevice(device);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700575 } catch (Exception e) {
Ray Milkey31b00482019-02-07 08:06:28 -0800576 log.warn("Failed to process {}: {}", event, e.getMessage());
Madan Jampanic626f1e2015-05-29 13:53:38 -0700577 }
578 });
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800579 }
580 }
581
Thomas Vachuska924cda42015-09-22 12:11:27 -0700582 /**
583 * Entity for tracking stats for a packet processor.
584 */
585 private class ProcessorEntry implements PacketProcessorEntry {
586 private final PacketProcessor processor;
587 private final int priority;
588 private long invocations = 0;
589 private long nanos = 0;
590
591 public ProcessorEntry(PacketProcessor processor, int priority) {
592 this.processor = processor;
593 this.priority = priority;
594 }
595
596 @Override
597 public PacketProcessor processor() {
598 return processor;
599 }
600
601 @Override
602 public int priority() {
603 return priority;
604 }
605
606 @Override
607 public long invocations() {
608 return invocations;
609 }
610
611 @Override
612 public long totalNanos() {
613 return nanos;
614 }
615
616 @Override
617 public long averageNanos() {
618 return invocations > 0 ? nanos / invocations : 0;
619 }
620
621 void addNanos(long nanos) {
622 this.nanos += nanos;
623 this.invocations++;
624 }
625 }
alshabibae857582014-09-12 23:53:10 -0700626}