(ONOS-684) Added a few new OF actions, which are required for Segment Routing Application
 - MPLS POP (Ethernet type)
 - Dec MPLS TTL
 - Dec NW TTL
 - Copy TTL In
 - Copy TTL Out

Change-Id: I639a1bfff9ba3ae8c372c0a4b36f132cb2610b7b
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
index 638f00d..90f8c4e 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -196,6 +196,21 @@
         }
 
         @Override
+        public Builder decNwTtl() {
+            return add(Instructions.decNwTtl());
+        }
+
+        @Override
+        public Builder copyTtlIn() {
+            return add(Instructions.copyTtlIn());
+        }
+
+        @Override
+        public Builder copyTtlOut() {
+            return add(Instructions.copyTtlOut());
+        }
+
+        @Override
         public Builder pushMpls() {
             return add(Instructions.pushMpls());
         }
@@ -205,6 +220,10 @@
             return add(Instructions.popMpls());
         }
 
+        @Override
+        public Builder popMpls(short etherType) {
+            return add(Instructions.popMpls(etherType));
+        }
 
         @Override
         public Builder setMpls(Integer mplsLabel) {
@@ -212,6 +231,11 @@
         }
 
         @Override
+        public Builder decMplsTtl() {
+            return add(Instructions.decMplsTtl());
+        }
+
+        @Override
         public Builder setLambda(short lambda) {
             return add(Instructions.modL0Lambda(lambda));
         }
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 e7eb85d..da682ee 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
@@ -119,6 +119,27 @@
         public Builder setIpDst(IpAddress addr);
 
         /**
+         * Decrease the TTL in IP header by one.
+         *
+         * @return a treatment builder
+         */
+        public Builder decNwTtl();
+
+        /**
+         * Copy the TTL to outer protocol layer.
+         *
+         * @return a treatment builder
+         */
+        public Builder copyTtlOut();
+
+        /**
+         * Copy the TTL to inner protocol layer.
+         *
+         * @return a treatment builder
+         */
+        public Builder copyTtlIn();
+
+        /**
          * Push MPLS ether type.
          *
          * @return a treatment builder.
@@ -133,6 +154,14 @@
         public Builder popMpls();
 
         /**
+         * Pops MPLS ether type.
+         *
+         * @param ethType Ethernet type to set
+         * @return a treatment builder.
+         */
+        public Builder popMpls(short ethType);
+
+        /**
          * Sets the mpls label.
          *
          * @param mplsLabel MPLS label.
@@ -141,6 +170,13 @@
         public Builder setMpls(Integer mplsLabel);
 
         /**
+         * Decrement MPLS TTL.
+         *
+         * @return a treatment builder
+         */
+        public Builder decMplsTtl();
+
+        /**
          * Sets the optical channel ID or lambda.
          *
          * @param lambda optical channel ID
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 4dd2c48..6f1281f 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
@@ -28,6 +28,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.ModTtlInstruction;
 
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.IpAddress;
@@ -122,6 +123,15 @@
         checkNotNull(mplsLabel, "MPLS label cannot be null");
         return new ModMplsLabelInstruction(mplsLabel);
     }
+
+    /**
+     * Creates a MPLS TTL modification.
+     *
+     * @return a L2 Modification
+     */
+    public static L2ModificationInstruction decMplsTtl() {
+        return new ModMplsTtlInstruction();
+    }
     /**
      * Creates a L3 src modification.
      * @param addr the ip address to modify to.
@@ -143,6 +153,30 @@
     }
 
     /**
+     * Creates a L3 TTL modification.
+     * @return a L3 modification
+     */
+    public static L3ModificationInstruction decNwTtl() {
+        return new ModTtlInstruction(L3SubType.DEC_TTL);
+    }
+
+    /**
+     * Creates a L3 TTL modification.
+     * @return a L3 modification
+     */
+    public static L3ModificationInstruction copyTtlOut() {
+        return new ModTtlInstruction(L3SubType.TTL_OUT);
+    }
+
+    /**
+     * Creates a L3 TTL modification.
+     * @return a L3 modification
+     */
+    public static L3ModificationInstruction copyTtlIn() {
+        return new ModTtlInstruction(L3SubType.TTL_IN);
+    }
+
+    /**
      * Creates a mpls header instruction.
      * @return a L2 modification.
      */
