REST API related implemetations for ODU SIGID and SIGTYPE Fields in Flow Criteria and Instruction

Change-Id: I78ddc162409d377b8c55e7f8eedd9a91939ab277
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
index 4416456..453a764 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
@@ -15,8 +15,14 @@
  */
 package org.onosproject.net.flow;
 
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableSet;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+
 import org.onlab.packet.Ip6Address;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
@@ -27,13 +33,8 @@
 import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.criteria.Criterion;
 
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * Default traffic selector implementation.
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 6174cef..ac37d1f 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
@@ -15,9 +15,11 @@
  */
 package org.onosproject.net.flow;
 
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Objects;
+
 import org.onlab.packet.EthType;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
@@ -31,10 +33,9 @@
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.meter.MeterId;
 
-import java.util.List;
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 
 /**
  * Default traffic treatment implementation.
@@ -239,6 +240,7 @@
                 case GROUP:
                 case QUEUE:
                 case L0MODIFICATION:
+                case L1MODIFICATION:
                 case L2MODIFICATION:
                 case L3MODIFICATION:
                 case L4MODIFICATION:
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 c7fe8b8..91c19b7 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
@@ -15,6 +15,8 @@
  */
 package org.onosproject.net.flow;
 
+import java.util.List;
+
 import org.onlab.packet.EthType;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
@@ -27,8 +29,6 @@
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.meter.MeterId;
 
-import java.util.List;
-
 /**
  * Abstraction of network traffic treatment.
  */
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 4e0f2bd..69c5e79 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
@@ -15,6 +15,8 @@
  */
 package org.onosproject.codec.impl;
 
+import static org.onlab.util.Tools.nullIsIllegal;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -24,9 +26,13 @@
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
+import org.onlab.util.HexString;
 import org.onosproject.net.ChannelSpacing;
 import org.onosproject.net.GridType;
 import org.onosproject.net.Lambda;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalId;
+import org.onosproject.net.OduSignalType;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.criteria.Criterion;
@@ -34,8 +40,6 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
-import static org.onlab.util.Tools.nullIsIllegal;
-
 /**
  * Decode portion of the criterion codec.
  */
@@ -95,6 +99,8 @@
         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());
+        decoderMap.put(Criterion.Type.ODU_SIGID.name(), new OduSigIdDecoder());
+        decoderMap.put(Criterion.Type.ODU_SIGTYPE.name(), new OduSigTypeDecoder());
     }
 
     private class EthTypeDecoder implements CriterionDecoder {
@@ -415,7 +421,9 @@
     private class OchSigTypeDecoder implements CriterionDecoder {
         @Override
         public Criterion decodeCriterion(ObjectNode json) {
-            return null;
+            OchSignalType ochSignalType = OchSignalType.valueOf(nullIsIllegal(json.get(CriterionCodec.OCH_SIGNAL_TYPE),
+                    CriterionCodec.OCH_SIGNAL_TYPE + MISSING_MEMBER_MESSAGE).asText());
+            return Criteria.matchOchSignalType(ochSignalType);
         }
     }
 
@@ -428,6 +436,34 @@
         }
     }
 
+    private class OduSigIdDecoder implements CriterionDecoder {
+        @Override
+        public Criterion decodeCriterion(ObjectNode json) {
+            JsonNode oduSignalId = nullIsIllegal(json.get(CriterionCodec.ODU_SIGNAL_ID),
+                    CriterionCodec.TRIBUTARY_PORT_NUMBER + MISSING_MEMBER_MESSAGE);
+
+            int tributaryPortNumber = nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_PORT_NUMBER),
+                    CriterionCodec.TRIBUTARY_PORT_NUMBER + MISSING_MEMBER_MESSAGE).asInt();
+            int tributarySlotLen = nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_SLOT_LEN),
+                    CriterionCodec.TRIBUTARY_SLOT_LEN + MISSING_MEMBER_MESSAGE).asInt();
+            byte[] tributarySlotBitmap = HexString.fromHexString(
+                    nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_SLOT_BITMAP),
+                    CriterionCodec.TRIBUTARY_SLOT_BITMAP + MISSING_MEMBER_MESSAGE).asText());
+
+            return Criteria.matchOduSignalId(
+                    OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap));
+        }
+    }
+
+    private class OduSigTypeDecoder implements CriterionDecoder {
+        @Override
+        public Criterion decodeCriterion(ObjectNode json) {
+            OduSignalType oduSignalType = OduSignalType.valueOf(nullIsIllegal(json.get(CriterionCodec.ODU_SIGNAL_TYPE),
+                    CriterionCodec.ODU_SIGNAL_TYPE + MISSING_MEMBER_MESSAGE).asText());
+            return Criteria.matchOduSignalType(oduSignalType);
+        }
+    }
+
     /**
      * 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 6a97a07..14555b3 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
@@ -15,26 +15,29 @@
  */
 package org.onosproject.codec.impl;
 
