Initial import of CFM and SOAM api

Change-Id: Icf5cc2d5fb34b75460e80e8cced0d70265bcd33b
diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceAssociationCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceAssociationCodecTest.java
new file mode 100644
index 0000000..9712c7d
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceAssociationCodecTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfm.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test that the MaintenanceAssociationCodec can successfully parse Json in to a MaintenanceAssociation.
+ */
+public class MaintenanceAssociationCodecTest {
+    private static final MaIdShort MAID1_CHAR = MaIdCharStr.asMaId("ma-1");
+    private static final MaIdShort MAID2_VID = MaIdPrimaryVid.asMaId(1234);
+    private static final MaIdShort MAID3_OCTET = MaId2Octet.asMaId(12467);
+    private static final MaIdShort MAID4_RFC = MaIdRfc2685VpnId.asMaIdHex("aa:bb:cc:dd:ee:ff:99");
+    private static final MaIdShort MAID5_Y1731 = MaIdIccY1731.asMaId("abc", "defghij");
+
+
+    private ObjectMapper mapper;
+    private CfmCodecContext context;
+
+    @Before
+    public void setUp() throws Exception, CfmConfigException {
+        mapper = new ObjectMapper();
+        context = new CfmCodecContext();
+    }
+
+    @Test
+    public void testDecodeMa1() throws IOException {
+        String mdString = "{\"ma\": {    \"maName\": \"ma-1\"," +
+                "\"maNameType\": \"CHARACTERSTRING\"," +
+                "\"component-list\": [], " +
+                "\"rmep-list\": [], " +
+                "\"maNumericId\": 1}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceAssociation maDecode1 = ((MaintenanceAssociationCodec) context
+                .codec(MaintenanceAssociation.class))
+                .decode((ObjectNode) cfg, context, 10);
+        assertEquals(MAID1_CHAR, maDecode1.maId());
+        assertEquals(1, maDecode1.maNumericId());
+    }
+
+    @Test
+    public void testDecodeMa1NoTypeGiven() throws IOException {
+        String mdString = "{\"ma\": {    \"maName\": \"ma-1\"," +
+                "\"component-list\": [], " +
+                "\"rmep-list\": [], " +
+                "\"maNumericId\": 1}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceAssociation maDecode1 = ((MaintenanceAssociationCodec) context
+                .codec(MaintenanceAssociation.class))
+                .decode((ObjectNode) cfg, context, 10);
+        assertEquals(MAID1_CHAR, maDecode1.maId());
+        assertEquals(1, maDecode1.maNumericId());
+    }
+
+    @Test
+    public void testDecodeMa2() throws IOException {
+        String mdString = "{\"ma\": {    \"maName\": 1234," +
+                "\"maNameType\": \"PRIMARYVID\"," +
+                "\"component-list\": [], " +
+                "\"rmep-list\": [], " +
+                "\"maNumericId\": 2}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceAssociation maDecode2 = ((MaintenanceAssociationCodec) context
+                .codec(MaintenanceAssociation.class))
+                .decode((ObjectNode) cfg, context, 10);
+        assertEquals(MAID2_VID, maDecode2.maId());
+    }
+
+    @Test
+    public void testDecodeMa3() throws IOException {
+        String mdString = "{\"ma\": {    \"maName\": 12467," +
+                "\"maNameType\": \"TWOOCTET\"," +
+                "\"component-list\": [], " +
+                "\"rmep-list\": [], " +
+                "\"maNumericId\": 3}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceAssociation maDecode3 = ((MaintenanceAssociationCodec) context
+                .codec(MaintenanceAssociation.class))
+                .decode((ObjectNode) cfg, context, 10);
+        assertEquals(MAID3_OCTET, maDecode3.maId());
+    }
+
+    @Test
+    public void testDecodeMa4() throws IOException {
+        String mdString = "{\"ma\": {    \"maName\": \"aa:bb:cc:dd:ee:ff:99\"," +
+                "\"maNameType\": \"RFC2685VPNID\"," +
+                "\"component-list\": [], " +
+                "\"rmep-list\": [], " +
+                "\"maNumericId\": 4}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceAssociation maDecode4 = ((MaintenanceAssociationCodec) context
+                .codec(MaintenanceAssociation.class))
+                .decode((ObjectNode) cfg, context, 10);
+        assertEquals(MAID4_RFC, maDecode4.maId());
+    }
+
+    @Test
+    public void testDecodeMa5() throws IOException {
+        String mdString = "{\"ma\": {    \"maName\": \"abc:defghij\"," +
+                "\"maNameType\": \"ICCY1731\"," +
+                "\"component-list\": [], " +
+                "\"rmep-list\": [], " +
+                "\"maNumericId\": 5}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceAssociation maDecode5 = ((MaintenanceAssociationCodec) context
+                .codec(MaintenanceAssociation.class))
+                .decode((ObjectNode) cfg, context, 10);
+        assertEquals(MAID5_Y1731, maDecode5.maId());
+    }
+
+    @Test
+    public void testEncodeMa1() throws CfmConfigException {
+        MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID1_CHAR, 10)
+                .maNumericId((short) 1)
+                .build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context));
+
+        assertEquals("{\"ma\":{" +
+                "\"maName\":\"ma-1\"," +
+                "\"maNameType\":\"CHARACTERSTRING\"," +
+                "\"maNumericId\":1," +
+                "\"component-list\":[]," +
+                "\"rmep-list\":[]}}", node.toString());
+    }
+
+    @Test
+    public void testEncodeMa2() throws CfmConfigException {
+        MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID2_VID, 10)
+                .maNumericId((short) 2)
+                .build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context));
+
+        assertEquals("{\"ma\":{" +
+                "\"maName\":\"1234\"," +
+                "\"maNameType\":\"PRIMARYVID\"," +
+                "\"maNumericId\":2," +
+                "\"component-list\":[]," +
+                "\"rmep-list\":[]}}", node.toString());
+    }
+
+    @Test
+    public void testEncodeMa3() throws CfmConfigException {
+        MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID3_OCTET, 10)
+                .maNumericId((short) 3)
+                .build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context));
+
+        assertEquals("{\"ma\":{" +
+                "\"maName\":\"12467\"," +
+                "\"maNameType\":\"TWOOCTET\"," +
+                "\"maNumericId\":3," +
+                "\"component-list\":[]," +
+                "\"rmep-list\":[]}}", node.toString());
+    }
+
+    @Test
+    public void testEncodeMa4() throws CfmConfigException {
+        MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID4_RFC, 10)
+                .maNumericId((short) 4)
+                .build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context));
+
+        assertEquals("{\"ma\":{" +
+                "\"maName\":\"aa:bb:cc:dd:ee:ff:99\"," +
+                "\"maNameType\":\"RFC2685VPNID\"," +
+                "\"maNumericId\":4," +
+                "\"component-list\":[]," +
+                "\"rmep-list\":[]}}", node.toString());
+    }
+
+    @Test
+    public void testEncodeMa5() throws CfmConfigException {
+        MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID5_Y1731, 10)
+                .maNumericId((short) 5)
+                .build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context));
+
+        assertEquals("{\"ma\":{" +
+                "\"maName\":\"abc:defghij\"," +
+                "\"maNameType\":\"ICCY1731\"," +
+                "\"maNumericId\":5," +
+                "\"component-list\":[]," +
+                "\"rmep-list\":[]}}", node.toString());
+    }
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceDomainCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceDomainCodecTest.java
new file mode 100644
index 0000000..b1fff52
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceDomainCodecTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfm.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.net.InternetDomainName;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.MacAddress;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test that the MaintenanceDomainCodec can successfully parse Json in to a MaintenanceDomain.
+ */
+public class MaintenanceDomainCodecTest {
+    private static final MdId MDID1_CHAR = MdIdCharStr.asMdId("test-1");
+    private static final MdId MDID2_DOMAIN = MdIdDomainName.asMdId(
+                        InternetDomainName.from("test.opennetworking.org"));
+    private static final MdId MDID3_MACUINT =
+            MdIdMacUint.asMdId(MacAddress.valueOf("aa:bb:cc:dd:ee:ff"), 181);
+    private static final MdId MDID4_NONE = MdIdNone.asMdId();
+
+    private ObjectMapper mapper;
+    private CfmCodecContext context;
+
+    @Before
+    public void setUp() throws Exception, CfmConfigException {
+        mapper = new ObjectMapper();
+        context = new CfmCodecContext();
+    }
+
+    @Test
+    public void testDecodeMd1() throws IOException {
+        String mdString = "{\"md\": {    \"mdName\": \"test-1\"," +
+                "\"mdNameType\": \"CHARACTERSTRING\"," +
+                "\"mdLevel\": \"LEVEL1\", \"mdNumericId\": 1}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceDomain mdDecode1 = context
+                .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context);
+        assertEquals(MDID1_CHAR, mdDecode1.mdId());
+        assertEquals(MaintenanceDomain.MdLevel.LEVEL1, mdDecode1.mdLevel());
+        assertEquals(1, mdDecode1.mdNumericId());
+    }
+
+    @Test
+    public void testDecodeMd1NoTypeGiven() throws IOException {
+        String mdString = "{\"md\": {    \"mdName\": \"test-1\"," +
+                "\"mdLevel\": \"LEVEL1\", \"mdNumericId\": 1}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceDomain mdDecode1 = context
+                .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context);
+        assertEquals(MDID1_CHAR, mdDecode1.mdId());
+        assertEquals(MaintenanceDomain.MdLevel.LEVEL1, mdDecode1.mdLevel());
+        assertEquals(1, mdDecode1.mdNumericId());
+    }
+
+
+    @Test
+    public void testDecodeMd2() throws IOException {
+        String mdString = "{\"md\": {    \"mdName\": \"test.opennetworking.org\"," +
+                "\"mdNameType\": \"DOMAINNAME\"}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceDomain mdDecode1 = context
+                .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context);
+        assertEquals(MDID2_DOMAIN, mdDecode1.mdId());
+        assertEquals(MaintenanceDomain.MdLevel.LEVEL0, mdDecode1.mdLevel());
+        assertEquals(0, mdDecode1.mdNumericId());
+    }
+
+    @Test
+    public void testDecodeMd3() throws IOException {
+        String mdString = "{\"md\": {    \"mdName\": \"aa:bb:cc:dd:ee:ff:181\"," +
+                "\"mdNameType\": \"MACANDUINT\"}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceDomain mdDecode1 = context
+                .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context);
+        assertEquals(MDID3_MACUINT, mdDecode1.mdId());
+    }
+
+    @Test
+    public void testDecodeMd4() throws IOException {
+        String mdString = "{\"md\": {    \"mdName\": \"\"," +
+                "\"mdNameType\": \"NONE\"}}";
+
+        InputStream input = new ByteArrayInputStream(
+                mdString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MaintenanceDomain mdDecode1 = context
+                .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context);
+        assertEquals(MDID4_NONE, mdDecode1.mdId());
+    }
+
+    @Test
+    public void testEncodeMd1() throws CfmConfigException {
+        MaintenanceDomain md1 = DefaultMaintenanceDomain.builder(MDID1_CHAR)
+                .mdLevel(MaintenanceDomain.MdLevel.LEVEL1)
+                .mdNumericId((short) 1)
+                .build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("md", context.codec(MaintenanceDomain.class).encode(md1, context));
+
+        assertEquals("{\"md\":{" +
+                "\"mdName\":\"test-1\"," +
+                "\"mdNameType\":\"CHARACTERSTRING\"," +
+                "\"mdLevel\":\"LEVEL1\"," +
+                "\"mdNumericId\":1," +
+                "\"maList\":[]}}", node.toString());
+    }
+
+    @Test
+    public void testEncodeMd2() throws CfmConfigException {
+        MaintenanceDomain md2 = DefaultMaintenanceDomain.builder(MDID2_DOMAIN)
+                .mdLevel(MaintenanceDomain.MdLevel.LEVEL2).build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("md", context.codec(MaintenanceDomain.class).encode(md2, context));
+
+        assertEquals("{\"md\":{" +
+                "\"mdName\":\"test.opennetworking.org\"," +
+                "\"mdNameType\":\"DOMAINNAME\"," +
+                "\"mdLevel\":\"LEVEL2\"," +
+                "\"maList\":[]}}", node.toString());
+    }
+
+    @Test
+    public void testEncodeMd3() throws CfmConfigException {
+        MaintenanceDomain md3 = DefaultMaintenanceDomain.builder(MDID3_MACUINT)
+                .mdLevel(MaintenanceDomain.MdLevel.LEVEL3).build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("md", context.codec(MaintenanceDomain.class).encode(md3, context));
+
+        assertEquals("{\"md\":{" +
+                "\"mdName\":\"AA:BB:CC:DD:EE:FF:181\"," +
+                "\"mdNameType\":\"MACANDUINT\"," +
+                "\"mdLevel\":\"LEVEL3\"," +
+                "\"maList\":[]}}", node.toString());
+    }
+
+    @Test
+    public void testEncodeMd4() throws CfmConfigException {
+        MaintenanceDomain md4 = DefaultMaintenanceDomain.builder(MDID4_NONE)
+                .mdLevel(MaintenanceDomain.MdLevel.LEVEL4).build();
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("md", context.codec(MaintenanceDomain.class).encode(md4, context));
+
+        assertEquals("{\"md\":{" +
+                "\"mdName\":\"\"," +
+                "\"mdNameType\":\"NONE\"," +
+                "\"mdLevel\":\"LEVEL4\"," +
+                "\"maList\":[]}}", node.toString());
+    }
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MepEntryCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepEntryCodecTest.java
new file mode 100644
index 0000000..ea07b8e
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepEntryCodecTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfm.web;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.MacAddress;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.MepDirection;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry.MepEntryBuilder;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Test that the MepEntryCodec can successfully parse Json in to a Mep.
+ */
+public class MepEntryCodecTest {
+    ObjectMapper mapper;
+    CfmCodecContext context;
+    MepEntry mepEntry1;
+
+    @Before
+    public void setUp() throws Exception, CfmConfigException {
+        mapper = new ObjectMapper();
+        context = new CfmCodecContext();
+        MepEntryBuilder builder = DefaultMepEntry.builder(
+                MepId.valueOf((short) 22),
+                DeviceId.deviceId("netconf:1234:830"),
+                PortNumber.portNumber(2),
+                MepDirection.UP_MEP,
+                MdIdCharStr.asMdId("md-1"),
+                MaIdCharStr.asMaId("ma-1-1"))
+            .macAddress(MacAddress.valueOf("aa:bb:cc:dd:ee:ff"));
+        builder = (MepEntryBuilder) builder
+                .administrativeState(true)
+                .cciEnabled(true)
+                .ccmLtmPriority(Priority.PRIO1);
+        mepEntry1 = builder.buildEntry();
+
+    }
+
+    @Test
+    public void testEncodeMepEntryCodecContext() {
+        ObjectNode node = mapper.createObjectNode();
+        node.set("mep", context.codec(MepEntry.class).encode(mepEntry1, context));
+
+        assertEquals(22, node.get("mep").get("mepId").asInt());
+        assertEquals("aa:bb:cc:dd:ee:ff".toUpperCase(),
+                node.get("mep").get("macAddress").asText());
+        assertTrue(node.get("mep").get("administrative-state").asBoolean());
+        assertTrue(node.get("mep").get("cci-enabled").asBoolean());
+        assertEquals(Priority.PRIO1.ordinal(),
+                node.get("mep").get("ccm-ltm-priority").asInt());
+    }
+
+    @Test
+    public void testEncodeIterableOfMepEntryCodecContext() throws CfmConfigException {
+        MepEntry mepEntry2 = DefaultMepEntry.builder(
+                MepId.valueOf((short) 33),
+                DeviceId.deviceId("netconf:4321:830"),
+                PortNumber.portNumber(1),
+                MepDirection.DOWN_MEP,
+                MdIdCharStr.asMdId("md-2"),
+                MaIdCharStr.asMaId("ma-2-2"))
+            .buildEntry();
+
+        ArrayList<MepEntry> meps = new ArrayList<>();
+        meps.add(mepEntry1);
+        meps.add(mepEntry2);
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("mep", context.codec(MepEntry.class)
+                .encode(meps, context));
+
+        Iterator<JsonNode> an = node.get("mep").elements();
+        while (an.hasNext()) {
+            JsonNode jn = an.next();
+            assertEquals("md-", jn.get("mdName").asText().substring(0, 3));
+        }
+    }
+
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbCreateCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbCreateCodecTest.java
new file mode 100644
index 0000000..e2c853a
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbCreateCodecTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfm.web;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class MepLbCreateCodecTest {
+    ObjectMapper mapper;
+    CfmCodecContext context;
+
+    @Before
+    public void setUp() throws Exception {
+        mapper = new ObjectMapper();
+        context = new CfmCodecContext();
+    }
+
+    @Test
+    public void testDecodeMepLbCreateMepId() throws JsonProcessingException, IOException {
+        String loopbackString = "{\"loopback\": {    \"remoteMepId\": 20," +
+                "\"numberMessages\": 10,    \"vlanDropEligible\": true," +
+                "\"vlanPriority\": 6,    \"dataTlvHex\": \"0A:BB:CC\" }}";
+
+        InputStream input = new ByteArrayInputStream(
+                loopbackString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MepLbCreate mepLbCreate = context
+                .codec(MepLbCreate.class).decode((ObjectNode) cfg, context);
+
+        assertNull(mepLbCreate.remoteMepAddress());
+        assertEquals(20, mepLbCreate.remoteMepId().id().shortValue());
+        assertEquals(10, mepLbCreate.numberMessages().intValue());
+        assertEquals(6, mepLbCreate.vlanPriority().ordinal());
+        assertEquals(true, mepLbCreate.vlanDropEligible());
+        assertEquals("0A:BB:CC".toLowerCase(), mepLbCreate.dataTlvHex());
+    }
+
+    @Test
+    public void testDecodeMepLbCreateMepMac() throws JsonProcessingException, IOException {
+        String loopbackString = "{\"loopback\": {    " +
+                "\"remoteMepMac\": \"AA:BB:CC:DD:EE:FF\" }}";
+        InputStream input = new ByteArrayInputStream(
+                loopbackString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MepLbCreate mepLbCreate = context
+                .codec(MepLbCreate.class).decode((ObjectNode) cfg, context);
+
+        assertNull(mepLbCreate.remoteMepId());
+        assertEquals("AA:BB:CC:DD:EE:FF", mepLbCreate.remoteMepAddress().toString());
+        assertNull(mepLbCreate.dataTlvHex());
+    }
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbEntryCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbEntryCodecTest.java
new file mode 100644
index 0000000..844e4a2
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbEntryCodecTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfm.web;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class MepLbEntryCodecTest {
+    ObjectMapper mapper;
+    CfmCodecContext context;
+
+    @Before
+    public void setUp() throws Exception {
+        mapper = new ObjectMapper();
+        context = new CfmCodecContext();
+    }
+
+    @Test
+    public void testEncodeMepLbEntryCodecContext() {
+        MepLbEntry mepLbEntry1 = DefaultMepLbEntry.builder()
+                .countLbrMacMisMatch(987654321L)
+                .countLbrReceived(987654322L)
+                .countLbrTransmitted(987654323L)
+                .countLbrValidInOrder(987654324L)
+                .countLbrValidOutOfOrder(987654325L)
+                .nextLbmIdentifier(987654326L)
+                .build();
+
+        assertEquals(987654321L, mepLbEntry1.countLbrMacMisMatch());
+        assertEquals(987654322L, mepLbEntry1.countLbrReceived());
+        assertEquals(987654323L, mepLbEntry1.countLbrTransmitted());
+        assertEquals(987654324L, mepLbEntry1.countLbrValidInOrder());
+        assertEquals(987654325L, mepLbEntry1.countLbrValidOutOfOrder());
+        assertEquals(987654326L, mepLbEntry1.nextLbmIdentifier());
+    }
+
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLtCreateCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLtCreateCodecTest.java
new file mode 100644
index 0000000..3e0ec46
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLtCreateCodecTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfm.web;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLtCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.BitSet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class MepLtCreateCodecTest {
+    ObjectMapper mapper;
+    CfmCodecContext context;
+
+    @Before
+    public void setUp() throws Exception {
+        mapper = new ObjectMapper();
+        context = new CfmCodecContext();
+    }
+
+    @Test
+    public void testDecodeMepLtCreateMepId() throws JsonProcessingException, IOException {
+        String linktraceString = "{\"linktrace\": {    " +
+                "\"remoteMepId\": 20," +
+                "\"defaultTtl\": 21," +
+                "\"transmitLtmFlags\": \"use-fdb-only\"}}";
+
+        InputStream input = new ByteArrayInputStream(
+                linktraceString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        MepLtCreate mepLtCreate = context
+                .codec(MepLtCreate.class).decode((ObjectNode) cfg, context);
+
+        assertNull(mepLtCreate.remoteMepAddress());
+        assertEquals(20, mepLtCreate.remoteMepId().id().shortValue());
+        assertEquals(21, mepLtCreate.defaultTtl().intValue());
+        assertEquals(BitSet.valueOf(new byte[]{1}), mepLtCreate.transmitLtmFlags());
+    }
+
+    @Test
+    public void testDecodeMepLtCreateInvalidTransmitLtmFlags()
+            throws JsonProcessingException, IOException {
+        String linktraceString = "{\"linktrace\": {    " +
+                "\"remoteMepId\": 20," +
+                "\"transmitLtmFlags\": \"1\"}}";
+
+        InputStream input = new ByteArrayInputStream(
+                linktraceString.getBytes(StandardCharsets.UTF_8));
+        JsonNode cfg = mapper.readTree(input);
+        try {
+            context.codec(MepLtCreate.class).decode((ObjectNode) cfg, context);
+        } catch (IllegalArgumentException e) {
+            assertEquals("Expecting value 'use-fdb-only' or '' " +
+                    "for transmitLtmFlags", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testEncodeMepLtCreate() {
+        MepId mepId1 = MepId.valueOf((short) 1);
+        MepLtCreate mepLtCreate1 = DefaultMepLtCreate
+                .builder(mepId1)
+                .defaultTtl((short) 20)
+                .transmitLtmFlags(BitSet.valueOf(new byte[]{1}))
+                .build();
+
+        ObjectMapper mapper = new ObjectMapper();
+        CfmCodecContext context = new CfmCodecContext();
+        ObjectNode node = mapper.createObjectNode();
+        node.set("linktrace", context.codec(MepLtCreate.class).encode(mepLtCreate1, context));
+
+        assertEquals("{\"linktrace\":{" +
+                "\"remoteMepId\":1," +
+                "\"defaultTtl\":20," +
+                "\"transmitLtmFlags\":\"use-fdb-only\"}}", node.toString());
+    }
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/RemoteMepEntryCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/RemoteMepEntryCodecTest.java
new file mode 100644
index 0000000..7ad77ac
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/RemoteMepEntryCodecTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfm.web;
+
+import static org.junit.Assert.assertEquals;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.MacAddress;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultRemoteMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.InterfaceStatusTlvType;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.PortStatusTlvType;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState;
+import org.onosproject.incubator.net.l2monitoring.cfm.SenderIdTlv.SenderIdTlvType;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class RemoteMepEntryCodecTest {
+    ObjectMapper mapper;
+    CfmCodecContext context;
+    RemoteMepEntry remoteMep1;
+
+    @Before
+    public void setUp() throws Exception, CfmConfigException {
+        mapper = new ObjectMapper();
+        context = new CfmCodecContext();
+        remoteMep1 = DefaultRemoteMepEntry
+                .builder(MepId.valueOf((short) 10), RemoteMepState.RMEP_OK)
+                .failedOrOkTime(Duration.ofMillis(546546546L))
+                .interfaceStatusTlvType(InterfaceStatusTlvType.IS_LOWERLAYERDOWN)
+                .macAddress(MacAddress.IPV4_MULTICAST)
+                .portStatusTlvType(PortStatusTlvType.PS_NO_STATUS_TLV)
+                .rdi(true)
+                .senderIdTlvType(SenderIdTlvType.SI_NETWORK_ADDRESS)
+                .build();
+    }
+
+    @Test
+    public void testEncodeRemoteMepEntryCodecContext() {
+        ObjectNode node = mapper.createObjectNode();
+        node.set("remoteMep", context.codec(RemoteMepEntry.class)
+                .encode(remoteMep1, context));
+
+        assertEquals(10, node.get("remoteMep").get("remoteMepId").asInt());
+    }
+
+    @Test
+    public void testEncodeIterableOfRemoteMepEntryCodecContext()
+            throws CfmConfigException {
+        RemoteMepEntry remoteMep2 = DefaultRemoteMepEntry
+                .builder(MepId.valueOf((short) 20), RemoteMepState.RMEP_IDLE)
+                .build();
+
+        ArrayList<RemoteMepEntry> remoteMeps = new ArrayList<>();
+        remoteMeps.add(remoteMep1);
+        remoteMeps.add(remoteMep2);
+
+        ObjectNode node = mapper.createObjectNode();
+        node.set("remoteMep", context.codec(RemoteMepEntry.class)
+                .encode(remoteMeps, context));
+
+        Iterator<JsonNode> an = node.get("remoteMep").elements();
+        while (an.hasNext()) {
+            JsonNode jn = an.next();
+            assertEquals("RMEP_", jn.get("remoteMepState").asText().substring(0, 5));
+        }
+    }
+}