Adding small handler to ICMPHandler

Change-Id: I8401c1564cc8aa89f8e3767ae83ec56c0dfe6fd0
diff --git a/apps/segmentrouting/BUCK b/apps/segmentrouting/BUCK
index d24cde8..67f55d1 100644
--- a/apps/segmentrouting/BUCK
+++ b/apps/segmentrouting/BUCK
@@ -7,6 +7,7 @@
     '//core/store/serializers:onos-core-serializers',
     '//incubator/api:onos-incubator-api',
     '//utils/rest:onlab-rest',
+    '//apps/routing-api:onos-apps-routing-api'
 ]
 
 BUNDLES = [
diff --git a/apps/segmentrouting/pom.xml b/apps/segmentrouting/pom.xml
index 2859718..d416749 100644
--- a/apps/segmentrouting/pom.xml
+++ b/apps/segmentrouting/pom.xml
@@ -106,6 +106,11 @@
             <scope>test</scope>
             <classifier>tests</classifier>
         </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-app-routing-api</artifactId>
+            <version>1.9.0-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index 0e408bb..ecaa77d 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -28,17 +28,24 @@
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onlab.packet.ndp.NeighborSolicitation;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.incubator.net.config.basics.InterfaceConfig;
+import org.onosproject.incubator.net.intf.Interface;
 import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
 import org.onosproject.incubator.net.neighbour.NeighbourMessageType;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
 import org.onosproject.net.HostId;
+import org.onosproject.net.config.NetworkConfigEvent;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.host.HostService;
 import org.onosproject.net.packet.DefaultOutboundPacket;
+import org.onosproject.net.packet.InboundPacket;
 import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.routing.config.RouterConfig;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
 import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
 import org.slf4j.Logger;
@@ -455,4 +462,71 @@
         flood(ndpRequest, inPort, targetAddress);
     }
 
+    /////////////////////////////////////////////////////////////////
+    //    XXX Neighbour hacking, temporary workaround will be      //
+    //    removed as soon as possible, when the bridging will      //
+    //    be implemented. For now, it's fine to leave this         //
+    /////////////////////////////////////////////////////////////////
+
+    // XXX Neighbour hacking. To store upstream connect
+    // point and vRouter connect point
+    private ConnectPoint upstreamCP = null;
+    private ConnectPoint vRouterCP = null;
+
+    // XXX Neighbour hacking, this method is used to handle
+    // the ICMPv6 protocols for the upstream port
+    public boolean handleUPstreamPackets(PacketContext packetContext) {
+        InboundPacket pkt = packetContext.inPacket();
+        Ethernet ethernet = pkt.parsed();
+        if (vRouterCP == null || upstreamCP == null) {
+            return false;
+        }
+        if (pkt.receivedFrom().equals(upstreamCP)) {
+            sendTo(ByteBuffer.wrap(ethernet.serialize()), vRouterCP);
+            return true;
+        }
+        return false;
+    }
+
+    // XXX Neighbour hacking. To update the Upstream CP
+    public void updateUPstreamCP(NetworkConfigEvent event) {
+        Set<ConnectPoint> portSubjects = srManager.cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
+        upstreamCP = null;
+        portSubjects.stream().forEach(subject -> {
+            InterfaceConfig config = srManager.cfgService.getConfig(subject, InterfaceConfig.class);
+            Set<Interface> networkInterfaces;
+            try {
+                networkInterfaces = config.getInterfaces();
+            } catch (ConfigException e) {
+                log.error("Error loading port configuration");
+                return;
+            }
+            networkInterfaces.forEach(networkInterface -> {
+                if (networkInterface.name().equals("internet-router")) {
+                    upstreamCP = subject;
+                }
+            });
+        });
+
+    }
+
+    // XXX Neighbour hacking. To update the Upstream CP
+    public void updateVRouterCP(NetworkConfigEvent event) {
+        RouterConfig config = (RouterConfig) event.config().get();
+        if (config == null) {
+            log.warn("Router config not available");
+            vRouterCP = null;
+            return;
+        }
+        vRouterCP = config.getControlPlaneConnectPoint();
+    }
+
+    // XXX Neigbour hack. To send out a packet
+    private void sendTo(ByteBuffer packet, ConnectPoint outPort) {
+        TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
+        builder.setOutput(outPort.port());
+        srManager.packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
+                                                     builder.build(), packet));
+    }
+
 }
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 4f912f3..614709f 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -34,6 +34,7 @@
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.event.Event;
+import org.onosproject.incubator.net.config.basics.InterfaceConfig;
 import org.onosproject.incubator.net.config.basics.McastConfig;
 import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.incubator.net.routing.RouteEvent;