+import static org.onlab.util.Tools.nullIsIllegal;
+
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
+import org.onlab.util.HexString;
 import org.onosproject.net.ChannelSpacing;
 import org.onosproject.net.GridType;
 import org.onosproject.net.Lambda;
 import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
 import org.onosproject.net.PortNumber;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
 
-import static org.onlab.util.Tools.nullIsIllegal;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 
 /**
  * Decoding portion of the instruction codec.
@@ -174,6 +177,30 @@
     }
 
     /**
+     * Decodes a Layer 1 instruction.
+     *
+     * @return instruction object decoded from the JSON
+     * @throws IllegalArgumentException if the JSON is invalid
+     */
+    private Instruction decodeL1() {
+        String subType = json.get(InstructionCodec.SUBTYPE).asText();
+        if (subType.equals(L1ModificationInstruction.L1SubType.ODU_SIGID.name())) {
+            int tributaryPortNumber = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_PORT_NUMBER),
+                    InstructionCodec.TRIBUTARY_PORT_NUMBER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
+            int tributarySlotLen = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_LEN),
+                    InstructionCodec.TRIBUTARY_SLOT_LEN + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
+            byte[] tributarySlotBitmap = null;
+            tributarySlotBitmap = HexString.fromHexString(
+                    nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_BITMAP),
+                    InstructionCodec.TRIBUTARY_SLOT_BITMAP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
+            return Instructions.modL1OduSignalId(OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen,
+                    tributarySlotBitmap));
+        }
+        throw new IllegalArgumentException("L1 Instruction subtype "
+                + subType + " is not supported");
+    }
+
+    /**
      * Decodes a Layer 4 instruction.
      *
      * @return instruction object decoded from the JSON
@@ -221,6 +248,8 @@
             return Instructions.createDrop();
         } else if (type.equals(Instruction.Type.L0MODIFICATION.name())) {
             return decodeL0();
+        } else if (type.equals(Instruction.Type.L1MODIFICATION.name())) {
+            return decodeL1();
         } else if (type.equals(Instruction.Type.L2MODIFICATION.name())) {
             return decodeL2();
         } else if (type.equals(Instruction.Type.L3MODIFICATION.name())) {
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 f7af736..8fc6bbc 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
@@ -17,8 +17,10 @@
 
 import java.util.EnumMap;
 
+import org.onlab.util.HexString;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
 import org.onosproject.net.flow.criteria.Criterion;
 import org.onosproject.net.flow.criteria.EthCriterion;
 import org.onosproject.net.flow.criteria.EthTypeCriterion;
@@ -370,12 +372,18 @@
     private static class FormatOduSignalId implements CriterionTypeFormatter {
         @Override
         public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
-            final OduSignalIdCriterion oduSignalIdCriterion =
-                    (OduSignalIdCriterion) criterion;
-            return root.put(CriterionCodec.ODU_SIGNAL_ID, oduSignalIdCriterion.oduSignalId().toString());
+            OduSignalId oduSignalId = ((OduSignalIdCriterion) criterion).oduSignalId();
+            ObjectNode child = root.putObject(CriterionCodec.ODU_SIGNAL_ID);
+
+            child.put(CriterionCodec.TRIBUTARY_PORT_NUMBER, oduSignalId.tributaryPortNumber());
+            child.put(CriterionCodec.TRIBUTARY_SLOT_LEN, oduSignalId.tributarySlotLength());
+            child.put(CriterionCodec.TRIBUTARY_SLOT_BITMAP, HexString.toHexString(oduSignalId.tributarySlotBitmap()));
+
+            return root;
         }
     }
 
+
     private static class FormatOduSignalType implements CriterionTypeFormatter {
         @Override
         public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
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 d12e4ad..2ec301d 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
@@ -15,11 +15,14 @@
  */
 package org.onosproject.codec.impl;
 
