blob: 89086014690ee6c6ec963e470e8f4c737195608a [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
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;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.net.Device;
alshabib089bb772015-03-03 18:26:26 -080026import org.onosproject.net.MastershipRole;
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;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080030import org.onosproject.net.flow.DefaultFlowRule;
31import 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;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.packet.OutboundPacket;
37import org.onosproject.net.packet.PacketContext;
38import org.onosproject.net.packet.PacketEvent;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080039import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.packet.PacketProcessor;
41import org.onosproject.net.packet.PacketProvider;
42import org.onosproject.net.packet.PacketProviderRegistry;
43import org.onosproject.net.packet.PacketProviderService;
44import org.onosproject.net.packet.PacketService;
45import org.onosproject.net.packet.PacketStore;
46import org.onosproject.net.packet.PacketStoreDelegate;
47import org.onosproject.net.provider.AbstractProviderRegistry;
48import org.onosproject.net.provider.AbstractProviderService;
alshabib7674db42014-09-12 23:40:46 -070049import org.slf4j.Logger;
50
alshabib089bb772015-03-03 18:26:26 -080051import java.util.Collections;
52import java.util.Map;
53import java.util.Set;
54import java.util.concurrent.ConcurrentHashMap;
55
56import static com.google.common.base.Preconditions.checkNotNull;
57import static org.slf4j.LoggerFactory.getLogger;
58
alshabib7674db42014-09-12 23:40:46 -070059/**
60 * Provides a basic implementation of the packet SB & NB APIs.
alshabib7674db42014-09-12 23:40:46 -070061 */
62@Component(immediate = true)
63@Service
tom202175a2014-09-19 19:00:11 -070064public class PacketManager
alshabib7674db42014-09-12 23:40:46 -070065extends AbstractProviderRegistry<PacketProvider, PacketProviderService>
66implements PacketService, PacketProviderRegistry {
67
68 private final Logger log = getLogger(getClass());
69
Jonathan Hart4f60f982014-10-27 08:11:17 -070070 private final PacketStoreDelegate delegate = new InternalStoreDelegate();
71
alshabib7674db42014-09-12 23:40:46 -070072 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 private DeviceService deviceService;
74
Jonathan Hart4f60f982014-10-27 08:11:17 -070075 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080076 private FlowRuleService flowService;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart4f60f982014-10-27 08:11:17 -070079 private PacketStore store;
80
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080081 private final DeviceListener deviceListener = new InternalDeviceListener();
82
Jonathan Hart4f60f982014-10-27 08:11:17 -070083 private final Map<Integer, PacketProcessor> processors = new ConcurrentHashMap<>();
alshabib7674db42014-09-12 23:40:46 -070084
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080085 private Set<PacketRequest> packetRequests =
86 Collections.newSetFromMap(new ConcurrentHashMap<>());
87
88 private final class PacketRequest {
89 private final TrafficSelector selector;
90 private final PacketPriority priority;
91 private final ApplicationId appId;
Saurav Dasc313c402015-02-27 10:09:47 -080092 private final FlowRule.Type tableType;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080093
94 public PacketRequest(TrafficSelector selector, PacketPriority priority,
Saurav Dasc313c402015-02-27 10:09:47 -080095 ApplicationId appId, FlowRule.Type tableType) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080096 this.selector = selector;
97 this.priority = priority;
98 this.appId = appId;
Saurav Dasc313c402015-02-27 10:09:47 -080099 this.tableType = tableType;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800100 }
101
102 public TrafficSelector selector() {
103 return selector;
104 }
105
106 public PacketPriority priority() {
107 return priority;
108 }
109
110 public ApplicationId appId() {
111 return appId;
112 }
113
Saurav Dasc313c402015-02-27 10:09:47 -0800114 public FlowRule.Type tableType() {
115 return tableType;
116 }
117
alshabib78baaf22015-02-18 18:55:45 -0800118 @Override
119 public boolean equals(Object o) {
120 if (this == o) {
121 return true;
122 }
123 if (o == null || getClass() != o.getClass()) {
124 return false;
125 }
126
127 PacketRequest that = (PacketRequest) o;
128
129 if (priority != that.priority) {
130 return false;
131 }
132 if (!selector.equals(that.selector)) {
133 return false;
134 }
135
136 return true;
137 }
138
139 @Override
140 public int hashCode() {
141 int result = selector.hashCode();
142 result = 31 * result + priority.hashCode();
143 return result;
144 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800145 }
146
alshabib7674db42014-09-12 23:40:46 -0700147 @Activate
148 public void activate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700149 store.setDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800150 deviceService.addListener(deviceListener);
alshabib7674db42014-09-12 23:40:46 -0700151 log.info("Started");
152 }
153
154 @Deactivate
155 public void deactivate() {
Jonathan Hart4f60f982014-10-27 08:11:17 -0700156 store.unsetDelegate(delegate);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800157 deviceService.removeListener(deviceListener);
alshabib7674db42014-09-12 23:40:46 -0700158 log.info("Stopped");
159 }
160
161 @Override
162 public void addProcessor(PacketProcessor processor, int priority) {
alshabib030111e2014-09-15 15:56:42 -0700163 checkNotNull(processor, "Processor cannot be null");
alshabibd58d3522014-09-13 17:14:53 -0700164 processors.put(priority, processor);
alshabib7674db42014-09-12 23:40:46 -0700165 }
166
167 @Override
168 public void removeProcessor(PacketProcessor processor) {
tomc370ebd2014-09-16 01:25:21 -0700169 checkNotNull(processor, "Processor cannot be null");
alshabibd58d3522014-09-13 17:14:53 -0700170 processors.values().remove(processor);
alshabib7674db42014-09-12 23:40:46 -0700171 }
172
173 @Override
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800174 public void requestPackets(TrafficSelector selector, PacketPriority priority,
175 ApplicationId appId) {
176 checkNotNull(selector, "Selector cannot be null");
177 checkNotNull(appId, "Application ID cannot be null");
178
179 PacketRequest request =
Saurav Dasc313c402015-02-27 10:09:47 -0800180 new PacketRequest(selector, priority, appId, FlowRule.Type.DEFAULT);
181
182 packetRequests.add(request);
183 pushToAllDevices(request);
184 }
185
186 @Override
187 public void requestPackets(TrafficSelector selector, PacketPriority priority,
188 ApplicationId appId, FlowRule.Type tableType) {
189 checkNotNull(selector, "Selector cannot be null");
190 checkNotNull(appId, "Application ID cannot be null");
191 checkNotNull(tableType, "Table Type cannot be null. For requesting packets +"
192 + "without table hints, use other methods in the packetService API");
193
194 PacketRequest request =
195 new PacketRequest(selector, priority, appId, tableType);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800196
alshabib089bb772015-03-03 18:26:26 -0800197 if (packetRequests.add(request)) {
198 pushToAllDevices(request);
199 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800200 }
201
202 /**
203 * Pushes a packet request flow rule to all devices.
204 *
205 * @param request the packet request
206 */
207 private void pushToAllDevices(PacketRequest request) {
208 for (Device device : deviceService.getDevices()) {
alshabib089bb772015-03-03 18:26:26 -0800209 if (deviceService.getRole(device.id()) == MastershipRole.MASTER) {
210 pushRule(device, request);
211 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800212 }
213 }
214
215 /**
216 * Pushes flow rules to the device to request packets be sent to the
217 * controller.
218 *
219 * @param device the device to push the rules to
220 * @param request the packet request
221 */
222 private void pushRule(Device device, PacketRequest request) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800223 // Everything is pre-provisioned on ROADMs
224 if (device.type().equals(Device.Type.ROADM)) {
225 return;
226 }
227
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800228 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
229 .punt()
230 .build();
231
232 FlowRule flow = new DefaultFlowRule(device.id(),
233 request.selector(),
234 treatment,
235 request.priority().priorityValue(),
236 request.appId(),
Saurav Dasc313c402015-02-27 10:09:47 -0800237 0, true, request.tableType());
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800238
239 flowService.applyFlowRules(flow);
240 }
241
242 @Override
alshabib7674db42014-09-12 23:40:46 -0700243 public void emit(OutboundPacket packet) {
tomc370ebd2014-09-16 01:25:21 -0700244 checkNotNull(packet, "Packet cannot be null");
Jonathan Hart4f60f982014-10-27 08:11:17 -0700245
246 store.emit(packet);
247 }
248
249 private void localEmit(OutboundPacket packet) {
alshabib7674db42014-09-12 23:40:46 -0700250 final Device device = deviceService.getDevice(packet.sendThrough());
Jonathan Hart7466d612014-11-24 17:09:53 -0800251
252 if (device == null) {
253 return;
254 }
255
alshabib7674db42014-09-12 23:40:46 -0700256 final PacketProvider packetProvider = getProvider(device.providerId());
Jonathan Hart7466d612014-11-24 17:09:53 -0800257
alshabib3d643ec2014-10-22 18:33:00 -0700258 if (packetProvider != null) {
259 packetProvider.emit(packet);
260 }
alshabib7674db42014-09-12 23:40:46 -0700261 }
262
263 @Override
tomc370ebd2014-09-16 01:25:21 -0700264 protected PacketProviderService createProviderService(PacketProvider provider) {
alshabib7674db42014-09-12 23:40:46 -0700265 return new InternalPacketProviderService(provider);
266 }
267
268 // Personalized link provider service issued to the supplied provider.
269 private class InternalPacketProviderService
270 extends AbstractProviderService<PacketProvider>
271 implements PacketProviderService {
272
273 protected InternalPacketProviderService(PacketProvider provider) {
274 super(provider);
275 }
276
277 @Override
278 public void processPacket(PacketContext context) {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800279 // TODO filter packets sent to processors based on registrations
alshabibd58d3522014-09-13 17:14:53 -0700280 for (PacketProcessor processor : processors.values()) {
alshabib7674db42014-09-12 23:40:46 -0700281 processor.process(context);
282 }
283 }
284
285 }
Jonathan Hart4f60f982014-10-27 08:11:17 -0700286
287 /**
288 * Internal callback from the packet store.
289 */
290 private class InternalStoreDelegate
291 implements PacketStoreDelegate {
292 @Override
293 public void notify(PacketEvent event) {
294 localEmit(event.subject());
295 }
296 }
297
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800298 /**
299 * Internal listener for device service events.
300 */
301 private class InternalDeviceListener implements DeviceListener {
302 @Override
303 public void event(DeviceEvent event) {
304 Device device = event.subject();
305 if (event.type() == DeviceEvent.Type.DEVICE_ADDED) {
306 for (PacketRequest request : packetRequests) {
307 pushRule(device, request);
308 }
309 }
310 }
311 }
312
alshabibae857582014-09-12 23:53:10 -0700313}