@@ -72,6 +73,7 @@
 import org.onosproject.net.packet.PacketProcessor;
 import org.onosproject.net.packet.PacketService;
 import org.onosproject.net.topology.TopologyService;
+import org.onosproject.routing.config.RouterConfig;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
 import org.onosproject.segmentrouting.config.DeviceConfiguration;
 import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
@@ -651,6 +653,11 @@
 
             InboundPacket pkt = context.inPacket();
             Ethernet ethernet = pkt.parsed();
+
+            if (ethernet == null) {
+                return;
+            }
+
             log.trace("Rcvd pktin: {}", ethernet);
             if (ethernet.getEtherType() == TYPE_ARP) {
                 log.warn("{} - we are still receiving ARP packets from {}",
@@ -670,17 +677,21 @@
             } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
                 IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
                 //ipHandler.addToPacketBuffer(ipv6Packet);
-                /*
-                 * We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
-                 */
+                // We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
                 if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
                     ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
                     if (icmp6Packet.getIcmpType() == ICMP6.ECHO_REQUEST ||
                             icmp6Packet.getIcmpType() == ICMP6.ECHO_REPLY) {
                         icmpHandler.processIcmpv6(ethernet, pkt.receivedFrom());
                     } else {
-                        log.warn("Received ICMPv6 0x{} - not handled",
-                                 Integer.toHexString(icmp6Packet.getIcmpType() & 0xff));
+                        // XXX Neigbour hacking, to handle the ICMPv6 packet
+                        // not under our control
+                        if (icmpHandler.handleUPstreamPackets(context)) {
+                            log.debug("Rcvd pktin from UpStream: {}", ipv6Packet);
+                        } else {
+                            log.debug("Received ICMPv6 0x{} - not handled",
+                                     Integer.toHexString(icmp6Packet.getIcmpType() & 0xff));
+                        }
                     }
                 } else {
                    // NOTE: We don't support IP learning at this moment so this
@@ -1092,6 +1103,35 @@
                     default:
                         break;
                 }
+                // XXX Neighbour hacking. This method is looking for
+                // the Internet-Router interface. In order to retrieve
+                // the upstream port.
+            } else if (event.configClass().equals(InterfaceConfig.class)) {
+                switch (event.type()) {
+                    case CONFIG_ADDED:
+                    case CONFIG_UPDATED:
+                        icmpHandler.updateUPstreamCP(event);
+                    case CONFIG_REGISTERED:
+                    case CONFIG_UNREGISTERED:
+                    case CONFIG_REMOVED:
+                        break;
+                    default:
+                        break;
+                }
+                // XXX Neighbour hacking. This method is looking for
+                // the vrouter port.
+            } else if (event.configClass().equals(RouterConfig.class)) {
+                switch (event.type()) {
+                    case CONFIG_ADDED:
+                    case CONFIG_UPDATED:
+                        icmpHandler.updateVRouterCP(event);
+                    case CONFIG_REGISTERED:
+                    case CONFIG_UNREGISTERED:
+                    case CONFIG_REMOVED:
+                        break;
+                    default:
+                        break;
+                }
             }
         }
     }