Adds ARP/NDP handler for SDX-L2 and updates the README
Changes:
- Implements the internal ARP/NDP handler;
- Updates the README file;
- Adds interaction with PacketService
Change-Id: I245b2d5df2acaaa4b3f00ca2eed07d18337e41a5
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java
index d59b909..21dd06a 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java
@@ -23,12 +23,22 @@
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Deactivate;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP6;
+import org.onlab.packet.IPv6;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.edge.EdgePortService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,6 +49,12 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import static org.onlab.packet.Ethernet.TYPE_ARP;
+import static org.onlab.packet.Ethernet.TYPE_IPV6;
+import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
+import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
+import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
+import static org.onosproject.net.packet.PacketPriority.CONTROL;
/**
* Implementation of the SdxL2Service.
@@ -62,20 +78,34 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EdgePortService edgePortService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PacketService packetService;
+
+ protected SdxL2Processor processor = new SdxL2Processor();
+
+ protected SdxL2ArpNdpHandler arpndpHandler;
+
protected ApplicationId appId;
protected SdxL2MonitoringService monitoringManager;
+ protected String vcType = "MAC";
+
+
@Activate
protected void activate(ComponentContext context) {
appId = coreService.registerApplication(SDXL2_APP);
monitoringManager = new SdxL2MonitoringManager(appId, intentService, edgePortService);
+ handleArpNdp();
log.info("Started");
}
+
+
@Deactivate
protected void deactivate() {
this.cleanSdxL2();
+ unhandleArpNdp();
log.info("Stopped");
}
@@ -236,4 +266,115 @@
this.monitoringManager.cleanup();
}
+ /**
+ * It requests ARP and NDP packets to the PacketService
+ * and registers the SDX-L2 PacketProcessor.
+ */
+ private void handleArpNdp() {
+ SdxL2ArpNdpHandler.vcType = vcType;
+ arpndpHandler = new SdxL2ArpNdpHandler(intentService, packetService, appId);
+ packetService.addProcessor(processor, PacketProcessor.director(1));
+
+ // ARP packet
+ TrafficSelector.Builder selectorBuilder =
+ DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthType(TYPE_ARP);
+ packetService.requestPackets(selectorBuilder.build(),
+ CONTROL, appId, Optional.<DeviceId>empty());
+
+ // IPv6 Neighbor Solicitation packet.
+ selectorBuilder = DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthType(TYPE_IPV6);
+ selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
+ selectorBuilder.matchIcmpv6Type(NEIGHBOR_SOLICITATION);
+ packetService.requestPackets(selectorBuilder.build(),
+ CONTROL, appId, Optional.<DeviceId>empty());
+
+ // IPv6 Neighbor Advertisement packet.
+ selectorBuilder = DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthType(TYPE_IPV6);
+ selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
+ selectorBuilder.matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT);
+ packetService.requestPackets(selectorBuilder.build(),
+ CONTROL, appId, Optional.<DeviceId>empty());
+ }
+
+ /**
+ * Withdraws the requests for ARP/NDP packets and
+ * unregisters the SDX-L2 PacketProcessor.
+ */
+ private void unhandleArpNdp() {
+ arpndpHandler = null;
+ packetService.removeProcessor(processor);
+ processor = null;
+
+ TrafficSelector.Builder selectorBuilder =
+ DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthType(TYPE_ARP);
+ packetService.cancelPackets(selectorBuilder.build(),
+ CONTROL, appId, Optional.<DeviceId>empty());
+
+ selectorBuilder = DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthType(TYPE_IPV6);
+ selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
+ selectorBuilder.matchIcmpv6Type(NEIGHBOR_SOLICITATION);
+ packetService.cancelPackets(selectorBuilder.build(),
+ CONTROL, appId, Optional.<DeviceId>empty());
+
+ selectorBuilder = DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthType(TYPE_IPV6);
+ selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
+ selectorBuilder.matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT);
+ packetService.cancelPackets(selectorBuilder.build(),
+ CONTROL, appId, Optional.<DeviceId>empty());
+ }
+
+ /**
+ * Packet processor responsible for forwarding packets along their paths.
+ */
+ private class SdxL2Processor implements PacketProcessor {
+
+ /**
+ * Processes the inbound packet as specified in the given context.
+ *
+ * @param context packet processing context
+ */
+ @Override
+ public void process(PacketContext context) {
+
+ /** Stop processing if the packet has been handled, since we
+ * can't do any more to it
+ */
+ if (context.isHandled()) {
+ return;
+ }
+
+ InboundPacket pkt = context.inPacket();
+ Ethernet ethPkt = pkt.parsed();
+ if (ethPkt == null) {
+ return;
+ }
+
+ boolean handled = false;
+ if (ethPkt.getEtherType() == TYPE_ARP) {
+ //handle the arp packet.
+ handled = arpndpHandler.handlePacket(context);
+ } else if (ethPkt.getEtherType() == TYPE_IPV6) {
+ IPv6 ipv6Pkt = (IPv6) ethPkt.getPayload();
+ if (ipv6Pkt.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
+ ICMP6 icmp6Pkt = (ICMP6) ipv6Pkt.getPayload();
+ if (icmp6Pkt.getIcmpType() == NEIGHBOR_SOLICITATION ||
+ icmp6Pkt.getIcmpType() == NEIGHBOR_ADVERTISEMENT) {
+ // handle ICMPv6 solicitations and advertisements
+ handled = arpndpHandler.handlePacket(context);
+ }
+ }
+ }
+
+ if (handled) {
+ context.block();
+ }
+
+ }
+ }
}