blob: 28f1df0c164b9a3dda3eef09b86174dc0dc9eaff [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
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
alshabib7674db42014-09-12 23:40:46 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080024import org.onosproject.core.ApplicationId;
Thomas Vachuska6cba4952015-04-22 12:38:22 -070025import org.onosproject.core.CoreService;
Changhoon Yoon541ef712015-05-23 17:18:34 +090026import org.onosproject.core.Permission;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.net.Device;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080028import org.onosproject.net.device.DeviceEvent;
29import org.onosproject.net.device.DeviceListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.device.DeviceService;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080031import org.onosproject.net.flow.DefaultTrafficTreatment;
32import org.onosproject.net.flow.FlowRule;
33import org.onosproject.net.flow.FlowRuleService;
34import org.onosproject.net.flow.TrafficSelector;
35import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart17d00452015-04-21 17:10:00 -070036import org.onosproject.net.flowobjective.DefaultForwardingObjective;
37import org.onosproject.net.flowobjective.FlowObjectiveService;
38import org.onosproject.net.flowobjective.ForwardingObjective;
39import org.onosproject.net.flowobjective.Objective;
40import org.onosproject.net.flowobjective.ObjectiveContext;
41import org.onosproject.net.flowobjective.ObjectiveError;
alshabib42947782015-03-31 14:59:06 -070042import org.onosproject.net.packet.DefaultPacketRequest;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.packet.OutboundPacket;
44import org.onosproject.net.packet.PacketContext;
45import org.onosproject.net.packet.PacketEvent;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080046import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080047import org.onosproject.net.packet.PacketProcessor;
48import 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;
alshabib7674db42014-09-12 23:40:46 -070057import org.slf4j.Logger;
58
alshabib089bb772015-03-03 18:26:26 -080059import java.util.Map;
alshabib089bb772015-03-03 18:26:26 -080060import java.util.concurrent.ConcurrentHashMap;
Madan Jampanic626f1e2015-05-29 13:53:38 -070061import java.util.concurrent.ExecutorService;
62import java.util.concurrent.Executors;
alshabib089bb772015-03-03 18:26:26 -080063
64import static com.google.common.base.Preconditions.checkNotNull;
65import static org.slf4j.LoggerFactory.getLogger;
Madan Jampanic626f1e2015-05-29 13:53:38 -070066import static org.onlab.util.Tools.groupedThreads;
Changhoon Yoon541ef712015-05-23 17:18:34 +090067import static org.onosproject.security.AppGuard.checkPermission;
68
alshabib089bb772015-03-03 18:26:26 -080069
alshabib7674db42014-09-12 23:40:46 -070070/**
71 * Provides a basic implementation of the packet SB & NB APIs.
alshabib7674db42014-09-12 23:40:46 -070072 */
73@Component(immediate = true)
74@Service
tom202175a2014-09-19 19:00:11 -070075public class PacketManager
Thomas Vachuska6cba4952015-04-22 12:38:22 -070076 extends AbstractProviderRegistry<PacketProvider, PacketProviderService>
77 implements PacketService, PacketProviderRegistry {
alshabib7674db42014-09-12 23:40:46 -070078
79 private final Logger log = getLogger(getClass());
80
Jonathan Hart4f60f982014-10-27 08:11:17 -070081 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
82
alshabib7674db42014-09-12 23:40:46 -070083 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuska6cba4952015-04-22 12:38:22 -070084 private CoreService coreService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib7674db42014-09-12 23:40:46 -070087 private DeviceService deviceService;
88
Jonathan Hart4f60f982014-10-27 08:11:17 -070089 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080090 private FlowRuleService flowService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart4f60f982014-10-27 08:11:17 -070093 private PacketStore store;
94
Thomas Vachuska866b46a2015-04-30 00:26:55 -070095 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 private FlowObjectiveService objectiveService;
97
Madan Jampanic626f1e2015-05-29 13:53:38 -070098 private ExecutorService eventHandlingExecutor;
99
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800100 private final DeviceListener deviceListener = new InternalDeviceListener();
101
Jonathan Hart4f60f982014-10-27 08:11:17 -0700102 private final Map<Integer, PacketProcessor> processors = new ConcurrentHashMap<>();
alshabib7674db42014-09-12 23:40:46 -0700103
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700104 private ApplicationId appId;
105
alshabib7674db42014-09-12 23:40:46 -0700106 @Activate
107 public void activate() {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700108 eventHandlingExecutor = Executors.newSingleThreadExecutor(
109 groupedThreads("onos/net/packet", "event-handler"));
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700110 appId = coreService.getAppId(CoreService.CORE_APP_NAME);
Jonathan Hart4f60f982014-10-27 08:11:17 -0700111 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800112 deviceService.addListener(deviceListener);
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700113 // TODO: Should we request packets for all existing devices? I believe we should.
alshabib7674db42014-09-12 23:40:46 -0700114 log.info("Started");
115 }
116
117 @Deactivate
118 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700119 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800120 deviceService.removeListener(deviceListener);
Madan Jampanic626f1e2015-05-29 13:53:38 -0700121 eventHandlingExecutor.shutdown();
alshabib7674db42014-09-12 23:40:46 -0700122 log.info("Stopped");
123 }
124
125 @Override
126 public void addProcessor(PacketProcessor processor, int priority) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900127 checkPermission(Permission.PACKET_EVENT);
128
alshabib030111e2014-09-15 15:56:42 -0700129 checkNotNull(processor, "Processor cannot be null");
alshabibd58d3522014-09-13 17:14:53 -0700130 processors.put(priority, processor);
alshabib7674db42014-09-12 23:40:46 -0700131 }
132
133 @Override
134 public void removeProcessor(PacketProcessor processor) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900135 checkPermission(Permission.PACKET_EVENT);
136
tomc370ebd2014-09-16 01:25:21 -0700137 checkNotNull(processor, "Processor cannot be null");
alshabibd58d3522014-09-13 17:14:53 -0700138 processors.values().remove(processor);
alshabib7674db42014-09-12 23:40:46 -0700139 }
140
141 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800142 public void requestPackets(TrafficSelector selector, PacketPriority priority,
143 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900144 checkPermission(Permission.PACKET_READ);
145
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800146 checkNotNull(selector, "Selector cannot be null");
147 checkNotNull(appId, "Application ID cannot be null");
148
149 PacketRequest request =
alshabib42947782015-03-31 14:59:06 -0700150 new DefaultPacketRequest(selector, priority, appId, FlowRule.Type.DEFAULT);
Saurav Dasc313c402015-02-27 10:09:47 -0800151
alshabib42947782015-03-31 14:59:06 -0700152 if (store.requestPackets(request)) {
153 pushToAllDevices(request);
154 }
Saurav Dasc313c402015-02-27 10:09:47 -0800155 }
156
157 @Override
158 public void requestPackets(TrafficSelector selector, PacketPriority priority,
159 ApplicationId appId, FlowRule.Type tableType) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900160 checkPermission(Permission.PACKET_READ);
161
Saurav Dasc313c402015-02-27 10:09:47 -0800162 checkNotNull(selector, "Selector cannot be null");
163 checkNotNull(appId, "Application ID cannot be null");
164 checkNotNull(tableType, "Table Type cannot be null. For requesting packets +"
165 + "without table hints, use other methods in the packetService API");
166
167 PacketRequest request =
alshabib42947782015-03-31 14:59:06 -0700168 new DefaultPacketRequest(selector, priority, appId, tableType);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800169
alshabib42947782015-03-31 14:59:06 -0700170 if (store.requestPackets(request)) {
alshabib089bb772015-03-03 18:26:26 -0800171 pushToAllDevices(request);
172 }
alshabib42947782015-03-31 14:59:06 -0700173
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800174 }
175
176 /**
177 * Pushes a packet request flow rule to all devices.
178 *
179 * @param request the packet request
180 */
181 private void pushToAllDevices(PacketRequest request) {
182 for (Device device : deviceService.getDevices()) {
alshabib42947782015-03-31 14:59:06 -0700183 pushRule(device, request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800184 }
185 }
186
187 /**
188 * Pushes flow rules to the device to request packets be sent to the
189 * controller.
190 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700191 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800192 * @param request the packet request
193 */
194 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800195 // Everything is pre-provisioned on ROADMs
196 if (device.type().equals(Device.Type.ROADM)) {
197 return;
198 }
199
Jonathan Hart17d00452015-04-21 17:10:00 -0700200 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
201 .punt()
202 .build();
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800203
Jonathan Hart17d00452015-04-21 17:10:00 -0700204 ForwardingObjective forwarding = DefaultForwardingObjective.builder()
205 .withPriority(request.priority().priorityValue())
206 .withSelector(request.selector())
207 .fromApp(appId)
208 .withFlag(ForwardingObjective.Flag.VERSATILE)
209 .withTreatment(treatment)
210 .makePermanent()
211 .add(new ObjectiveContext() {
212 @Override
213 public void onSuccess(Objective objective) { }
214
215 @Override
216 public void onError(Objective objective, ObjectiveError error) {
Saurav Das3d038262015-04-23 12:36:58 -0700217 log.warn("Failed to install packet request {}: {}",
218 request, error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700219 }
220 });
221
222 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800223 }
224
225 @Override
alshabib7674db42014-09-12 23:40:46 -0700226 public void emit(OutboundPacket packet) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900227 checkPermission(Permission.PACKET_WRITE);
228
tomc370ebd2014-09-16 01:25:21 -0700229 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700230
231 store.emit(packet);
232 }
233
234 private void localEmit(OutboundPacket packet) {
alshabib7674db42014-09-12 23:40:46 -0700235 final Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800236
237 if (device == null) {
238 return;
239 }
240
alshabib7674db42014-09-12 23:40:46 -0700241 final PacketProvider packetProvider = getProvider(device.providerId());
Jonathan Hart7466d612014-11-24 17:09:53 -0800242
alshabib3d643ec2014-10-22 18:33:00 -0700243 if (packetProvider != null) {
244 packetProvider.emit(packet);
245 }
alshabib7674db42014-09-12 23:40:46 -0700246 }
247
248 @Override
tomc370ebd2014-09-16 01:25:21 -0700249 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700250 return new InternalPacketProviderService(provider);
251 }
252
253 // Personalized link provider service issued to the supplied provider.
254 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700255 extends AbstractProviderService<PacketProvider>
256 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700257
258 protected InternalPacketProviderService(PacketProvider provider) {
259 super(provider);
260 }
261
262 @Override
263 public void processPacket(PacketContext context) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800264 // TODO filter packets sent to processors based on registrations
alshabibd58d3522014-09-13 17:14:53 -0700265 for (PacketProcessor processor : processors.values()) {
alshabib7674db42014-09-12 23:40:46 -0700266 processor.process(context);
267 }
268 }
269
270 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700271
272 /**
273 * Internal callback from the packet store.
274 */
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700275 private class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700276 @Override
277 public void notify(PacketEvent event) {
278 localEmit(event.subject());
279 }
280 }
281
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800282 /**
283 * Internal listener for device service events.
284 */
285 private class InternalDeviceListener implements DeviceListener {
286 @Override
287 public void event(DeviceEvent event) {
Madan Jampanic626f1e2015-05-29 13:53:38 -0700288 eventHandlingExecutor.execute(() -> {
289 try {
290 Device device = event.subject();
291 switch (event.type()) {
292 case DEVICE_ADDED:
293 case DEVICE_AVAILABILITY_CHANGED:
294 if (deviceService.isAvailable(event.subject().id())) {
295 for (PacketRequest request : store.existingRequests()) {
296 pushRule(device, request);
297 }
sangho864a9db22015-04-28 12:06:31 -0700298 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700299 break;
300 default:
301 break;
sangho864a9db22015-04-28 12:06:31 -0700302 }
Madan Jampanic626f1e2015-05-29 13:53:38 -0700303 } catch (Exception e) {
304 log.warn("Failed to process {}", event, e);
305 }
306 });
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800307 }
308 }
309
alshabibae857582014-09-12 23:53:10 -0700310}