@@ -160,6 +194,18 @@
                                           new Ethernet().setEtherType(Ethernet.MPLS_UNICAST));
     }
 
+    /**
+     * Creates a mpls header instruction.
+     *
+     * @param etherType Ethernet type to set
+     * @return a L2 modification.
+     */
+    public static Instruction popMpls(Short etherType) {
+        checkNotNull(etherType, "Ethernet type cannot be null");
+        return new PushHeaderInstructions(L2SubType.MPLS_POP,
+                new Ethernet().setEtherType(etherType));
+    }
+
     /*
      *  Output instructions
      */
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java
index 6baeceb..b005bfc 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java
@@ -65,7 +65,13 @@
         /**
          * MPLS Pop modification.
          */
-        MPLS_POP
+        MPLS_POP,
+
+        /**
+         * MPLS TTL modification.
+         */
+        DEC_MPLS_TTL
+
     }
 
     // TODO: Create factory class 'Instructions' that will have various factory
@@ -322,4 +328,41 @@
             return false;
         }
     }
+
+    /**
+     * Represents a MPLS label modification.
+     */
+    public static final class ModMplsTtlInstruction extends
+            L2ModificationInstruction {
+
+        public ModMplsTtlInstruction() {
+        }
+
+        @Override
+        public L2SubType subtype() {
+            return L2SubType.DEC_MPLS_TTL;
+        }
+
+        @Override
+        public String toString() {
+            return type().toString();
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(type(), L2SubType.DEC_MPLS_TTL);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof ModMplsLabelInstruction) {
+                ModMplsTtlInstruction that = (ModMplsTtlInstruction) obj;
+                return Objects.equals(this.type(), that.type());
+            }
+            return false;
+        }
+    }
 }
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 fb80557..139cc18 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
@@ -38,7 +38,22 @@
         /**
          * Ether dst modification.
          */
-        IP_DST
+        IP_DST,
+
+        /**
+         * Decrease TTL.
+         */
+        DEC_TTL,
+
+        /**
+         * Copy TTL out.
+         */
+        TTL_OUT,
+
+        /**
+         * Copy TTL in.
+         */
+        TTL_IN
 
         //TODO: remaining types
     }
@@ -102,6 +117,43 @@
             }
             return false;
         }
+    }
 
+    public static final class ModTtlInstruction extends L3ModificationInstruction {
+
+        private final L3SubType subtype;
+
+        public ModTtlInstruction(L3SubType subtype) {
+            this.subtype = subtype;
+        }
+
+        @Override
+        public L3SubType subtype() {
+            return this.subtype;
+        }
+
+        @Override
+        public String toString() {
+            return subtype().toString();
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(type(), subtype());
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof ModIPInstruction) {
+                ModIPInstruction that = (ModIPInstruction) obj;
+                return  Objects.equals(this.type(), that.type()) &&
+                        Objects.equals(this.subtype(), that.subtype());
+
+            }
+            return false;
+        }
     }
 }
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
index a78cadb..3c1e643 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -38,8 +38,14 @@
 import org.projectfloodlight.openflow.protocol.OFInstructionType;
 import org.projectfloodlight.openflow.protocol.action.OFAction;
 import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
+import org.projectfloodlight.openflow.protocol.action.OFActionCopyTtlIn;
+import org.projectfloodlight.openflow.protocol.action.OFActionCopyTtlOut;
+import org.projectfloodlight.openflow.protocol.action.OFActionDecMplsTtl;
+import org.projectfloodlight.openflow.protocol.action.OFActionDecNwTtl;
 import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls;
