[CORD-630] IPv6 filtering rules

Changes:
- Udpates TMAC table in order to handle IPv6 protocol;
- Updates ACL table in order to handle ICMPv6 traffic and traffic for the router;
- Udpates UNICAST table in order to handle the traffic towards the other routers;
- Updates the router ip in the netcfg in order to handle IPv6 address;
- Substitutes IpAddress and IpPrefix in many parts;
- Updates cpqd and ofdpa drivers to handle the above cases;
- Fixes the interaction with NRM when neighbordiscovery is activated;
- Introduces the IPv6 loopback and IPv6 node sid;

Change-Id: I0a3003be6f2f4b581cabe224c47a0cfbf51e8f9c
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
index 2bd9932..255f740 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
@@ -20,6 +20,7 @@
 import com.google.common.collect.SetMultimap;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Address;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
@@ -63,9 +64,11 @@
     private SegmentRoutingManager srManager;
 
     private class SegmentRouterInfo {
-        int nodeSid;
+        int ipv4NodeSid;
+        int ipv6NodeSid;
         DeviceId deviceId;
-        Ip4Address ip;
+        Ip4Address ipv4Loopback;
+        Ip6Address ipv6Loopback;
         MacAddress mac;
         boolean isEdge;
         Map<PortNumber, Ip4Address> gatewayIps;
@@ -95,14 +98,19 @@
                     srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
             SegmentRouterInfo info = new SegmentRouterInfo();
             info.deviceId = subject;
-            info.nodeSid = config.nodeSid();
-            info.ip = config.routerIp();
+            info.ipv4NodeSid = config.nodeSidIPv4();
+            info.ipv6NodeSid = config.nodeSidIPv6();
+            info.ipv4Loopback = config.routerIpv4();
+            info.ipv6Loopback = config.routerIpv6();
             info.mac = config.routerMac();
             info.isEdge = config.isEdgeRouter();
             info.adjacencySids = config.adjacencySids();
             deviceConfigMap.put(info.deviceId, info);
             log.info("Read device config for device: {}", info.deviceId);
-            allSegmentIds.add(info.nodeSid);
+            /*
+             * IPv6 sid is not inserted. this part of the code is not used for now.
+             */
+            allSegmentIds.add(info.ipv4NodeSid);
         });
 
         // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
@@ -148,28 +156,40 @@
     }
 
     @Override
-    public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
+    public int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
         SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
         if (srinfo != null) {
-            log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
-            return srinfo.nodeSid;
+            log.trace("getIPv4SegmentId for device{} is {}", deviceId, srinfo.ipv4NodeSid);
+            return srinfo.ipv4NodeSid;
         } else {
-            String message = "getSegmentId fails for device: " + deviceId + ".";
+            String message = "getIPv4SegmentId fails for device: " + deviceId + ".";
+            throw new DeviceConfigNotFoundException(message);
+        }
+    }
+
+    @Override
+    public int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
+        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+        if (srinfo != null) {
+            log.trace("getIPv6SegmentId for device{} is {}", deviceId, srinfo.ipv6NodeSid);
+            return srinfo.ipv6NodeSid;
+        } else {
+            String message = "getIPv6SegmentId fails for device: " + deviceId + ".";
             throw new DeviceConfigNotFoundException(message);
         }
     }
 
     /**
-     * Returns the Node segment id of a segment router given its Router mac address.
+     * Returns the IPv4 Node segment id of a segment router given its Router mac address.
      *
      * @param routerMac router mac address
      * @return node segment id, or -1 if not found in config
      */
-    public int getSegmentId(MacAddress routerMac) {
+    public int getIPv4SegmentId(MacAddress routerMac) {
         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
                     deviceConfigMap.entrySet()) {
             if (entry.getValue().mac.equals(routerMac)) {
-                return entry.getValue().nodeSid;
+                return entry.getValue().ipv4NodeSid;
             }
         }
 
@@ -177,16 +197,50 @@
     }
 
     /**
-     * Returns the Node segment id of a segment router given its Router ip address.
+     * Returns the IPv6 Node segment id of a segment router given its Router mac address.
+     *
+     * @param routerMac router mac address
+     * @return node segment id, or -1 if not found in config
+     */
+    public int getIPv6SegmentId(MacAddress routerMac) {
+        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
+                deviceConfigMap.entrySet()) {
+            if (entry.getValue().mac.equals(routerMac)) {
+                return entry.getValue().ipv6NodeSid;
+            }
+        }
+
+        return -1;
+    }
+
+    /**
+     * Returns the IPv4 Node segment id of a segment router given its Router ip address.
      *
      * @param routerAddress router ip address
      * @return node segment id, or -1 if not found in config
      */
