ONOS-2581 Add codec for tunnel id

Change-Id: I6ff456b0419b427945cc53fb74fd0a91cdfa758e
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
index 8a6a729..76f621f 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
@@ -60,6 +60,7 @@
     protected static final String SPACING_MULIPLIER = "spacingMultiplier";
     protected static final String SLOT_GRANULARITY = "slotGranularity";
     protected static final String OCH_SIGNAL_ID = "ochSignalId";
+    protected static final String TUNNEL_ID = "tunnelId";
 
     @Override
     public ObjectNode encode(Criterion criterion, CodecContext context) {
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
index 1a86284..e5f8896 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
@@ -93,6 +93,7 @@
         decoderMap.put(Criterion.Type.IPV6_EXTHDR.name(), new IpV6ExthdrDecoder());
         decoderMap.put(Criterion.Type.OCH_SIGID.name(), new OchSigIdDecoder());
         decoderMap.put(Criterion.Type.OCH_SIGTYPE.name(), new OchSigTypeDecoder());
+        decoderMap.put(Criterion.Type.TUNNEL_ID.name(), new TunnelIdDecoder());
     }
 
     private class EthTypeDecoder implements CriterionDecoder {
@@ -417,6 +418,15 @@
         }
     }
 
+    private class TunnelIdDecoder implements CriterionDecoder {
+        @Override
+        public Criterion decodeCriterion(ObjectNode json) {
+            long tunnelId = nullIsIllegal(json.get(CriterionCodec.TUNNEL_ID),
+                    CriterionCodec.TUNNEL_ID + MISSING_MEMBER_MESSAGE).asLong();
+            return Criteria.matchTunnelId(tunnelId);
+        }
+    }
+
     /**
      * Decodes the JSON into a criterion object.
      *
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
index 21968c2..568fa76 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
@@ -88,6 +88,10 @@
             return Instructions.popVlan();
         } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PUSH.name())) {
             return Instructions.pushVlan();
+        } else if (subType.equals(L2ModificationInstruction.L2SubType.TUNNEL_ID.name())) {
+            long tunnelId = nullIsIllegal(json.get(InstructionCodec.TUNNEL_ID),
+                    InstructionCodec.TUNNEL_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asLong();
+            return Instructions.modTunnelId(tunnelId);
         }
         throw new IllegalArgumentException("L2 Instruction subtype "
                 + subType + " is not supported");
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
index 0783c5e..7edbd78 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
@@ -41,6 +41,7 @@
 import org.onosproject.net.flow.criteria.PortCriterion;
 import org.onosproject.net.flow.criteria.SctpPortCriterion;
 import org.onosproject.net.flow.criteria.TcpPortCriterion;
+import org.onosproject.net.flow.criteria.TunnelIdCriterion;
 import org.onosproject.net.flow.criteria.UdpPortCriterion;
 import org.onosproject.net.flow.criteria.VlanIdCriterion;
 import org.onosproject.net.flow.criteria.VlanPcpCriterion;
@@ -105,6 +106,7 @@
         formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatIpV6Exthdr());
         formatMap.put(Criterion.Type.OCH_SIGID, new FormatOchSigId());
         formatMap.put(Criterion.Type.OCH_SIGTYPE, new FormatOchSigType());
+        formatMap.put(Criterion.Type.TUNNEL_ID, new FormatTunnelId());
         formatMap.put(Criterion.Type.DUMMY, new FormatDummyType());
 
         // Currently unimplemented
@@ -116,7 +118,6 @@
         formatMap.put(Criterion.Type.MPLS_TC, new FormatUnknown());
         formatMap.put(Criterion.Type.MPLS_BOS, new FormatUnknown());
         formatMap.put(Criterion.Type.PBB_ISID, new FormatUnknown());
-        formatMap.put(Criterion.Type.TUNNEL_ID, new FormatUnknown());
         formatMap.put(Criterion.Type.UNASSIGNED_40, new FormatUnknown());
         formatMap.put(Criterion.Type.PBB_UCA, new FormatUnknown());
         formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown());
@@ -354,6 +355,15 @@
         }
     }
 
+    private static class FormatTunnelId implements CriterionTypeFormatter {
+        @Override
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
+            final TunnelIdCriterion tunnelIdCriterion =
+                    (TunnelIdCriterion) criterion;
+            return root.put(CriterionCodec.TUNNEL_ID, tunnelIdCriterion.tunnelId());
+        }
+    }
+
     private class FormatDummyType implements CriterionTypeFormatter {
 
         @Override
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
index 850334d..6927680 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
@@ -123,6 +123,12 @@
                            pushHeaderInstructions.ethernetType().toShort());
                 break;
 
+            case TUNNEL_ID:
+                final L2ModificationInstruction.ModTunnelIdInstruction modTunnelIdInstruction =
+                        (L2ModificationInstruction.ModTunnelIdInstruction) instruction;
+                result.put(InstructionCodec.TUNNEL_ID, modTunnelIdInstruction.tunnelId());
+                break;
+
             default:
                 log.info("Cannot convert L2 subtype of {}", instruction.subtype());
                 break;
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
index 6f680c8..6fa4ae0 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
@@ -47,6 +47,7 @@
     protected static final String SPACING_MULTIPLIER = "spacingMultiplier";
     protected static final String SLOT_GRANULARITY = "slotGranularity";
     protected static final String ETHERNET_TYPE = "ethernetType";
+    protected static final String TUNNEL_ID = "tunnelId";
 
     protected static final String MISSING_MEMBER_MESSAGE =
             " member is required in Instruction";