blob: 21dd06a216dd0b83c8267df41822127ec606179e [file] [log] [blame]
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +02001/*
2 * Copyright 2016-present 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 */
16
17package org.onosproject.sdxl2;
18
19
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
24import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Deactivate;
pierventrebbb2e362016-06-26 19:42:48 +020026import org.onlab.packet.Ethernet;
27import org.onlab.packet.ICMP6;
28import org.onlab.packet.IPv6;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020029import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
pierventre1483e642016-06-08 18:52:29 +020031import org.onosproject.net.ConnectPoint;
pierventrebbb2e362016-06-26 19:42:48 +020032import org.onosproject.net.DeviceId;
pierventre1483e642016-06-08 18:52:29 +020033import org.onosproject.net.edge.EdgePortService;
pierventrebbb2e362016-06-26 19:42:48 +020034import org.onosproject.net.flow.DefaultTrafficSelector;
35import org.onosproject.net.flow.TrafficSelector;
pierventre1483e642016-06-08 18:52:29 +020036import org.onosproject.net.intent.IntentService;
37import org.onosproject.net.intent.Key;
pierventrebbb2e362016-06-26 19:42:48 +020038import org.onosproject.net.packet.InboundPacket;
39import org.onosproject.net.packet.PacketContext;
40import org.onosproject.net.packet.PacketProcessor;
41import org.onosproject.net.packet.PacketService;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020042import org.osgi.service.component.ComponentContext;
43import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
pierventre3849e562016-05-11 11:47:32 +020045
46import java.util.Collections;
47import java.util.Optional;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020048import java.util.Set;
49
50import static com.google.common.base.Preconditions.checkNotNull;
51import static com.google.common.base.Preconditions.checkState;
pierventrebbb2e362016-06-26 19:42:48 +020052import static org.onlab.packet.Ethernet.TYPE_ARP;
53import static org.onlab.packet.Ethernet.TYPE_IPV6;
54import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
55import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
56import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
57import static org.onosproject.net.packet.PacketPriority.CONTROL;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020058
59/**
pierventre3849e562016-05-11 11:47:32 +020060 * Implementation of the SdxL2Service.
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020061 */
62@Component(immediate = true)
63@Service
64public class SdxL2Manager implements SdxL2Service {
65
66 private static final String SDXL2_APP = "org.onosproject.sdxl2";
67 private static Logger log = LoggerFactory.getLogger(SdxL2Manager.class);
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected SdxL2Store sdxL2Store;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected CoreService coreService;
74
pierventre1483e642016-06-08 18:52:29 +020075 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected IntentService intentService;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected EdgePortService edgePortService;
80
pierventrebbb2e362016-06-26 19:42:48 +020081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected PacketService packetService;
83
84 protected SdxL2Processor processor = new SdxL2Processor();
85
86 protected SdxL2ArpNdpHandler arpndpHandler;
87
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020088 protected ApplicationId appId;
89
pierventre1483e642016-06-08 18:52:29 +020090 protected SdxL2MonitoringService monitoringManager;
91
pierventrebbb2e362016-06-26 19:42:48 +020092 protected String vcType = "MAC";
93
94
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020095 @Activate
96 protected void activate(ComponentContext context) {
97 appId = coreService.registerApplication(SDXL2_APP);
pierventre1483e642016-06-08 18:52:29 +020098 monitoringManager = new SdxL2MonitoringManager(appId, intentService, edgePortService);
pierventrebbb2e362016-06-26 19:42:48 +020099 handleArpNdp();
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200100 log.info("Started");
101 }
102
pierventrebbb2e362016-06-26 19:42:48 +0200103
104
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200105 @Deactivate
106 protected void deactivate() {
pierventre1483e642016-06-08 18:52:29 +0200107 this.cleanSdxL2();
pierventrebbb2e362016-06-26 19:42:48 +0200108 unhandleArpNdp();
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200109 log.info("Stopped");
110 }
111
112 /**
pierventre3849e562016-05-11 11:47:32 +0200113 * Creates a named SDX-L2.
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200114 *
pierventre3849e562016-05-11 11:47:32 +0200115 * @param sdxl2 SDX-L2 name
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200116 */
117 @Override
118 public void createSdxL2(String sdxl2) {
pierventre3849e562016-05-11 11:47:32 +0200119
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200120 checkNotNull(sdxl2, "sdxl2 name cannot be null");
121 checkState(!sdxl2.contains(","), "sdxl2 names cannot contain commas");
122 checkState(!sdxl2.contains("|"), "sdxl2 names cannot contain pipe");
123 checkState(!sdxl2.contains("-"), "sdxl2 names cannot contain dash");
124 checkState(!sdxl2.contains(":"), "sdxl2 names cannot contain colon");
125
126 try {
127 this.sdxL2Store.putSdxL2(sdxl2);
128 } catch (SdxL2Exception e) {
pierventre3849e562016-05-11 11:47:32 +0200129 log.info(e.getMessage());
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200130 }
131
132 }
133
134 /**
pierventre3849e562016-05-11 11:47:32 +0200135 * Deletes a named SDX-L2.
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200136 *
pierventre3849e562016-05-11 11:47:32 +0200137 * @param sdxl2 SDX-L2 name
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200138 */
139 @Override
140 public void deleteSdxL2(String sdxl2) {
pierventre3849e562016-05-11 11:47:32 +0200141
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200142 checkNotNull(sdxl2, "sdxl2 name cannot be null");
143
144 try {
145 this.sdxL2Store.removeSdxL2(sdxl2);
146 } catch (SdxL2Exception e) {
pierventre3849e562016-05-11 11:47:32 +0200147 log.info(e.getMessage());
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200148 }
149
150 }
151
152 /**
pierventre3849e562016-05-11 11:47:32 +0200153 * Returns a set of SDX-L2 names.
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200154 *
pierventre3849e562016-05-11 11:47:32 +0200155 * @return a set of SDX-L2 names
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200156 */
157 @Override
158 public Set<String> getSdxL2s() {
159 return this.sdxL2Store.getSdxL2s();
160 }
161
pierventre3849e562016-05-11 11:47:32 +0200162 /**
163 * Adds an SDX-L2 connection point to an SDX-L2.
164 *
165 * @param sdxl2 SDX-L2 name
166 * @param sdxl2cp SDX-L2 connection point object
167 */
168 @Override
169 public void addSdxL2ConnectionPoint(String sdxl2, SdxL2ConnectionPoint sdxl2cp) {
170
171 checkNotNull(sdxl2, "sdxl2 name cannot be null");
172 checkNotNull(sdxl2cp, "SdxL2ConnectionPoint cannot be null");
173
174 try {
175 this.sdxL2Store.addSdxL2ConnectionPoint(sdxl2, sdxl2cp);
176 } catch (SdxL2Exception e) {
177 log.info(e.getMessage());
178 }
179
180 }
181
182 /**
183 * Returns all the SDX-L2 connection points names in a SDX-L2 or all the SDX-L2 connection points names.
184 *
185 * @param sdxl2 SDX-L2 name
186 * @return a set of SDX-L2 connection points names
187 */
188 @Override
189 public Set<String> getSdxL2ConnectionPoints(Optional<String> sdxl2) {
190
191 try {
192 return this.sdxL2Store.getSdxL2ConnectionPoints(sdxl2);
193 } catch (SdxL2Exception e) {
194 log.info(e.getMessage());
195 }
196
197 return Collections.emptySet();
198
199 }
200
201 /**
202 * Removes an SDX-L2 connection point from an SDX-L2.
203 *
204 * @param sdxl2cp SDX-L2 connection point name
205 */
206 @Override
207 public void removeSdxL2ConnectionPoint(String sdxl2cp) {
208
209 checkNotNull(sdxl2cp, "SdxL2ConnectionPoint name cannot be null");
210
211 try {
212 this.sdxL2Store.removeSdxL2ConnectionPoint(sdxl2cp);
213 } catch (SdxL2Exception e) {
214 log.info(e.getMessage());
215 }
216
217 }
218
pierventre1483e642016-06-08 18:52:29 +0200219 /**
220 * Returns an SDX-L2 connection point in a SDX-L2.
221 *
222 * @param sdxl2cp SDX-L2 connection point name
223 * @return the relative SdxL2ConnectionPoint object
224 */
225 @Override
226 public SdxL2ConnectionPoint getSdxL2ConnectionPoint(String sdxl2cp) {
227 checkNotNull(sdxl2cp, "SdxL2ConnectionPoint name cannot be null");
228 try {
229 return this.sdxL2Store.getSdxL2ConnectionPoint(sdxl2cp);
230 } catch (SdxL2Exception e) {
231 log.info(e.getMessage());
232 }
233
234 return null;
235 }
236
237 /**
238 * Returns the state of the Intent that has been provided as input.
239 *
240 * @param intentKey key of the intent;
241 * @return the last state of the intent;
242 */
243 @Override
244 public SdxL2State getIntentState(Key intentKey) {
245 checkNotNull(intentKey, "Intent key cannot be null");
246 return this.monitoringManager.getIntentState(intentKey);
247 }
248
249 /**
250 * Returns the state of the EdgePort that has been provided as input.
251 *
252 * @param edgeport the connect point representing the edge port
253 * @return the last state of the edgeport;
254 */
255 @Override
256 public SdxL2State getEdgePortState(ConnectPoint edgeport) {
257 checkNotNull(edgeport, "Edge port cannot be null");
258 return this.monitoringManager.getEdgePortState(edgeport);
259 }
260
261 /**
262 * Cleans the state of the Application.
263 */
264 @Override
265 public void cleanSdxL2() {
266 this.monitoringManager.cleanup();
267 }
268
pierventrebbb2e362016-06-26 19:42:48 +0200269 /**
270 * It requests ARP and NDP packets to the PacketService
271 * and registers the SDX-L2 PacketProcessor.
272 */
273 private void handleArpNdp() {
274 SdxL2ArpNdpHandler.vcType = vcType;
275 arpndpHandler = new SdxL2ArpNdpHandler(intentService, packetService, appId);
276 packetService.addProcessor(processor, PacketProcessor.director(1));
277
278 // ARP packet
279 TrafficSelector.Builder selectorBuilder =
280 DefaultTrafficSelector.builder();
281 selectorBuilder.matchEthType(TYPE_ARP);
282 packetService.requestPackets(selectorBuilder.build(),
283 CONTROL, appId, Optional.<DeviceId>empty());
284
285 // IPv6 Neighbor Solicitation packet.
286 selectorBuilder = DefaultTrafficSelector.builder();
287 selectorBuilder.matchEthType(TYPE_IPV6);
288 selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
289 selectorBuilder.matchIcmpv6Type(NEIGHBOR_SOLICITATION);
290 packetService.requestPackets(selectorBuilder.build(),
291 CONTROL, appId, Optional.<DeviceId>empty());
292
293 // IPv6 Neighbor Advertisement packet.
294 selectorBuilder = DefaultTrafficSelector.builder();
295 selectorBuilder.matchEthType(TYPE_IPV6);
296 selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
297 selectorBuilder.matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT);
298 packetService.requestPackets(selectorBuilder.build(),
299 CONTROL, appId, Optional.<DeviceId>empty());
300 }
301
302 /**
303 * Withdraws the requests for ARP/NDP packets and
304 * unregisters the SDX-L2 PacketProcessor.
305 */
306 private void unhandleArpNdp() {
307 arpndpHandler = null;
308 packetService.removeProcessor(processor);
309 processor = null;
310
311 TrafficSelector.Builder selectorBuilder =
312 DefaultTrafficSelector.builder();
313 selectorBuilder.matchEthType(TYPE_ARP);
314 packetService.cancelPackets(selectorBuilder.build(),
315 CONTROL, appId, Optional.<DeviceId>empty());
316
317 selectorBuilder = DefaultTrafficSelector.builder();
318 selectorBuilder.matchEthType(TYPE_IPV6);
319 selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
320 selectorBuilder.matchIcmpv6Type(NEIGHBOR_SOLICITATION);
321 packetService.cancelPackets(selectorBuilder.build(),
322 CONTROL, appId, Optional.<DeviceId>empty());
323
324 selectorBuilder = DefaultTrafficSelector.builder();
325 selectorBuilder.matchEthType(TYPE_IPV6);
326 selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
327 selectorBuilder.matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT);
328 packetService.cancelPackets(selectorBuilder.build(),
329 CONTROL, appId, Optional.<DeviceId>empty());
330 }
331
332 /**
333 * Packet processor responsible for forwarding packets along their paths.
334 */
335 private class SdxL2Processor implements PacketProcessor {
336
337 /**
338 * Processes the inbound packet as specified in the given context.
339 *
340 * @param context packet processing context
341 */
342 @Override
343 public void process(PacketContext context) {
344
345 /** Stop processing if the packet has been handled, since we
346 * can't do any more to it
347 */
348 if (context.isHandled()) {
349 return;
350 }
351
352 InboundPacket pkt = context.inPacket();
353 Ethernet ethPkt = pkt.parsed();
354 if (ethPkt == null) {
355 return;
356 }
357
358 boolean handled = false;
359 if (ethPkt.getEtherType() == TYPE_ARP) {
360 //handle the arp packet.
361 handled = arpndpHandler.handlePacket(context);
362 } else if (ethPkt.getEtherType() == TYPE_IPV6) {
363 IPv6 ipv6Pkt = (IPv6) ethPkt.getPayload();
364 if (ipv6Pkt.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
365 ICMP6 icmp6Pkt = (ICMP6) ipv6Pkt.getPayload();
366 if (icmp6Pkt.getIcmpType() == NEIGHBOR_SOLICITATION ||
367 icmp6Pkt.getIcmpType() == NEIGHBOR_ADVERTISEMENT) {
368 // handle ICMPv6 solicitations and advertisements
369 handled = arpndpHandler.handlePacket(context);
370 }
371 }
372 }
373
374 if (handled) {
375 context.block();
376 }
377
378 }
379 }
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200380}