-    public int getSegmentId(Ip4Address routerAddress) {
+    public int getIPv4SegmentId(Ip4Address routerAddress) {
         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
             deviceConfigMap.entrySet()) {
-            if (entry.getValue().ip.equals(routerAddress)) {
-                return entry.getValue().nodeSid;
+            if (entry.getValue().ipv4Loopback.equals(routerAddress)) {
+                return entry.getValue().ipv4NodeSid;
+            }
+        }
+
+        return -1;
+    }
+
+    /**
+     * Returns the IPv6 Node segment id of a segment router given its Router ip address.
+     *
+     * @param routerAddress router ip address
+     * @return node segment id, or -1 if not found in config
+     */
+    public int getIPv6SegmentId(Ip6Address routerAddress) {
+        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
+                deviceConfigMap.entrySet()) {
+            if (entry.getValue().ipv6Loopback.equals(routerAddress)) {
+                return entry.getValue().ipv6NodeSid;
             }
         }
 
@@ -206,13 +260,25 @@
     }
 
     @Override
-    public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
+    public Ip4Address getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException {
         SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
         if (srinfo != null) {
-            log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
-            return srinfo.ip;
+            log.trace("getRouterIpv4 for device{} is {}", deviceId, srinfo.ipv4Loopback);
+            return srinfo.ipv4Loopback;
         } else {
-            String message = "getRouterIp fails for device: " + deviceId + ".";
+            String message = "getRouterIpv4 fails for device: " + deviceId + ".";
+            throw new DeviceConfigNotFoundException(message);
+        }
+    }
+
+    @Override
+    public Ip6Address getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException {
+        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+        if (srinfo != null) {
+            log.trace("getRouterIpv6 for device{} is {}", deviceId, srinfo.ipv6Loopback);
+            return srinfo.ipv6Loopback;
+        } else {
+            String message = "getRouterIpv6 fails for device: " + deviceId + ".";
             throw new DeviceConfigNotFoundException(message);
         }
     }