+import org.projectfloodlight.openflow.protocol.action.OFActionPushMpls;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
@@ -57,6 +63,7 @@
 import org.projectfloodlight.openflow.types.IPv6Address;
 import org.projectfloodlight.openflow.types.Masked;
 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
+import org.projectfloodlight.openflow.types.U32;
 import org.projectfloodlight.openflow.types.VlanPcp;
 import org.slf4j.Logger;
 
@@ -194,12 +201,34 @@
                 OFActionSetField setField = (OFActionSetField) act;
                 handleSetField(builder, setField.getField());
                 break;
+            case POP_MPLS:
+                OFActionPopMpls popMpls = (OFActionPopMpls) act;
+                builder.popMpls((short) popMpls.getEthertype().getValue());
+                break;
+            case PUSH_MPLS:
+                OFActionPushMpls pushMpls = (OFActionPushMpls) act;
+                builder.pushMpls();
+                break;
+            case COPY_TTL_IN:
+                OFActionCopyTtlIn copyTtlIn = (OFActionCopyTtlIn) act;
+                builder.copyTtlIn();
+                break;
+            case COPY_TTL_OUT:
+                OFActionCopyTtlOut copyTtlOut = (OFActionCopyTtlOut) act;
+                builder.copyTtlOut();
+                break;
+            case DEC_MPLS_TTL:
+                OFActionDecMplsTtl decMplsTtl = (OFActionDecMplsTtl) act;
+                builder.decMplsTtl();
+                break;
+            case DEC_NW_TTL:
+                OFActionDecNwTtl decNwTtl = (OFActionDecNwTtl) act;
+                builder.decNwTtl();
+                break;
             case SET_TP_DST:
             case SET_TP_SRC:
-            case POP_MPLS:
             case POP_PBB:
             case POP_VLAN:
-            case PUSH_MPLS:
             case PUSH_PBB:
             case PUSH_VLAN:
             case SET_MPLS_LABEL:
@@ -210,10 +239,6 @@
             case SET_NW_TTL:
             case SET_QUEUE:
             case STRIP_VLAN:
-            case COPY_TTL_IN:
-            case COPY_TTL_OUT:
-            case DEC_MPLS_TTL:
-            case DEC_NW_TTL:
             case ENQUEUE:
 
             case GROUP:
@@ -259,6 +284,11 @@
             OFOxm<IPv4Address> ip4src = (OFOxm<IPv4Address>) oxm;
             builder.setIpSrc(Ip4Address.valueOf(ip4src.getValue().getInt()));
             break;
+        case MPLS_LABEL:
+            @SuppressWarnings("unchecked")
+            OFOxm<U32> labelId = (OFOxm<U32>) oxm;
+            builder.setMpls((int) labelId.getValue().getValue());
+            break;
         case ARP_OP:
         case ARP_SHA:
         case ARP_SPA:
@@ -299,7 +329,6 @@
         case IP_ECN:
         case IP_PROTO:
         case METADATA:
-        case MPLS_LABEL:
         case MPLS_TC:
         case OCH_SIGID:
         case OCH_SIGID_BASIC:
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
index 64ebe0d..905cee9 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -241,8 +241,9 @@
                         (ModMplsLabelInstruction) l2m;
                 oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.label()
                                                                   .longValue()));
-
                 break;
+            case DEC_MPLS_TTL:
+                return factory().actions().decMplsTtl();
             default:
                 log.warn("Unimplemented action type {}.", l2m.subtype());
                 break;
@@ -270,6 +271,12 @@
             ip4 = ip.ip().getIp4Address();
             oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
             break;
+        case DEC_TTL:
+            return factory().actions().decNwTtl();
+        case TTL_IN:
+            return factory().actions().copyTtlIn();
+        case TTL_OUT:
+            return factory().actions().copyTtlOut();
         default:
             log.warn("Unimplemented action type {}.", l3m.subtype());
             break;