blob: 26c4102727e4e55a86a029bcc0b9a505a927802e [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;
61
62import static com.google.common.base.Preconditions.checkNotNull;
63import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoon541ef712015-05-23 17:18:34 +090064import static org.onosproject.security.AppGuard.checkPermission;
65
alshabib089bb772015-03-03 18:26:26 -080066
alshabib7674db42014-09-12 23:40:46 -070067/**
68 * Provides a basic implementation of the packet SB & NB APIs.
alshabib7674db42014-09-12 23:40:46 -070069 */
70@Component(immediate = true)
71@Service
tom202175a2014-09-19 19:00:11 -070072public class PacketManager
Thomas Vachuska6cba4952015-04-22 12:38:22 -070073 extends AbstractProviderRegistry<PacketProvider, PacketProviderService>
74 implements PacketService, PacketProviderRegistry {
alshabib7674db42014-09-12 23:40:46 -070075
76 private final Logger log = getLogger(getClass());
77
Jonathan Hart4f60f982014-10-27 08:11:17 -070078 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
79
alshabib7674db42014-09-12 23:40:46 -070080 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuska6cba4952015-04-22 12:38:22 -070081 private CoreService coreService;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib7674db42014-09-12 23:40:46 -070084 private DeviceService deviceService;
85
Jonathan Hart4f60f982014-10-27 08:11:17 -070086 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080087 private FlowRuleService flowService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart4f60f982014-10-27 08:11:17 -070090 private PacketStore store;
91
Thomas Vachuska866b46a2015-04-30 00:26:55 -070092 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 private FlowObjectiveService objectiveService;
94
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080095 private final DeviceListener deviceListener = new InternalDeviceListener();
96
Jonathan Hart4f60f982014-10-27 08:11:17 -070097 private final Map<Integer, PacketProcessor> processors = new ConcurrentHashMap<>();
alshabib7674db42014-09-12 23:40:46 -070098
Thomas Vachuska6cba4952015-04-22 12:38:22 -070099 private ApplicationId appId;
100
alshabib7674db42014-09-12 23:40:46 -0700101 @Activate
102 public void activate() {
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700103 appId = coreService.getAppId(CoreService.CORE_APP_NAME);
Jonathan Hart4f60f982014-10-27 08:11:17 -0700104 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800105 deviceService.addListener(deviceListener);
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700106 // TODO: Should we request packets for all existing devices? I believe we should.
alshabib7674db42014-09-12 23:40:46 -0700107 log.info("Started");
108 }
109
110 @Deactivate
111 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700112 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800113 deviceService.removeListener(deviceListener);
alshabib7674db42014-09-12 23:40:46 -0700114 log.info("Stopped");
115 }
116
117 @Override
118 public void addProcessor(PacketProcessor processor, int priority) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900119 checkPermission(Permission.PACKET_EVENT);
120
alshabib030111e2014-09-15 15:56:42 -0700121 checkNotNull(processor, "Processor cannot be null");
alshabibd58d3522014-09-13 17:14:53 -0700122 processors.put(priority, processor);
alshabib7674db42014-09-12 23:40:46 -0700123 }
124
125 @Override
126 public void removeProcessor(PacketProcessor processor) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900127 checkPermission(Permission.PACKET_EVENT);
128
tomc370ebd2014-09-16 01:25:21 -0700129 checkNotNull(processor, "Processor cannot be null");
alshabibd58d3522014-09-13 17:14:53 -0700130 processors.values().remove(processor);
alshabib7674db42014-09-12 23:40:46 -0700131 }
132
133 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800134 public void requestPackets(TrafficSelector selector, PacketPriority priority,
135 ApplicationId appId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900136 checkPermission(Permission.PACKET_READ);
137
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800138 checkNotNull(selector, "Selector cannot be null");
139 checkNotNull(appId, "Application ID cannot be null");
140
141 PacketRequest request =
alshabib42947782015-03-31 14:59:06 -0700142 new DefaultPacketRequest(selector, priority, appId, FlowRule.Type.DEFAULT);
Saurav Dasc313c402015-02-27 10:09:47 -0800143
alshabib42947782015-03-31 14:59:06 -0700144 if (store.requestPackets(request)) {
145 pushToAllDevices(request);
146 }
Saurav Dasc313c402015-02-27 10:09:47 -0800147 }
148
149 @Override
150 public void requestPackets(TrafficSelector selector, PacketPriority priority,
151 ApplicationId appId, FlowRule.Type tableType) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900152 checkPermission(Permission.PACKET_READ);
153
Saurav Dasc313c402015-02-27 10:09:47 -0800154 checkNotNull(selector, "Selector cannot be null");
155 checkNotNull(appId, "Application ID cannot be null");
156 checkNotNull(tableType, "Table Type cannot be null. For requesting packets +"
157 + "without table hints, use other methods in the packetService API");
158
159 PacketRequest request =
alshabib42947782015-03-31 14:59:06 -0700160 new DefaultPacketRequest(selector, priority, appId, tableType);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800161
alshabib42947782015-03-31 14:59:06 -0700162 if (store.requestPackets(request)) {
alshabib089bb772015-03-03 18:26:26 -0800163 pushToAllDevices(request);
164 }
alshabib42947782015-03-31 14:59:06 -0700165
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800166 }
167
168 /**
169 * Pushes a packet request flow rule to all devices.
170 *
171 * @param request the packet request
172 */
173 private void pushToAllDevices(PacketRequest request) {
174 for (Device device : deviceService.getDevices()) {
alshabib42947782015-03-31 14:59:06 -0700175 pushRule(device, request);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800176 }
177 }
178
179 /**
180 * Pushes flow rules to the device to request packets be sent to the
181 * controller.
182 *
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700183 * @param device the device to push the rules to
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800184 * @param request the packet request
185 */
186 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800187 // Everything is pre-provisioned on ROADMs
188 if (device.type().equals(Device.Type.ROADM)) {
189 return;
190 }
191
Jonathan Hart17d00452015-04-21 17:10:00 -0700192 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
193 .punt()
194 .build();
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800195
Jonathan Hart17d00452015-04-21 17:10:00 -0700196 ForwardingObjective forwarding = DefaultForwardingObjective.builder()
197 .withPriority(request.priority().priorityValue())
198 .withSelector(request.selector())
199 .fromApp(appId)
200 .withFlag(ForwardingObjective.Flag.VERSATILE)
201 .withTreatment(treatment)
202 .makePermanent()
203 .add(new ObjectiveContext() {
204 @Override
205 public void onSuccess(Objective objective) { }
206
207 @Override
208 public void onError(Objective objective, ObjectiveError error) {
Saurav Das3d038262015-04-23 12:36:58 -0700209 log.warn("Failed to install packet request {}: {}",
210 request, error);
Jonathan Hart17d00452015-04-21 17:10:00 -0700211 }
212 });
213
214 objectiveService.forward(device.id(), forwarding);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800215 }
216
217 @Override
alshabib7674db42014-09-12 23:40:46 -0700218 public void emit(OutboundPacket packet) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900219 checkPermission(Permission.PACKET_WRITE);
220
tomc370ebd2014-09-16 01:25:21 -0700221 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700222
223 store.emit(packet);
224 }
225
226 private void localEmit(OutboundPacket packet) {
alshabib7674db42014-09-12 23:40:46 -0700227 final Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800228
229 if (device == null) {
230 return;
231 }
232
alshabib7674db42014-09-12 23:40:46 -0700233 final PacketProvider packetProvider = getProvider(device.providerId());
Jonathan Hart7466d612014-11-24 17:09:53 -0800234
alshabib3d643ec2014-10-22 18:33:00 -0700235 if (packetProvider != null) {
236 packetProvider.emit(packet);
237 }
alshabib7674db42014-09-12 23:40:46 -0700238 }
239
240 @Override
tomc370ebd2014-09-16 01:25:21 -0700241 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700242 return new InternalPacketProviderService(provider);
243 }
244
245 // Personalized link provider service issued to the supplied provider.
246 private class InternalPacketProviderService
Thomas Vachuska6cba4952015-04-22 12:38:22 -0700247 extends AbstractProviderService<PacketProvider>
248 implements PacketProviderService {
alshabib7674db42014-09-12 23:40:46 -0700249
250 protected InternalPacketProviderService(PacketProvider provider) {
251 super(provider);
252 }
253
254 @Override
255 public void processPacket(PacketContext context) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800256 // TODO filter packets sent to processors based on registrations
alshabibd58d3522014-09-13 17:14:53 -0700257 for (PacketProcessor processor : processors.values()) {
alshabib7674db42014-09-12 23:40:46 -0700258 processor.process(context);
259 }
260 }
261
262 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700263
264 /**
265 * Internal callback from the packet store.
266 */
Thomas Vachuska866b46a2015-04-30 00:26:55 -0700267 private class InternalStoreDelegate implements PacketStoreDelegate {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700268 @Override
269 public void notify(PacketEvent event) {
270 localEmit(event.subject());
271 }
272 }
273
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800274 /**
275 * Internal listener for device service events.
276 */
277 private class InternalDeviceListener implements DeviceListener {
278 @Override
279 public void event(DeviceEvent event) {
280 Device device = event.subject();
sangho864a9db22015-04-28 12:06:31 -0700281 switch (event.type()) {
282 case DEVICE_ADDED:
283 case DEVICE_AVAILABILITY_CHANGED:
284 if (deviceService.isAvailable(event.subject().id())) {
285 for (PacketRequest request : store.existingRequests()) {
286 pushRule(device, request);
287 }
288 }
289 break;
290 default:
291 break;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800292 }
293 }
294 }
295
alshabibae857582014-09-12 23:53:10 -0700296}