[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/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
index a6a9d4e..890af99 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
@@ -15,22 +15,6 @@
  */
 package org.onosproject.driver.pipeline;
 
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import org.onlab.osgi.ServiceDirectory;
@@ -68,6 +52,8 @@
 import org.onosproject.net.flow.criteria.EthTypeCriterion;
 import org.onosproject.net.flow.criteria.ExtensionCriterion;
 import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
 import org.onosproject.net.flow.criteria.MplsBosCriterion;
 import org.onosproject.net.flow.criteria.MplsCriterion;
 import org.onosproject.net.flow.criteria.PortCriterion;
@@ -92,6 +78,22 @@
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.slf4j.Logger;
 
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import static java.util.concurrent.Executors.newScheduledThreadPool;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.slf4j.LoggerFactory.getLogger;
+
 /**
  * Driver for Broadcom's OF-DPA v2.0 TTP.
  *
@@ -648,6 +650,25 @@
                     .makePermanent()
                     .forTable(TMAC_TABLE).build();
             rules.add(rule);
+            /*
+             * TMAC rules for IPv6 packets
+             */
+            selector = DefaultTrafficSelector.builder();
+            treatment = DefaultTrafficTreatment.builder();
+            selector.matchInPort(pnum);
+            selector.extension(ofdpaMatchVlanVid, deviceId);
+            selector.matchEthType(Ethernet.TYPE_IPV6);
+            selector.matchEthDst(ethCriterion.mac());
+            treatment.transition(UNICAST_ROUTING_TABLE);
+            rule = DefaultFlowRule.builder()
+                    .forDevice(deviceId)
+                    .withSelector(selector.build())
+                    .withTreatment(treatment.build())
+                    .withPriority(DEFAULT_PRIORITY)
+                    .fromApp(applicationId)
+                    .makePermanent()
+                    .forTable(TMAC_TABLE).build();
+            rules.add(rule);
         }
         return rules;
     }
@@ -701,6 +722,8 @@
         return Collections.emptySet();
     }
 
+
+
     /**
      * In the OF-DPA 2.0 pipeline, versatile forwarding objectives go to the
      * ACL table.
@@ -740,6 +763,14 @@
                 OfdpaMatchVlanVid ofdpaMatchVlanVid =
                         new OfdpaMatchVlanVid(vlanId);
                 sbuilder.extension(ofdpaMatchVlanVid, deviceId);
+            } else if (criterion instanceof Icmpv6TypeCriterion ||
+                    criterion instanceof Icmpv6CodeCriterion) {
+                /*
+                 * We silenty discard these criterions, our current
+                 * OFDPA platform does not support these matches on
+                 * the ACL table.
+                 */
+                log.warn("ICMPv6 Type and ICMPv6 Code are not supported");
             } else {
                 sbuilder.add(criterion);
             }
@@ -830,6 +861,39 @@
     }
 
     /**
+     * Helper method to build Ipv6 selector using the selector provided by
+     * a forwarding objective.
+     *
+     * @param builderToUpdate the builder to update
+     * @param fwd the selector to read
+     * @return 0 if the update ends correctly. -1 if the matches
+     * are not yet supported
+     */
+    protected int buildIpv6Selector(TrafficSelector.Builder builderToUpdate,
+                                    ForwardingObjective fwd) {
+
+        TrafficSelector selector = fwd.selector();
+
+        IpPrefix ipv6Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV6_DST)).ip();
+        if (ipv6Dst.isMulticast()) {
+            log.warn("IPv6 Multicast is currently not supported");
+            fail(fwd, ObjectiveError.BADPARAMS);
+            return -1;
+        } else {
+            if (ipv6Dst.prefixLength() == 0) {
+                log.warn("Default ipv6 route is currently not supported");
+                fail(fwd, ObjectiveError.BADPARAMS);
+                return -1;
+            } else {
+                builderToUpdate.matchEthType(Ethernet.TYPE_IPV6).matchIPv6Dst(ipv6Dst);
+            }
+            log.debug("processing IPv6 unicast specific forwarding objective {} -> next:{}"
+                              + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
+        }
+        return 0;
+    }
+
+    /**
      * Internal implementation of processEthTypeSpecific.
      * <p>
      * Wildcarded IPv4_DST is not supported in OFDPA i12. Therefore, we break
@@ -882,10 +946,8 @@
                         // The entire IPV4_DST field is wildcarded intentionally
                         filteredSelector.matchEthType(Ethernet.TYPE_IPV4);
                     } else {
-                        /*
-                         * NOTE: The switch does not support matching 0.0.0.0/0
-                         * Split it into 0.0.0.0/1 and 128.0.0.0/1
-                         */
+                         // NOTE: The switch does not support matching 0.0.0.0/0
+                         // Split it into 0.0.0.0/1 and 128.0.0.0/1
                         filteredSelector.matchEthType(Ethernet.TYPE_IPV4)
                                 .matchIPDst(IpPrefix.valueOf("0.0.0.0/1"));
                         complementarySelector.matchEthType(Ethernet.TYPE_IPV4)