+import org.onlab.util.HexString;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
@@ -81,6 +84,36 @@
     }
 
     /**
+     * Encode an L1 modification instruction.
+     *
+     * @param result json node that the instruction attributes are added to
+     * @param instruction The L1 instruction
+     * @param context context of the request
+     */
+    private void encodeL1(ObjectNode result) {
+        L1ModificationInstruction instruction =
+                (L1ModificationInstruction) this.instruction;
+        result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
+
+        switch (instruction.subtype()) {
+        case ODU_SIGID:
+            final L1ModificationInstruction.ModOduSignalIdInstruction oduSignalIdInstruction =
+                    (L1ModificationInstruction.ModOduSignalIdInstruction) instruction;
+            OduSignalId oduSignalId = oduSignalIdInstruction.oduSignalId();
+
+            ObjectNode child = result.putObject("oduSignalId");
+
+            child.put(InstructionCodec.TRIBUTARY_PORT_NUMBER, oduSignalId.tributaryPortNumber());
+            child.put(InstructionCodec.TRIBUTARY_SLOT_LEN, oduSignalId.tributarySlotLength());
+            child.put(InstructionCodec.TRIBUTARY_SLOT_BITMAP, HexString.toHexString(oduSignalId.tributarySlotBitmap()));
+            break;
+        default:
+            log.info("Cannot convert L1 subtype of {}", instruction.subtype());
+            break;
+        }
+    }
+
+    /**
      * Encode an L2 modification instruction.
      *
      * @param result json node that the instruction attributes are added to
@@ -222,6 +255,10 @@
                 encodeL0(result);
                 break;
 
+            case L1MODIFICATION:
+                encodeL1(result);
+                break;
+
             case L2MODIFICATION:
                 encodeL2(result);
                 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 f4d5008..d7307ad 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
@@ -50,6 +50,9 @@
     protected static final String TUNNEL_ID = "tunnelId";
     protected static final String TCP_PORT = "tcpPort";
     protected static final String UDP_PORT = "udpPort";
+    protected static final String TRIBUTARY_PORT_NUMBER = "tributaryPortNumber";
+    protected static final String TRIBUTARY_SLOT_LEN = "tributarySlotLength";
+    protected static final String TRIBUTARY_SLOT_BITMAP = "tributarySlotBitmap";
 
     protected static final String MISSING_MEMBER_MESSAGE =
             " member is required in Instruction";
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
index 54e1146..86374f8 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
@@ -31,6 +31,8 @@
 import org.onosproject.net.GridType;
 import org.onosproject.net.Lambda;
 import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalId;
+import org.onosproject.net.OduSignalType;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.criteria.Criterion;
@@ -54,6 +56,10 @@
     final IpPrefix ipPrefix6 = IpPrefix.valueOf("fe80::/64");
     final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
     final TpPort tpPort = TpPort.tpPort(40000);
+    final int tributaryPortNumber = 11;
+    final int tributarySlotLen = 80;
+    final byte[] tributarySlotBitmap = new byte[] {1, 2, 3, 4, 2, 3, 4, 2, 3, 4};
+
 
     /**
      * Sets up for each test.  Creates a context and fetches the criterion
@@ -427,4 +433,31 @@
         ObjectNode result = criterionCodec.encode(criterion, context);
         assertThat(result, matchesCriterion(criterion));
     }
+
+   /**
+     * Tests Odu Signal ID criterion.
+     */
+    @Test
+    public void matchOduSignalIdTest() {
+
+        OduSignalId oduSignalId = OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap);
+
+        Criterion criterion = Criteria.matchOduSignalId(oduSignalId);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
+    /**
+     * Tests Odu Signal Type criterion.
+     */
+    @Test
+    public void matchOduSignalTypeTest() {
+
+        OduSignalType signalType = OduSignalType.ODU2;
+
+        Criterion criterion = Criteria.matchOduSignalType(signalType);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
 }
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java b/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
index bb3acad..b00632c 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
@@ -15,13 +15,14 @@
  */
 package org.onosproject.codec.impl;
 