@@ -275,7 +341,8 @@
     public DeviceId getDeviceId(int sid) {
         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
             deviceConfigMap.entrySet()) {
-            if (entry.getValue().nodeSid == sid) {
+            if (entry.getValue().ipv4NodeSid == sid ||
+                    entry.getValue().ipv6NodeSid == sid) {
                 return entry.getValue().deviceId;
             }
         }
@@ -293,7 +360,25 @@
     public DeviceId getDeviceId(Ip4Address ipAddress) {
         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
             deviceConfigMap.entrySet()) {
-            if (entry.getValue().ip.equals(ipAddress)) {
+            if (entry.getValue().ipv4Loopback.equals(ipAddress)) {
+                return entry.getValue().deviceId;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the device identifier or data plane identifier (dpid)
+     * of a segment router given its router ipv6 address.
+     *
+     * @param ipAddress router ipv6 address
+     * @return deviceId device identifier
+     */
+    public DeviceId getDeviceId(Ip6Address ipAddress) {
+        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
+                deviceConfigMap.entrySet()) {
+            if (entry.getValue().ipv6Loopback.equals(ipAddress)) {
                 return entry.getValue().deviceId;
             }
         }
@@ -390,7 +475,32 @@
             return null;
         }
 
-        return srInfo.ip;
+        return srInfo.ipv4Loopback;
+    }
+
+    /**
+     * Returns the router ipv6 address of segment router that has the
+     * specified ip address in its subnets.
+     *
+     * @param destIpAddress target ip address
+     * @return router ip address
+     */
+    public Ip6Address getRouterIpAddressForASubnetHost(Ip6Address destIpAddress) {
+        Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
+
+        if (matchIntf == null) {
+            log.debug("No router was found for {}", destIpAddress);
+            return null;
+        }
+
+        DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
+        SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
+        if (srInfo == null) {
+            log.debug("No device config was found for {}", routerDeviceId);
+            return null;
+        }
+
+        return srInfo.ipv6Loopback;
     }
 
     /**
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
index 5ad9cdc..565dbe1 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
@@ -15,15 +15,15 @@
  */
 package org.onosproject.segmentrouting.config;
 
-import java.util.List;
-import java.util.Map;
-
-import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * Mechanism through which group handler module retrieves
  * the device specific attributes such as segment ID,
@@ -39,13 +39,22 @@
     boolean isConfigured(DeviceId deviceId);
 
     /**
-     * Returns the segment id of a device to be used in group creation.
+     * Returns the IPv4 segment id of a device to be used in group creation.
      *
      * @param deviceId device identifier
      * @throws DeviceConfigNotFoundException if the device configuration is not found
      * @return segment id of a device
      */
-    int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
+    int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
+
+    /**
+     * Returns the IPv6 segment id of a device to be used in group creation.
+     *
+     * @param deviceId device identifier
+     * @throws DeviceConfigNotFoundException if the device configuration is not found
+     * @return segment id of a device
+     */
+    int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
 
     /**
      * Returns the Mac address of a device to be used in group creation.
@@ -57,13 +66,22 @@
     MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException;
 
     /**
-     * Returns the router ip address of a segment router.
+     * Returns the router ipv4 address of a segment router.
      *
      * @param deviceId device identifier
      * @throws DeviceConfigNotFoundException if the device configuration is not found
      * @return router ip address
      */
-    Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException;
+    IpAddress getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException;
+
+    /**
+     * Returns the router ipv6 address of a segment router.
+     *
+     * @param deviceId device identifier
+     * @throws DeviceConfigNotFoundException if the device configuration is not found
+     * @return router ip address
+     */
+    IpAddress getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException;
 
     /**
      * Indicates whether a device is edge device or transit/core device.
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
index 21ba1e6..bc0d329 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
@@ -21,6 +21,7 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.ImmutableMap;
 import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
 import org.onlab.packet.MacAddress;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.config.Config;
@@ -36,9 +37,11 @@
  */
 public class SegmentRoutingDeviceConfig extends Config<DeviceId> {
     private static final String NAME = "name";
-    private static final String IP = "routerIp";
+    private static final String IP4 = "ipv4Loopback";
+    private static final String IP6 = "ipv6Loopback";
     private static final String MAC = "routerMac";
-    private static final String SID = "nodeSid";
+    private static final String IP4_SID = "ipv4NodeSid";
+    private static final String IP6_SID = "ipv6NodeSid";
     private static final String EDGE = "isEdgeRouter";
     private static final String ADJSIDS = "adjacencySids";
     private static final String ADJSID = "adjSid";
@@ -46,11 +49,13 @@
 
     @Override
     public boolean isValid() {
-        return hasOnlyFields(NAME, IP, MAC, SID, EDGE, ADJSIDS, ADJSID, PORTS) &&
+        return hasOnlyFields(NAME, IP4, IP6, MAC,
+                             IP4_SID, IP6_SID, EDGE,
+                             ADJSIDS, ADJSID, PORTS) &&
                 name() != null &&
-                routerIp() != null &&
+                routerIpv4() != null &&
                 routerMac() != null &&
-                nodeSid() != -1 &&
+                nodeSidIPv4() != -1 &&
                 isEdgeRouter() != null &&
                 adjacencySids() != null;
     }
@@ -76,23 +81,43 @@
     }
 
     /**
-     * Gets the IP address of the router.
+     * Gets the IPv4 address of the router.
      *
      * @return IP address of the router. Or null if not configured.
      */
-    public Ip4Address routerIp() {
-        String ip = get(IP, null);
+    public Ip4Address routerIpv4() {
+        String ip = get(IP4, null);
         return ip != null ? Ip4Address.valueOf(ip) : null;
     }
 
     /**
-     * Sets the IP address of the router.
+     * Gets the IPv6 address of the router.
      *
-     * @param ip IP address of the router.
+     * @return IP address of the router. Or null if not configured.
+     */
+    public Ip6Address routerIpv6() {
+        String ip = get(IP6, null);
+        return ip != null ? Ip6Address.valueOf(ip) : null;
+    }
+
+    /**
+     * Sets the IPv4 address of the router.
+     *
+     * @param ip IPv4 address of the router.
      * @return the config of the router.
      */
-    public SegmentRoutingDeviceConfig setRouterIp(String ip) {
-        return (SegmentRoutingDeviceConfig) setOrClear(IP, ip);
+    public SegmentRoutingDeviceConfig setRouterIpv4(String ip) {
+        return (SegmentRoutingDeviceConfig) setOrClear(IP4, ip);
+    }
+
+    /**
+     * Sets the IPv6 address of the router.
+     *
+     * @param ip IPv6 address of the router.
+     * @return the config of the router.
+     */
+    public SegmentRoutingDeviceConfig setRouterIpv6(String ip) {
+        return (SegmentRoutingDeviceConfig) setOrClear(IP6, ip);
     }
 
     /**
@@ -116,22 +141,41 @@
     }
 
     /**
-     * Gets the node SID of the router.
+     * Gets the IPv4 node SID of the router.
      *
      * @return node SID of the router. Or -1 if not configured.
      */
-    public int nodeSid() {
-        return get(SID, -1);
+    public int nodeSidIPv4() {
+        return get(IP4_SID, -1);
     }
 
     /**
-     * Sets the node SID of the router.
+     * Gets the IPv6 node SID of the router.
+     *
+     * @return node SID of the router. Or -1 if not configured.
+     */
+    public int nodeSidIPv6() {
+        return get(IP6_SID, -1);
+    }
+
+    /**
+     * Sets the node IPv4 node SID of the router.
      *
      * @param sid node SID of the router.
      * @return the config of the router.
      */
-    public SegmentRoutingDeviceConfig setNodeSid(int sid) {
-        return (SegmentRoutingDeviceConfig) setOrClear(SID, sid);
+    public SegmentRoutingDeviceConfig setNodeSidIPv4(int sid) {
+        return (SegmentRoutingDeviceConfig) setOrClear(IP4_SID, sid);
+    }
+
+    /**
+     * Sets the node IPv6 node SID of the router.
+     *
+     * @param sid node SID of the router.
+     * @return the config of the router.
+     */
+    public SegmentRoutingDeviceConfig setNodeSidIPv6(int sid) {
+        return (SegmentRoutingDeviceConfig) setOrClear(IP6_SID, sid);
     }
 
     /**
@@ -222,4 +266,4 @@
 
         return this;
     }
-}
\ No newline at end of file
+}