@@ -911,6 +973,21 @@
                 }
             }
 
+        } else if (ethType.ethType().toShort() == Ethernet.TYPE_IPV6) {
+            if (buildIpv6Selector(filteredSelector, fwd) < 0) {
+                return Collections.emptyList();
+            }
+            forTableId = UNICAST_ROUTING_TABLE;
+            if (fwd.treatment() != null) {
+                for (Instruction instr : fwd.treatment().allInstructions()) {
+                    if (instr instanceof L3ModificationInstruction &&
+                            ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
+                        // XXX decrementing IP ttl is done automatically for routing, this
+                        // action is ignored or rejected in ofdpa as it is not fully implemented
+                        //tb.deferred().add(instr);
+                    }
+                }
+            }
         } else {
             filteredSelector
                 .matchEthType(Ethernet.MPLS_UNICAST)
@@ -951,10 +1028,9 @@
                 log.warn("SR CONTINUE case cannot be handled as MPLS ECMP "
                         + "is not implemented in OF-DPA yet. Aborting this flow {} -> next:{}"
                         + "in this device {}", fwd.id(), fwd.nextId(), deviceId);
-                // XXX We could convert to forwarding to a single-port, via a
-                // MPLS interface, or a MPLS SWAP (with-same) but that would
-                // have to be handled in the next-objective. Also the pop-mpls
-                // logic used here won't work in non-BoS case.
+                // XXX We could convert to forwarding to a single-port, via a MPLS interface,
+                // or a MPLS SWAP (with-same) but that would have to be handled in the next-objective.
+                // Also the pop-mpls logic used here won't work in non-BoS case.
                 fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
                 return Collections.emptySet();
             }
@@ -1012,19 +1088,9 @@
         Collection<FlowRule> flowRuleCollection = new ArrayList<>();
         flowRuleCollection.add(ruleBuilder.build());
         if (defaultRule) {
-            FlowRule.Builder rule = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .withPriority(fwd.priority())
-                .forDevice(deviceId)
-                .withSelector(complementarySelector.build())
-                .withTreatment(tb.build())
-                .forTable(forTableId);
-            if (fwd.permanent()) {
-                rule.makePermanent();
-            } else {
-                rule.makeTemporary(fwd.timeout());
-            }
-            flowRuleCollection.add(rule.build());
+            flowRuleCollection.add(
+                    defaultRoute(fwd, complementarySelector, forTableId, tb)
+            );
             log.debug("Default rule 0.0.0.0/0 is being installed two rules");
         }
         // XXX retrying flows may be necessary due to bug CORD-554
@@ -1035,6 +1101,25 @@
         return flowRuleCollection;
     }
 
+    protected FlowRule defaultRoute(ForwardingObjective fwd,
+                                    TrafficSelector.Builder complementarySelector,
+                                    int forTableId,
+                                    TrafficTreatment.Builder tb) {
+        FlowRule.Builder rule = DefaultFlowRule.builder()
+                .fromApp(fwd.appId())
+                .withPriority(fwd.priority())
+                .forDevice(deviceId)
+                .withSelector(complementarySelector.build())
+                .withTreatment(tb.build())
+                .forTable(forTableId);
+        if (fwd.permanent()) {
+            rule.makePermanent();
+        } else {
+            rule.makeTemporary(fwd.timeout());
+        }
+        return rule.build();
+    }
+
     /**
      * Handles forwarding rules to the L2 bridging table. Flow actions are not
      * allowed in the bridging table - instead we use L2 Interface group or
@@ -1128,7 +1213,8 @@
                 .getCriterion(Criterion.Type.ETH_TYPE);
         return !((ethType == null) ||
                 ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
-                        (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)));
+                        (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) &&
+                        (ethType.ethType().toShort() != Ethernet.TYPE_IPV6));
     }
 
     private boolean isSupportedEthDstObjective(ForwardingObjective fwd) {