Implement some of the missing IPv6 flowmod treatments

Work toward ONOS-509

The following treatments are added/implemented:
  - IPV6_SRC
  - IPV6_DST
  - IPV6_FLABEL

Also:
 - Renamed L3ModificationInstruction.L3SubType.IP_SRC and IP_DST
   to IPV4_SRC and IPV4_DST (for naming consistency).
 - Few minor fixes in related code: Javadocs, comments, log messages,
   and IP address usage.

Change-Id: I551056f767a37e7cb6ae7d79f4a3929183500b57
diff --git a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
index 91edcbf..98cb3b2 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
@@ -120,7 +120,7 @@
         public Builder setIpDst(IpAddress addr);
 
         /**
-         * Decrease the TTL in IP header by one.
+         * Decrement the TTL in IP header by one.
          *
          * @return a treatment builder
          */
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
index 8141c9a..3838cdf 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
@@ -29,6 +29,7 @@
 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModTtlInstruction;
 
 import org.onlab.packet.Ethernet;
@@ -144,24 +145,59 @@
     public static L2ModificationInstruction decMplsTtl() {
         return new ModMplsTtlInstruction();
     }
+
     /**
-     * Creates a L3 src modification.
-     * @param addr the ip address to modify to.
+     * Creates a L3 IPv4 src modification.
+     *
+     * @param addr the IPv4 address to modify to
      * @return a L3 modification
      */
     public static L3ModificationInstruction modL3Src(IpAddress addr) {
-        checkNotNull(addr, "Src l3 address cannot be null");
-        return new ModIPInstruction(L3SubType.IP_SRC, addr);
+        checkNotNull(addr, "Src l3 IPv4 address cannot be null");
+        return new ModIPInstruction(L3SubType.IPV4_SRC, addr);
     }
 
     /**
-     * Creates a L3 dst modification.
-     * @param addr the ip address to modify to.
+     * Creates a L3 IPv4 dst modification.
+     *
+     * @param addr the IPv4 address to modify to
      * @return a L3 modification
      */
     public static L3ModificationInstruction modL3Dst(IpAddress addr) {
-        checkNotNull(addr, "Dst l3 address cannot be null");
-        return new ModIPInstruction(L3SubType.IP_DST, addr);
+        checkNotNull(addr, "Dst l3 IPv4 address cannot be null");
+        return new ModIPInstruction(L3SubType.IPV4_DST, addr);
+    }
+
+    /**
+     * Creates a L3 IPv6 src modification.
+     *
+     * @param addr the IPv6 address to modify to
+     * @return a L3 modification
+     */
+    public static L3ModificationInstruction modL3IPv6Src(IpAddress addr) {
+        checkNotNull(addr, "Src l3 IPv6 address cannot be null");
+        return new ModIPInstruction(L3SubType.IPV6_SRC, addr);
+    }
+
+    /**
+     * Creates a L3 IPv6 dst modification.
+     *
+     * @param addr the IPv6 address to modify to
+     * @return a L3 modification
+     */
+    public static L3ModificationInstruction modL3IPv6Dst(IpAddress addr) {
+        checkNotNull(addr, "Dst l3 IPv6 address cannot be null");
+        return new ModIPInstruction(L3SubType.IPV6_DST, addr);
+    }
+
+    /**
+     * Creates a L3 IPv6 Flow Label modification.
+     *
+     * @param flowLabel the IPv6 flow label to modify to (20 bits)
+     * @return a L3 modification
+     */
+    public static L3ModificationInstruction modL3IPv6FlowLabel(int flowLabel) {
+        return new ModIPv6FlowLabelInstruction(flowLabel);
     }
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java
index 93e85ef..f8814a0 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java
@@ -31,17 +31,32 @@
      */
     public enum L3SubType {
         /**
-         * Ether src modification.
+         * IPv4 src modification.
          */
-        IP_SRC,
+        IPV4_SRC,
 
         /**
-         * Ether dst modification.
+         * IPv4 dst modification.
          */
-        IP_DST,
+        IPV4_DST,
 
         /**
-         * Decrease TTL.
+         * IPv6 src modification.
+         */
+        IPV6_SRC,
+
+        /**
+         * IPv6 dst modification.
+         */
+        IPV6_DST,
+
+        /**
+         * IPv6 flow label modification.
+         */
+        IPV6_FLABEL,
+
+        /**
+         * Decrement TTL.
          */
         DEC_TTL,
 
@@ -120,6 +135,65 @@
     }
 
     /**
+     * Represents a L3 IPv6 Flow Label (RFC 6437) modification instruction
+     * (20 bits unsigned integer).
+     */
+    public static final class ModIPv6FlowLabelInstruction
+        extends L3ModificationInstruction {
+        private static final int MASK = 0xfffff;
+        private final int flowLabel;            // IPv6 flow label: 20 bits
+
+        /**
+         * Constructor.
+         *
+         * flowLabel the IPv6 flow label to set in the treatment (20 bits)
+         */
+        public ModIPv6FlowLabelInstruction(int flowLabel) {
+            this.flowLabel = flowLabel & MASK;
+        }
+
+        @Override
+        public L3SubType subtype() {
+            return L3SubType.IPV6_FLABEL;
+        }
+
+        /**
+         * Gets the IPv6 flow label to set in the treatment.
+         *
+         * @return the IPv6 flow label to set in the treatment (20 bits)
+         */
+        public int flowLabel() {
+            return this.flowLabel;
+        }
+
+        @Override
+        public String toString() {
+            return toStringHelper(subtype().toString())
+                .add("flowLabel", Long.toHexString(flowLabel)).toString();
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(type(), subtype(), flowLabel);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof ModIPv6FlowLabelInstruction) {
+                ModIPv6FlowLabelInstruction that =
+                    (ModIPv6FlowLabelInstruction) obj;
+                return  Objects.equals(flowLabel, that.flowLabel) &&
+                        Objects.equals(this.type(), that.type()) &&
+                        Objects.equals(this.subtype(), that.subtype());
+            }
+            return false;
+        }
+    }
+
+    /**
      * Represents a L3 TTL modification instruction.
      */
     public static final class ModTtlInstruction extends L3ModificationInstruction {