-import com.google.common.base.Joiner;
+import java.util.Objects;
+
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onlab.util.HexString;
 import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
 import org.onosproject.net.flow.criteria.Criterion;
-
-import com.fasterxml.jackson.databind.JsonNode;
 import org.onosproject.net.flow.criteria.EthCriterion;
 import org.onosproject.net.flow.criteria.EthTypeCriterion;
 import org.onosproject.net.flow.criteria.IPCriterion;
@@ -40,6 +41,8 @@
 import org.onosproject.net.flow.criteria.MplsCriterion;
 import org.onosproject.net.flow.criteria.OchSignalCriterion;
 import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
 import org.onosproject.net.flow.criteria.PortCriterion;
 import org.onosproject.net.flow.criteria.SctpPortCriterion;
 import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -47,7 +50,8 @@
 import org.onosproject.net.flow.criteria.VlanIdCriterion;
 import org.onosproject.net.flow.criteria.VlanPcpCriterion;
 
-import java.util.Objects;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.base.Joiner;
 
 /**
  * Hamcrest matcher for criterion objects.
@@ -496,6 +500,44 @@
         return true;
     }
 
+   /**
+     * Matches an ODU signal ID criterion object.
+     *
+     * @param criterion criterion to match
+     * @return true if the JSON matches the criterion, false otherwise.
+     */
+    private boolean matchCriterion(OduSignalIdCriterion criterion) {
+        final OduSignalId oduSignal = criterion.oduSignalId();
+        final JsonNode jsonOduSignal = jsonCriterion.get(CriterionCodec.ODU_SIGNAL_ID);
+        int jsonTpn = jsonOduSignal.get(CriterionCodec.TRIBUTARY_PORT_NUMBER).intValue();
+        int jsonTsLen = jsonOduSignal.get(CriterionCodec.TRIBUTARY_SLOT_LEN).intValue();
+        byte[] jsonTributaryBitMap = HexString.fromHexString(
+                jsonOduSignal.get(CriterionCodec.TRIBUTARY_SLOT_BITMAP).asText());
+        OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, jsonTributaryBitMap);
+        if (!oduSignal.equals(jsonOduSignalId)) {
+            description.appendText("oduSignalId was " + criterion);
+            return false;
+        }
+       return true;
+    }
+
+    /**
+     * Matches an ODU signal Type criterion object.
+     *
+     * @param criterion criterion to match
+     * @return true if the JSON matches the criterion, false otherwise.
+     */
+    private boolean matchCriterion(OduSignalTypeCriterion criterion) {
+        final String signalType = criterion.signalType().name();
+        final String jsonOduSignalType = jsonCriterion.get("oduSignalType").textValue();
+        if (!signalType.equals(jsonOduSignalType)) {
+            description.appendText("signalType was " + signalType);
+            return false;
+        }
+        return true;
+    }
+
+
     @Override
     public boolean matchesSafely(JsonNode jsonCriterion,
                                  Description description) {
@@ -594,6 +636,12 @@
             case OCH_SIGTYPE:
                 return matchCriterion((OchSignalTypeCriterion) criterion);
 
+            case ODU_SIGID:
+                return matchCriterion((OduSignalIdCriterion) criterion);
+
+            case ODU_SIGTYPE:
+                return matchCriterion((OduSignalTypeCriterion) criterion);
+
             default:
                 // Don't know how to format this type
                 description.appendText("unknown criterion type " +
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
index 6c88ac1..f6a9213 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
@@ -15,6 +15,15 @@
  */
 package org.onosproject.codec.impl;
 
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.net.NetTestTools.APP_ID;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.SortedMap;
@@ -35,6 +44,8 @@
 import org.onosproject.net.GridType;
 import org.onosproject.net.Lambda;
 import org.onosproject.net.OchSignal;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalType;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.criteria.Criterion;
@@ -55,6 +66,9 @@
 import org.onosproject.net.flow.criteria.IndexedLambdaCriterion;
 import org.onosproject.net.flow.criteria.MplsCriterion;
 import org.onosproject.net.flow.criteria.OchSignalCriterion;
+import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
 import org.onosproject.net.flow.criteria.PortCriterion;
 import org.onosproject.net.flow.criteria.SctpPortCriterion;
 import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -62,9 +76,6 @@
 import org.onosproject.net.flow.criteria.UdpPortCriterion;
 import org.onosproject.net.flow.criteria.VlanIdCriterion;
 import org.onosproject.net.flow.criteria.VlanPcpCriterion;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
@@ -72,14 +83,8 @@
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
 
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.net.NetTestTools.APP_ID;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 
 /**
  * Flow rule codec unit tests.
@@ -382,7 +387,7 @@
 
         checkCommonData(rule);
 
-        assertThat(rule.selector().criteria().size(), is(33));
+        assertThat(rule.selector().criteria().size(), is(36));
 
         rule.selector().criteria()
                 .stream()
@@ -518,6 +523,25 @@
         criterion = getCriterion(Criterion.Type.TUNNEL_ID);
         assertThat(((TunnelIdCriterion) criterion).tunnelId(),
                 is(100L));
+
+        criterion = getCriterion(Criterion.Type.OCH_SIGTYPE);
+        assertThat(((OchSignalTypeCriterion) criterion).signalType(),
+                is(OchSignalType.FIXED_GRID));
+
+        criterion = getCriterion(Criterion.Type.ODU_SIGTYPE);
+        assertThat(((OduSignalTypeCriterion) criterion).signalType(),
+                is(OduSignalType.ODU4));
+
+
+        criterion = getCriterion(Criterion.Type.ODU_SIGID);
+        assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributaryPortNumber(),
+                is(1));
+
+       assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributarySlotLength(),
+                is(80));
+
+       assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributarySlotBitmap(),
+                is(new byte [] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}));
     }
 
     /**
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
index bafbc0f..f7b0261 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
@@ -15,6 +15,10 @@
  */
 package org.onosproject.codec.impl;
 
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.codec.impl.InstructionJsonMatcher.matchesInstruction;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.packet.Ip4Address;
@@ -28,26 +32,23 @@
 import org.onosproject.net.GridType;
 import org.onosproject.net.IndexedLambda;
 import org.onosproject.net.Lambda;
+import org.onosproject.net.OduSignalId;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.codec.impl.InstructionJsonMatcher.matchesInstruction;
-
 /**
  * Unit tests for Instruction codec.
  */
 public class InstructionCodecTest {
     CodecContext context;
     JsonCodec<Instruction> instructionCodec;
-
     /**
      * Sets up for each test.  Creates a context and fetches the instruction
      * codec.
@@ -122,6 +123,20 @@
     }
 
     /**
+     * Tests the encoding of mod ODU signal ID instructions.
+     */
+    @Test
+    public void modOduSignalIdInstructionTest() {
+        OduSignalId oduSignalId = OduSignalId.oduSignalId(1, 8, new byte [] {8, 0, 0, 0, 0, 0, 0, 0, 0, 0});
+        L1ModificationInstruction.ModOduSignalIdInstruction instruction =
+                (L1ModificationInstruction.ModOduSignalIdInstruction)
+                    Instructions.modL1OduSignalId(oduSignalId);
+        ObjectNode instructionJson =
+                instructionCodec.encode(instruction, context);
+        assertThat(instructionJson, matchesInstruction(instruction));
+    }
+
+    /**
      * Tests the encoding of mod ether instructions.
      */
     @Test
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java b/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
index c3cdca0..9ffb3c3 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
@@ -17,15 +17,25 @@
 
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onlab.util.HexString;
+import org.onosproject.net.OduSignalId;
 import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions.DropInstruction;
+import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
 
 import com.fasterxml.jackson.databind.JsonNode;
 
-import static org.onosproject.net.flow.instructions.Instructions.*;
-import static org.onosproject.net.flow.instructions.L0ModificationInstruction.*;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.*;
-import static org.onosproject.net.flow.instructions.L3ModificationInstruction.*;
-
 /**
  * Hamcrest matcher for instructions.
  */
@@ -133,7 +143,7 @@
     }
 
     /**
-     * Matches teh contents of a mod OCh singal instruction.
+     * Matches the contents of a mod OCh singal instruction.
      *
      * @param instructionJson JSON instruction to match
      * @param description Description object used for recording errors
@@ -184,6 +194,40 @@
     }
 
     /**
+     * Matches the contents of a mod ODU singal Id instruction.
+     *
+     * @param instructionJson JSON instruction to match
+     * @param description Description object used for recording errors
+     * @return true if contents matches, false otherwise
+     */
+    private boolean matchModOduSingalIdInstruction(JsonNode instructionJson,
+                                                   Description description) {
+        ModOduSignalIdInstruction instructionToMatch =
+                (ModOduSignalIdInstruction) instruction;
+        String jsonSubType = instructionJson.get("subtype").textValue();
+        if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
+            description.appendText("subtype was " + jsonSubType);
+            return false;
+        }
+        String jsonType = instructionJson.get("type").textValue();
+        if (!instructionToMatch.type().name().equals(jsonType)) {
+            description.appendText("type was " + jsonType);
+            return false;
+        }
+        final JsonNode jsonOduSignal = instructionJson.get("oduSignalId");
+        int jsonTpn = jsonOduSignal.get("tributaryPortNumber").intValue();
+        int jsonTsLen = jsonOduSignal.get("tributarySlotLength").intValue();
+        byte [] tributaryBitMap = HexString.fromHexString(jsonOduSignal.get("tributarySlotBitmap").asText());
+        OduSignalId  jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, tributaryBitMap);
+        if (!instructionToMatch.oduSignalId().equals(jsonOduSignalId)) {
+            description.appendText("oduSignalId was " + instructionToMatch);
+            return false;
+        }
+        return true;
+    }
+
+
+    /**
      * Matches the contents of a mod Ethernet instruction.
      *
      * @param instructionJson JSON instruction to match
@@ -416,6 +460,8 @@
                                                     description);
         } else if (instruction instanceof ModMplsLabelInstruction) {
             return matchModMplsLabelInstruction(jsonInstruction, description);
+        } else if (instruction instanceof ModOduSignalIdInstruction) {
+            return matchModOduSingalIdInstruction(jsonInstruction, description);
         } else if (instruction instanceof NoActionInstruction) {
             return true;
         }
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json b/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
index 1a96e92..ccb2e16 100644
--- a/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
@@ -38,7 +38,10 @@
             {"type":"MPLS_LABEL", "label":123},
             {"type":"IPV6_EXTHDR", "exthdrFlags":99},
             {"type":"OCH_SIGID", "lambda":122},
-            {"type":"TUNNEL_ID", "tunnelId":100}
+            {"type":"TUNNEL_ID", "tunnelId":100},
+            {"type":"OCH_SIGTYPE", "ochSignalType":"FIXED_GRID"},
+            {"type":"ODU_SIGTYPE", "oduSignalType":"ODU4"},
+            {"type":"ODU_SIGID", "oduSignalId" : {"tributaryPortNumber":1, "tributarySlotLen":80, "tributarySlotBitmap":"01:01:01:01:01:01:01:01:01:01"}}
           ]
       }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
index 137aca1..0a1af6f 100644
--- a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
+++ b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
@@ -29,9 +29,11 @@
 import org.onosproject.net.flow.criteria.MplsCriterion;
 import org.onosproject.net.flow.criteria.IPCriterion;
 import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
 import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flowobjective.DefaultForwardingObjective;
@@ -155,6 +157,7 @@
         return treatmentBuilder.build();
     }
 
+    //CHECKSTYLE:OFF
     public static TrafficSelector revertTreatmentSelector(TrafficTreatment trafficTreatment,
                                                           TrafficSelector trafficSelector) {
 
@@ -195,14 +198,30 @@
                                 } else {
                                     return null;
                                 }
-                            } else {
-                                break;
                             }
                         default:
                             break;
                     }
                     break;
                 }
+                case L1MODIFICATION: {
+                    L1ModificationInstruction l1 = (L1ModificationInstruction) instruction;
+                    switch (l1.subtype()) {
+                        case ODU_SIGID:
+                            if (criterionMap.containsKey(Criterion.Type.ODU_SIGID)) {
+                                if (((OduSignalIdCriterion) criterionMap.get((Criterion.Type.ODU_SIGID))).oduSignalId()
+                                        .equals(((L1ModificationInstruction.ModOduSignalIdInstruction) l1)
+                                                .oduSignalId())) {
+                                    criterionMap.remove(Criterion.Type.ODU_SIGID);
+                                } else {
+                                    return null;
+                                }
+                            } 
+                        default:
+                            break;
+                    }
+                    break;
+                }
                 case L2MODIFICATION: {
                     L2ModificationInstruction l2 = (L2ModificationInstruction) instruction;
                     switch (l2.subtype()) {
@@ -344,6 +363,7 @@
 
         return selectorBuilder.build();
     }
+   //CHECKSTYLE:ON
 
     public static Set<Criterion.Type> getTypeSet(TrafficSelector trafficSelector) {
         Set<Criterion.Type> typeSet = new HashSet<>();
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 5b5056c..225b95d 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -70,6 +70,7 @@
 import org.onosproject.net.OchSignal;
 import org.onosproject.net.OchSignalType;
 import org.onosproject.net.OduCltPort;
+import org.onosproject.net.OduSignalId;
 import org.onosproject.net.OduSignalType;
 import org.onosproject.net.OmsPort;
 import org.onosproject.net.Port;
@@ -118,6 +119,8 @@
 import org.onosproject.net.flow.criteria.MplsCriterion;
 import org.onosproject.net.flow.criteria.OchSignalCriterion;
 import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
 import org.onosproject.net.flow.criteria.PortCriterion;
 import org.onosproject.net.flow.criteria.SctpPortCriterion;
 import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -127,6 +130,7 @@
 import org.onosproject.net.flow.criteria.VlanPcpCriterion;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
@@ -337,6 +341,8 @@
                     IndexedLambdaCriterion.class,
                     OchSignalCriterion.class,
                     OchSignalTypeCriterion.class,
+                    OduSignalIdCriterion.class,
+                    OduSignalTypeCriterion.class,
                     Criterion.class,
                     Criterion.Type.class,
                     DefaultTrafficTreatment.class,
@@ -349,6 +355,9 @@
                     L0ModificationInstruction.L0SubType.class,
                     L0ModificationInstruction.ModLambdaInstruction.class,
                     L0ModificationInstruction.ModOchSignalInstruction.class,
+                    L1ModificationInstruction.class,
+                    L1ModificationInstruction.L1SubType.class,
+                    L1ModificationInstruction.ModOduSignalIdInstruction.class,
                     L2ModificationInstruction.class,
                     L2ModificationInstruction.L2SubType.class,
                     L2ModificationInstruction.ModEtherInstruction.class,
@@ -458,6 +467,7 @@
             .register(OduCltPort.SignalType.class)
             .register(IndexedLambda.class)
             .register(OchSignal.class)
+            .register(OduSignalId.class)
             .register(OduCltPortDescription.class)
             .register(OchPortDescription.class)
             .register(OmsPortDescription.class)