Initial import of CFM and SOAM api

Change-Id: Icf5cc2d5fb34b75460e80e8cced0d70265bcd33b
diff --git a/drivers/microsemi/BUCK b/drivers/microsemi/BUCK
index 379e63d..398fff7 100644
--- a/drivers/microsemi/BUCK
+++ b/drivers/microsemi/BUCK
@@ -13,7 +13,8 @@
     '//lib:TEST_ADAPTERS',
     '//core/api:onos-api-tests',
     '//drivers/netconf:onos-drivers-netconf-tests',
-    '//utils/osgi:onlab-osgi-tests'
+    '//utils/osgi:onlab-osgi-tests',
+    '//incubator/net:onos-incubator-net'
 ]
 
 APPS = [
diff --git a/drivers/microsemi/pom.xml b/drivers/microsemi/pom.xml
index 6459186..154768f 100644
--- a/drivers/microsemi/pom.xml
+++ b/drivers/microsemi/pom.xml
@@ -50,6 +50,11 @@
 
         <dependency>
             <groupId>org.onosproject</groupId>
+            <artifactId>onos-incubator-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
             <artifactId>onos-yang-model</artifactId>
         </dependency>
 
@@ -133,6 +138,12 @@
             <classifier>tests</classifier>
         </dependency>
 
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-incubator-net</artifactId>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java
new file mode 100755
index 0000000..df6844e
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java
@@ -0,0 +1,610 @@
+/*
+ * 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.drivers.microsemi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.time.Duration;
+import java.util.Collection;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onlab.util.HexString;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.drivers.microsemi.yang.utils.MaNameUtil;
+import org.onosproject.incubator.net.l2monitoring.cfm.Component;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultRemoteMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+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.MepLbCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry.MepLbEntryBuilder;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
+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.RemoteMepEntryBuilder;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+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.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.DomainName;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.DefaultAbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.faultalarmdefectbitstype.Bits;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.CcmIntervalEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.ComponentList;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultComponentList;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.componentlist.TagTypeEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.ContinuityCheck;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultContinuityCheck;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.InterfaceEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultMacAddressAndUint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameDomainName;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameNone;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.remotemepstatetype.RemoteMepStateTypeEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMacAddress;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMepId;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.DefaultTransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.DefaultTargetAddress;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.TargetAddress;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MacAddressAndUintStr;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MdLevelType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.VlanIdType;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of CfmMepProgrammable for Microsemi EA1000.
+ */
+public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
+    implements CfmMepProgrammable {
+
+    private static final int NUMERIC_ID_MAX = 64;
+    private static final int REMOTEMEPLIST_MIN_COUNT = 2;
+    private static final int REMOTEMEPLIST_MAX_COUNT = 9;
+    private static final int COMPONENT_LIST_SIZE = 1;
+    private static final int VIDLIST_SIZE_MIN = 1;
+    private static final int MEP_PORT_MIN = 0;
+    private static final int MEP_PORT_MAX = 1;
+    private final Logger log = getLogger(getClass());
+
+    public EA1000CfmMepProgrammable() {
+        log.debug("Loaded handler behaviour EA1000CfmMepProgrammable");
+    }
+
+    @Override
+    public boolean createMep(MdId mdName, MaIdShort maName, Mep mep)
+            throws CfmConfigException {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap()
+                        .get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        MaintenanceAssociationEndPoint yangMep = buildYangMepFromApiMep(mep);
+
+        CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class));
+        MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdName).get();
+        MaintenanceAssociation ma = cfmMdService.getMaintenanceAssociation(mdName, maName).get();
+
+        if (!ma.remoteMepIdList().contains(mep.mepId())) {
+            throw new CfmConfigException("Mep Id " + mep.mepId() +
+                    " is not present in the remote Mep list for MA " + ma.maId() +
+                    ". This is required for EA1000.");
+        } else if (md.mdNumericId() <= 0 || md.mdNumericId() > NUMERIC_ID_MAX) {
+            throw new CfmConfigException("Numeric id of MD " + mdName + " must"
+                    + " be between 1 and 64 inclusive for EA1000");
+        } else if (ma.maNumericId() <= 0 || ma.maNumericId() > NUMERIC_ID_MAX) {
+            throw new CfmConfigException("Numeric id of MA " + maName + " must"
+                    + " be between 1 and 64 inclusive for EA1000");
+        }
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+        .MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma);
+        yangMa.addToMaintenanceAssociationEndPoint(yangMep);
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
+        .mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md);
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+        try {
+            mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            log.info("Created MEP {} on device {}", mdName + "/" + maName +
+                    "/" + mep.mepId(), handler().data().deviceId());
+            return true;
+        } catch (NetconfException e) {
+            log.error("Unable to create MEP {}/{}/{} on device {}",
+                    mdName, maName, mep.mepId(), handler().data().deviceId());
+            throw new CfmConfigException("Unable to create MEP :" + e.getMessage());
+        }
+    }
+
+    @Override
+    public Collection<MepEntry> getAllMeps(MdId mdName, MaIdShort maName) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        if (handler().data().deviceId() == null) {
+            throw new CfmConfigException("Device is not ready - connecting or "
+                    + "disconnected for MEP " + mdName + "/" + maName + "/" + mepId);
+        }
+        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        try {
+            MseaCfm mseacfm =
+                    mseaCfmService.getMepFull(mdName, maName, mepId, session);
+            for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.
+                    mseacfm.mefcfm.MaintenanceDomain replyMd:mseacfm.mefCfm().maintenanceDomain()) {
+                for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.
+                        mseacfm.mefcfm.maintenancedomain.
+                        MaintenanceAssociation replyMa:replyMd.maintenanceAssociation()) {
+                    for (MaintenanceAssociationEndPoint replyMep:replyMa.maintenanceAssociationEndPoint()) {
+                        return buildApiMepEntryFromYangMep(replyMep, handler().data().deviceId(), mdName, maName);
+                    }
+                }
+            }
+            log.warn("Mep " + mepId + " not found on device " + handler().data().deviceId());
+            return null;
+        } catch (NetconfException e) {
+            log.error("Unable to get MEP {}/{}/{} on device {}",
+                    mdName, maName, mepId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to create MEP :" + e.getMessage());
+        }
+    }
+
+    @Override
+    public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
+
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        MaintenanceAssociationEndPoint mep =
+                new DefaultMaintenanceAssociationEndPoint();
+        mep.mepIdentifier(MepIdType.of(mepId.id()));
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+            .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+        yangMa.maNameAndTypeCombo(MaNameUtil.getYangMaNameFromApiMaId(maName));
+        yangMa.addToMaintenanceAssociationEndPoint(mep);
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
+            new DefaultMaintenanceDomain();
+        yangMd.mdNameAndTypeCombo(getYangMdNameFromApiMdId(mdName));
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            mseaCfmService.deleteMseaMep(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            log.info("Deleted MEP {} on device {}", mdName + "/" + maName +
+                    "/" + mepId, handler().data().deviceId());
+            return true;
+        } catch (NetconfException e) {
+            log.error("Unable to delete MEP {}/{}/{} on device {}",
+                    mdName, maName, mepId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to delete MEP :" + e.getMessage());
+        }
+
+    }
+
+    @Override
+    public void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId,
+            MepLbCreate lbCreate) throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+        Short mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId();
+        Short maNumericId =
+                mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId();
+
+        TransmitLoopbackInput lb = new DefaultTransmitLoopbackInput();
+        lb.maintenanceDomain(mdNumericId);
+        lb.maintenanceAssociation(maNumericId);
+        lb.maintenanceAssociationEndPoint(mepId.id());
+        if (lbCreate.numberMessages() != null) {
+            lb.numberOfMessages(lbCreate.numberMessages());
+        }
+        if (lbCreate.vlanDropEligible() != null) {
+            lb.vlanDropEligible(lbCreate.vlanDropEligible());
+        }
+
+        if (lbCreate.remoteMepId() != null) {
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype
+            .MepId yangMepId = new DefaultMepId();
+            yangMepId.mepId(MepIdType.of(lbCreate.remoteMepId().id()));
+            TargetAddress ta = new DefaultTargetAddress();
+            ta.addressType(yangMepId);
+            lb.targetAddress(ta);
+        } else if (lbCreate.remoteMepAddress() != null) {
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype
+            .MacAddress yangMacAddress = new DefaultMacAddress();
+            yangMacAddress.macAddress(
+                    org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes
+                    .MacAddress.of(lbCreate.remoteMepAddress().toString()));
+            TargetAddress ta = new DefaultTargetAddress();
+            ta.addressType(yangMacAddress);
+            lb.targetAddress(ta);
+        } else {
+            throw new CfmConfigException("Either a remote MEP ID or Remote MEP "
+                    + "MacAddress must be specified when calling Transmit Loopback");
+        }
+
+        if (lbCreate.dataTlvHex() != null && !lbCreate.dataTlvHex().isEmpty()) {
+            lb.dataTlv(HexString.fromHexString(lbCreate.dataTlvHex()));
+        }
+        if (lbCreate.vlanPriority() != null) {
+            lb.vlanPriority(PriorityType.of((short) lbCreate.vlanPriority().ordinal()));
+        }
+
+        try {
+            mseaCfmService.transmitLoopback(lb, session);
+            log.info("Transmit Loopback called on MEP {} on device {}",
+                    mdName + "/" + maName + "/" + mepId,
+                    handler().data().deviceId());
+        } catch (NetconfException e) {
+            throw new CfmConfigException(e);
+        }
+    }
+
+    @Override
+    public void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+        Short mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId();
+        Short maNumericId =
+                mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId();
+
+        AbortLoopbackInput lbAbort = new DefaultAbortLoopbackInput();
+        lbAbort.maintenanceDomain(mdNumericId);
+        lbAbort.maintenanceAssociation(maNumericId);
+        lbAbort.maintenanceAssociationEndPoint(mepId.id());
+
+        try {
+            mseaCfmService.abortLoopback(lbAbort, session);
+            log.info("Loopback on MEP {} on device {} aborted",
+                    mdName + "/" + maName + "/" + mepId,
+                    handler().data().deviceId());
+        } catch (NetconfException e) {
+            throw new CfmConfigException(e);
+        }
+    }
+
+    @Override
+    public void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
+            MepLtCreate ltCreate) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    private org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+            .MaintenanceDomain buildYangMdFromApiMd(MaintenanceDomain md)
+            throws CfmConfigException {
+        MdNameAndTypeCombo mdName = getYangMdNameFromApiMdId(md.mdId());
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                .MaintenanceDomain mdYang = new DefaultMaintenanceDomain();
+        mdYang.id(md.mdNumericId());
+        mdYang.mdNameAndTypeCombo(mdName);
+        mdYang.mdLevel(MdLevelType.of((short) md.mdLevel().ordinal()));
+
+        return mdYang;
+    }
+
+    protected static MdNameAndTypeCombo getYangMdNameFromApiMdId(MdId mdId)
+            throws CfmConfigException {
+        MdNameAndTypeCombo mdName;
+        if (mdId instanceof MdIdDomainName) {
+            boolean isIpAddr = false;
+            try {
+                if (IpAddress.valueOf(mdId.mdName()) != null) {
+                    isIpAddr = true;
+                }
+            } catch (IllegalArgumentException e) {
+                //continue
+            }
+            if (isIpAddr) {
+                mdName = new DefaultNameDomainName();
+                ((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion.of(
+                                org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.
+                                IpAddress.fromString(mdId.mdName())));
+            } else {
+                mdName = new DefaultNameDomainName();
+                ((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion
+                                    .of(DomainName.fromString(mdId.mdName())));
+            }
+        } else if (mdId instanceof MdIdMacUint) {
+            mdName = new DefaultMacAddressAndUint();
+            ((DefaultMacAddressAndUint) mdName).nameMacAddressAndUint(MacAddressAndUintStr.fromString(mdId.mdName()));
+        } else if (mdId instanceof MdIdNone) {
+            mdName = new DefaultNameNone();
+        } else if (mdId instanceof MdIdCharStr) {
+            mdName = new DefaultNameCharacterString();
+            ((DefaultNameCharacterString) mdName).name(Identifier45.fromString(mdId.mdName()));
+        } else {
+            throw new CfmConfigException("Unexpected error creating MD " +
+                    mdId.getClass().getSimpleName());
+        }
+        return mdName;
+    }
+
+    private org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+            .maintenancedomain.MaintenanceAssociation buildYangMaFromApiMa(
+                        MaintenanceAssociation apiMa) throws CfmConfigException {
+
+        MaNameAndTypeCombo maName = MaNameUtil.getYangMaNameFromApiMaId(apiMa.maId());
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+                .MaintenanceAssociation yamgMa = new DefaultMaintenanceAssociation();
+        yamgMa.maNameAndTypeCombo(maName);
+
+        if (apiMa.remoteMepIdList() == null || apiMa.remoteMepIdList().size() < REMOTEMEPLIST_MIN_COUNT
+                || apiMa.remoteMepIdList().size() > REMOTEMEPLIST_MAX_COUNT) {
+            throw new CfmConfigException("EA1000 requires between " +
+                    REMOTEMEPLIST_MIN_COUNT + " and " + REMOTEMEPLIST_MAX_COUNT +
+                    " remote meps in an MA");
+        }
+        for (MepId rmep:apiMa.remoteMepIdList()) {
+            yamgMa.addToRemoteMeps(MepIdType.of(rmep.id()));
+        }
+
+        if (apiMa.ccmInterval() != null) {
+            switch (apiMa.ccmInterval()) {
+            case INTERVAL_3MS:
+                yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX3_3MS);
+                break;
+            case INVERVAL_10MS:
+                yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX10MS);
+                break;
+            case INVERVAL_100MS:
+                yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX100MS);
+                break;
+            case INTERVAL_1S:
+                yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX1S);
+                break;
+            default:
+                throw new CfmConfigException("EA1000 only supports "
+                        + "3ms, 10ms, 100ms and 1s for CCM Interval. Rejecting: "
+                        + apiMa.ccmInterval().name());
+            }
+        }
+        if (apiMa.componentList() == null || apiMa.componentList().size() != COMPONENT_LIST_SIZE) {
+            throw new CfmConfigException("EA1000 supports only 1 Component in an MA");
+        }
+
+        Component maComponent = apiMa.componentList().iterator().next();
+        if (maComponent.vidList() == null || maComponent.vidList().size() < VIDLIST_SIZE_MIN) {
+            throw new CfmConfigException("EA1000 requires at least 1 VID in "
+                    + "the Component of an MA");
+        }
+        ComponentList compList = new DefaultComponentList();
+        for (VlanId vid:maComponent.vidList()) {
+            compList.addToVid(VlanIdType.of(vid.toShort()));
+        }
+
+        if (maComponent.tagType() != null) {
+            switch (maComponent.tagType()) {
+            case VLAN_STAG:
+                compList.tagType(TagTypeEnum.VLAN_STAG);
+                break;
+            case VLAN_CTAG:
+                compList.tagType(TagTypeEnum.VLAN_CTAG);
+                break;
+            case VLAN_NONE:
+            default:
+                compList.tagType(TagTypeEnum.VLAN_NONE);
+                break;
+            }
+        }
+
+        yamgMa.componentList(compList);
+        yamgMa.id(apiMa.maNumericId());
+        return yamgMa;
+    }
+
+    private MaintenanceAssociationEndPoint buildYangMepFromApiMep(Mep mep)
+            throws CfmConfigException {
+        MaintenanceAssociationEndPoint mepBuilder =
+                                    new DefaultMaintenanceAssociationEndPoint();
+        mepBuilder.mepIdentifier(MepIdType.of(mep.mepId().id()));
+        ContinuityCheck cc = new DefaultContinuityCheck();
+        cc.cciEnabled(mep.cciEnabled());
+        mepBuilder.continuityCheck(cc);
+        mepBuilder.ccmLtmPriority(
+                        PriorityType.of((short) mep.ccmLtmPriority().ordinal()));
+        mepBuilder.administrativeState(mep.administrativeState());
+
+        if (mep.direction() == MepDirection.UP_MEP) {
+            throw new CfmConfigException("EA1000 only supports DOWN Meps");
+        }
+
+        if (mep.port() == null || mep.port().toLong() < MEP_PORT_MIN
+                                    || mep.port().toLong() > MEP_PORT_MAX) {
+            throw new CfmConfigException("EA1000 has only ports 0 and 1. "
+                    + "Rejecting Port: " + mep.port());
+        }
+        mepBuilder.yangAutoPrefixInterface(
+                (mep.port().toLong() == 0) ? InterfaceEnum.ETH0 : InterfaceEnum.ETH1);
+
+        return mepBuilder;
+    }
+
+    private MepEntry buildApiMepEntryFromYangMep(
+            MaintenanceAssociationEndPoint yangMep, DeviceId deviceId,
+            MdId mdName, MaIdShort maName) throws CfmConfigException {
+        MepId mepId = MepId.valueOf((short) yangMep.mepIdentifier().uint16());
+        MepEntry.MepEntryBuilder builder = DefaultMepEntry.builder(mepId,
+                deviceId,
+                (yangMep.yangAutoPrefixInterface() == InterfaceEnum.ETH0) ?
+                        PortNumber.portNumber(0) : PortNumber.portNumber(1),
+                MepDirection.DOWN_MEP, //Always down for EA1000
+                mdName, maName);
+
+        if (yangMep.loopback() != null) {
+            MepLbEntryBuilder lbEntryBuilder = DefaultMepLbEntry.builder();
+            if (yangMep.loopback().repliesReceived() != null) {
+                lbEntryBuilder = lbEntryBuilder.countLbrReceived(
+                        yangMep.loopback().repliesReceived().uint32());
+            }
+            if (yangMep.loopback().repliesTransmitted() != null) {
+                lbEntryBuilder = lbEntryBuilder.countLbrTransmitted(
+                        yangMep.loopback().repliesTransmitted().uint32());
+            }
+            builder.loopbackAttributes(lbEntryBuilder.build());
+        }
+
+        if (yangMep.remoteMepDatabase() != null &&
+                yangMep.remoteMepDatabase().remoteMep() != null) {
+            for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                    .maintenancedomain.maintenanceassociation
+                    .maintenanceassociationendpoint.remotemepdatabase.RemoteMep
+                    rmep:yangMep.remoteMepDatabase().remoteMep()) {
+                builder = (MepEntry.MepEntryBuilder) builder.addToActiveRemoteMepList(
+                        getApiRemoteMepFromYangRemoteMep(rmep));
+            }
+        }
+
+        if (yangMep.ccmLtmPriority() != null) {
+            builder = (MepEntry.MepEntryBuilder) builder.ccmLtmPriority(
+                    Priority.values()[yangMep.ccmLtmPriority().uint8()]);
+        }
+
+        //And the the state attributes
+        builder = (MepEntry.MepEntryBuilder) builder
+                .macAddress(MacAddress.valueOf(yangMep.macAddress().toString()))
+                .administrativeState(yangMep.administrativeState())
+                .cciEnabled(yangMep.continuityCheck().cciEnabled());
+
+        AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedyangMep = yangMep
+                .augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+
+        if (augmentedyangMep != null) {
+            if (augmentedyangMep.lastDefectSent() != null) {
+                builder = (MepEntry.MepEntryBuilder) builder
+                .activeXconCcmDefect(augmentedyangMep.lastDefectSent().bits()
+                            .get(Bits.CROSS_CONNECT_CCM.bits()))
+                .activeErrorCcmDefect(augmentedyangMep.lastDefectSent().bits()
+                        .get(Bits.INVALID_CCM.bits()))
+                .activeMacStatusDefect(augmentedyangMep.lastDefectSent().bits()
+                        .get(Bits.REMOTE_MAC_ERROR.bits()))
+                .activeRdiCcmDefect(augmentedyangMep.lastDefectSent().bits()
+                        .get(Bits.REMOTE_RDI.bits()))
+                .activeRemoteCcmDefect(augmentedyangMep.lastDefectSent().bits()
+                        .get(Bits.REMOTE_INVALID_CCM.bits()));
+            }
+        }
+
+        return builder.buildEntry();
+    }
+
+    private RemoteMepEntry getApiRemoteMepFromYangRemoteMep(
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.
+            maintenanceassociation.maintenanceassociationendpoint.remotemepdatabase.
+            RemoteMep yangRemoteMep) throws CfmConfigException {
+
+        MepId remoteMepId = MepId.valueOf((short) yangRemoteMep.remoteMepId().uint16());
+        RemoteMepStateTypeEnum state = RemoteMepStateTypeEnum.FAILED;
+        if (yangRemoteMep.remoteMepState() != null) {
+            state = yangRemoteMep.remoteMepState().enumeration();
+        }
+        RemoteMepEntryBuilder rmepBuilder = DefaultRemoteMepEntry.builder(
+                    remoteMepId, RemoteMepState.valueOf("RMEP_" + state.name()))
+                .rdi(yangRemoteMep.rdi());
+        if (yangRemoteMep.macAddress() != null) {
+            rmepBuilder = rmepBuilder.macAddress(
+                    MacAddress.valueOf(yangRemoteMep.macAddress().toString()));
+        }
+        if (yangRemoteMep.failedOkTime() != null) {
+            //Currently EA1000 is reporting this as 1/1000s even though yang type
+            // is time ticks 1/100s - to be fixed
+            rmepBuilder = rmepBuilder.failedOrOkTime(Duration.ofMillis(
+                    yangRemoteMep.failedOkTime().uint32()));
+        }
+        if (yangRemoteMep.portStatusTlv() != null) {
+            rmepBuilder = rmepBuilder.portStatusTlvType(PortStatusTlvType.valueOf(
+                    "PS_" + yangRemoteMep.portStatusTlv().enumeration().name()));
+        }
+        if (yangRemoteMep.interfaceStatusTlv() != null) {
+            rmepBuilder = rmepBuilder.interfaceStatusTlvType(InterfaceStatusTlvType.valueOf(
+                    "IS_" + yangRemoteMep.interfaceStatusTlv().enumeration().name()));
+        }
+        return rmepBuilder.build();
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java
new file mode 100755
index 0000000..5a8fddb
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java
@@ -0,0 +1,740 @@
+/*
+ * 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.drivers.microsemi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Optional;
+
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService.DmEntryParts;
+import org.onosproject.drivers.microsemi.yang.utils.IetfYangTypesUtils;
+import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepTsCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.incubator.net.l2monitoring.soam.StartTime.StartTimeOption;
+import org.onosproject.incubator.net.l2monitoring.soam.StopTime.StopTimeOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatCurrent;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatHistory;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.DmEntryBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent.DmStatCurrentBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory.DmStatHistoryBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.delaymeasurementbinsgroup.bins.FrameDelay;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.delaymeasurementbinsgroup.bins.InterFrameDelayVariation;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.DefaultDelayMeasurements;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.DelayMeasurements;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DefaultDelayMeasurement;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.HistoryStats;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.MeasurementEnable;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.MessagePeriodEnum;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep.DefaultMepId;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of SoamDmProgrammable for Microsemi EA1000.
+ */
+public class EA1000SoamDmProgrammable extends AbstractHandlerBehaviour
+        implements SoamDmProgrammable {
+    private static final Logger log = getLogger(EA1000SoamDmProgrammable.class);
+    private static final int MAX_DMS = 2;
+
+    public EA1000SoamDmProgrammable() {
+        log.debug("Loaded handler behaviour EA1000SoamDmProgrammable");
+    }
+
+    @Override
+    public Collection<DelayMeasurementEntry> getAllDms(
+            MdId mdName, MaIdShort maName, MepId mepId)
+                    throws CfmConfigException, SoamConfigException {
+        return getAllDmsOrOneDm(mdName, maName, mepId, null, DmEntryParts.ALL_PARTS);
+    }
+
+    @Override
+    public DelayMeasurementEntry getDm(MdId mdName, MaIdShort maName,
+            MepId mepId, SoamId dmId) throws CfmConfigException, SoamConfigException {
+        Collection<DelayMeasurementEntry> allDms =
+                getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.ALL_PARTS);
+
+        if (allDms != null && allDms.size() >= 1) {
+            return allDms.toArray(new DelayMeasurementEntry[1])[0];
+        }
+        return null;
+    }
+
+    @Override
+    public DelayMeasurementStatCurrent getDmCurrentStat(
+            MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId)
+                    throws CfmConfigException, SoamConfigException {
+        Collection<DelayMeasurementEntry> dms =
+                getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.CURRENT_ONLY);
+
+        //There should be only one
+        if (dms != null && dms.size() == 1) {
+            return dms.toArray((new DelayMeasurementEntry[1]))[0].currentResult();
+        }
+        return null;
+    }
+
+    @Override
+    public Collection<DelayMeasurementStatHistory> getDmHistoricalStats(
+            MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId)
+                    throws CfmConfigException, SoamConfigException {
+        Collection<DelayMeasurementEntry> dms =
+                getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.HISTORY_ONLY);
+
+        //There should only be one in the result
+        if (dms != null && dms.size() == 1) {
+            return dms.toArray(new DelayMeasurementEntry[1])[0].historicalResults();
+        }
+        return new ArrayList<>();
+    }
+
+    @Override
+    public Optional<SoamId> createDm(
+            MdId mdName, MaIdShort maName, MepId mepId, DelayMeasurementCreate dm)
+            throws CfmConfigException, SoamConfigException {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        MseaCfm mepEssentials;
+        try {
+            mepEssentials = mseaCfmService.getMepEssentials(
+                                        mdName, maName, mepId, session);
+        } catch (NetconfException e) {
+            throw new CfmConfigException(e);
+        }
+        short mdNumber = mepEssentials.mefCfm().maintenanceDomain().get(0).id();
+        short maNumber = mepEssentials.mefCfm().maintenanceDomain().get(0)
+                .maintenanceAssociation().get(0).id();
+        MaintenanceAssociationEndPoint currentMep =
+                mepEssentials.mefCfm().maintenanceDomain().get(0)
+                .maintenanceAssociation().get(0)
+                .maintenanceAssociationEndPoint().get(0);
+        AugmentedMseaCfmMaintenanceAssociationEndPoint currAugMep =
+                currentMep.augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+
+        if (dm.startTime() != null && !dm.startTime().option().equals(StartTimeOption.IMMEDIATE)) {
+            throw new SoamConfigException(
+                    "Only start time: IMMEDIATE is supported on EA1000");
+        } else if (dm.stopTime() != null && !dm.stopTime().option().equals(StopTimeOption.NONE)) {
+            throw new SoamConfigException(
+                    "Only stop time: NONE is supported on EA1000");
+        }
+
+        MessagePeriodEnum mpEnum = MessagePeriodEnum.YANGAUTOPREFIX1000MS;
+        if (dm.messagePeriod() != null) {
+            if (dm.messagePeriod().toMillis() == 1000) {
+                mpEnum = MessagePeriodEnum.YANGAUTOPREFIX1000MS;
+            } else if (dm.messagePeriod().toMillis() == 100) {
+                mpEnum = MessagePeriodEnum.YANGAUTOPREFIX100MS;
+            } else if (dm.messagePeriod().toMillis() == 10) {
+                mpEnum = MessagePeriodEnum.YANGAUTOPREFIX10MS;
+            } else if (dm.messagePeriod().toMillis() == 3) {
+                mpEnum = MessagePeriodEnum.YANGAUTOPREFIX3MS;
+            } else {
+                throw new SoamConfigException("EA1000 supports only Message "
+                    + "Periods 1000ms,100ms, 10ms and 3ms for Delay Measurements");
+            }
+        }
+
+        short lastDmId = 0;
+        short newDmId = 1;
+        if (currAugMep != null && currAugMep.delayMeasurements() != null) {
+            Iterator<DelayMeasurement> dmIterator =
+                    currAugMep.delayMeasurements().delayMeasurement().iterator();
+            while (dmIterator.hasNext()) {
+                lastDmId = dmIterator.next().dmId();
+            }
+
+            if (lastDmId == 0) {
+                //Indicates that no DM was found under this MEP.
+                //We will just create the next one as 1
+                log.info("Creating DM 1");
+                newDmId = 1;
+            } else if (lastDmId == 1) {
+                log.info("Creating DM 2");
+                newDmId = 2;
+            } else if (lastDmId == MAX_DMS) {
+                log.warn("Maximum number of DMs (2) have been created on MEP {}/{}/{}"
+                        + "on device {} - delete DMs before creating more",
+                        mdName.mdName(), maName.maName(), mepId.id(),
+                        handler().data().deviceId());
+                throw new CfmConfigException("Maximum number of DMs (2) exist on MEP. "
+                        + "Please call abort on a DM before creating more");
+            }
+        }
+
+
+        DelayMeasurement dmBuilder = new DefaultDelayMeasurement();
+        dmBuilder.dmId((short) newDmId);
+        DefaultMepId dMepId = new DefaultMepId();
+        dMepId.mepId(MepIdType.of(dm.remoteMepId().id()));
+        dmBuilder.remoteMep(dMepId);
+
+        BitSet measurementEnable = getMeasurementEnabledSet(dm.measurementsEnabled());
+        if (measurementEnable != null && !measurementEnable.isEmpty()) {
+            dmBuilder.measurementEnable(measurementEnable);
+        }
+        dmBuilder.administrativeState(true);
+        dmBuilder.priority(PriorityType.of((short) dm.priority().ordinal()));
+        dmBuilder.messagePeriod(mpEnum);
+
+        if (dm.numberIntervalsStored() != null) {
+            //Here we pass in num intervals stored - for EA1000 32 are always
+            //stored so it's not controllable - instead we set number returned
+            dmBuilder.numberIntervalsReturned(dm.numberIntervalsStored());
+        }
+
+        if (dm.measurementInterval() != null) {
+            dmBuilder.measurementInterval(dm.measurementInterval().toMinutes());
+        }
+        if (dm.frameSize() != null) {
+            dmBuilder.frameSize(dm.frameSize());
+        }
+        DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+                new DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint();
+        DelayMeasurements dms = new DefaultDelayMeasurements();
+        dms.addToDelayMeasurement(dmBuilder);
+        augmentedMep.delayMeasurements(dms);
+
+        MaintenanceAssociationEndPoint mep =
+                new DefaultMaintenanceAssociationEndPoint();
+        mep.mepIdentifier(MepIdType.of(mepId.id()));
+        mep.addAugmentation(augmentedMep);
+
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+            .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+        yangMa.id(maNumber);
+        yangMa.addToMaintenanceAssociationEndPoint(mep);
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                .MaintenanceDomain yangMd = new DefaultMaintenanceDomain();
+        yangMd.id(mdNumber);
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            return Optional.empty();
+        } catch (NetconfException e) {
+            log.error("Unable to create DM {}/{}/{} on device {}",
+                    mdName, maName, mepId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to create DM :" + e.getMessage());
+        }
+
+    }
+
+    @Override
+    public void abortDm(MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId)
+            throws CfmConfigException {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap().get(handler().data()
+                .deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService = checkNotNull(handler()
+                .get(MseaCfmNetconfService.class));
+        CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class));
+
+
+        org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain
+        .maintenanceassociation.maintenanceassociationendpoint
+        .augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements
+        .DelayMeasurement dm = new DefaultDelayMeasurement();
+         dm.dmId(dmId.id().shortValue());
+
+        DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+                new DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint();
+        DelayMeasurements ddms = new DefaultDelayMeasurements();
+        ddms.addToDelayMeasurement(dm);
+        augmentedMep.delayMeasurements(ddms);
+
+        MaintenanceAssociationEndPoint mep =
+                new DefaultMaintenanceAssociationEndPoint();
+        mep.mepIdentifier(MepIdType.of(mepId.id()));
+        mep.addAugmentation(augmentedMep);
+
+
+        short mdNumericId = cfmMdService.getMaintenanceDomain(mdName).get().mdNumericId();
+        short maNumericId = cfmMdService
+                .getMaintenanceAssociation(mdName, maName).get().maNumericId();
+
+        DefaultMaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+        yangMa.id(maNumericId);
+        yangMa.addToMaintenanceAssociationEndPoint(mep);
+
+        DefaultMaintenanceDomain yangMd = new DefaultMaintenanceDomain();
+        yangMd.id(mdNumericId);
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            mseaCfmService.deleteMseaCfmDm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+        } catch (NetconfException e) {
+            log.error("Unable to delete DM {}/{}/{}/{} on device {}",
+                    mdName, maName, mepId, dm.dmId(), handler().data().deviceId());
+            throw new CfmConfigException("Unable to delete DM :" + e.getMessage());
+        }
+    }
+
+    @Override
+    public void abortDm(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void clearDelayHistoryStats(MdId mdName, MaIdShort maName,
+            MepId mepId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void clearDelayHistoryStats(MdId mdName, MaIdShort maName,
+            MepId mepId, SoamId dmId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public Collection<LossMeasurementEntry> getAllLms(MdId mdName,
+            MaIdShort maName, MepId mepId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public LossMeasurementEntry getLm(MdId mdName, MaIdShort maName,
+            MepId mepId, SoamId lmId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public LossMeasurementStatCurrent getLmCurrentStat(MdId mdName,
+            MaIdShort maName, MepId mepId, SoamId lmId) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public Collection<LossMeasurementStatCurrent> getLmHistoricalStats(
+            MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public Optional<SoamId> createLm(MdId mdName, MaIdShort maName, MepId mepId,
+                             LossMeasurementCreate lm) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void abortLm(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void abortLm(MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId)
+            throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void clearLossHistoryStats(MdId mdName, MaIdShort maName,
+            MepId mepId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void clearLossHistoryStats(MdId mdName, MaIdShort maName,
+            MepId mepId, SoamId lmId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void createTestSignal(MdId mdName, MaIdShort maName, MepId mepId,
+            MepTsCreate tsCreate) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not supported by EA1000");
+    }
+
+    @Override
+    public void abortTestSignal(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        throw new UnsupportedOperationException("Not supported by EA1000");
+    }
+
+    private static DelayMeasurementEntry buildApiDmFromYangDm(DelayMeasurement dm,
+            MdId mdName, MaIdShort maName, MepId mepId)
+                    throws SoamConfigException, CfmConfigException {
+
+        org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep
+        .MepId rmep = MepIdUtil.convertRemoteMepId(dm.remoteMep());
+
+        DmEntryBuilder dmBuilder = (DmEntryBuilder) DefaultDelayMeasurementEntry.builder(
+                SoamId.valueOf(dm.dmId()), DmType.DMDMM, Version.Y17312011,
+                MepId.valueOf((short) ((MepIdType) rmep.mepId()).uint16()),
+                Priority.values()[dm.priority().uint8()]);
+        if (dm.sessionStatus() != null) {
+            dmBuilder = dmBuilder.sessionStatus(SessionStatus.valueOf(
+                    dm.sessionStatus().enumeration().name()));
+        }
+
+        if (dm.frameDelayTwoWay() != null) {
+            dmBuilder = dmBuilder.frameDelayTwoWay(Duration.ofNanos(
+                    dm.frameDelayTwoWay().uint32() * 1000));
+        }
+        if (dm.interFrameDelayVariationTwoWay() != null) {
+            dmBuilder = dmBuilder.interFrameDelayVariationTwoWay(Duration.ofNanos(
+                    dm.interFrameDelayVariationTwoWay().uint32() * 1000));
+        }
+
+        if (dm.frameSize() != 0) {
+            dmBuilder = (DmEntryBuilder) dmBuilder.frameSize((short) dm.frameSize());
+        }
+
+        if (dm.messagePeriod() != null) {
+            switch (dm.messagePeriod()) {
+                case YANGAUTOPREFIX1000MS:
+                    dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(1000));
+                    break;
+                case YANGAUTOPREFIX100MS:
+                    dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(100));
+                    break;
+                case YANGAUTOPREFIX10MS:
+                    dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(10));
+                    break;
+                case YANGAUTOPREFIX3MS:
+                    dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(3));
+                    break;
+                default:
+                    throw new SoamConfigException("EA1000 supports only 1000,"
+                            + "100, 10 and 3ms for Message Period on DM");
+            }
+        }
+
+        Collection<MeasurementOption> moSet =
+            EA1000SoamDmProgrammable.getMeasurementOptions(dm.measurementEnable());
+        moSet.forEach(dmBuilder::addToMeasurementsEnabled);
+
+        dmBuilder = dmBuilder
+                .currentResult(buildApiDmCurrFromYangDmCurr(dm, mdName, maName, mepId));
+
+        for (DelayMeasurementStatHistory historyStat:
+                            buildApiDmHistFromYangDm(dm, mdName, maName, mepId)) {
+            dmBuilder = dmBuilder.addToHistoricalResults(historyStat);
+        }
+
+        return dmBuilder.build();
+    }
+
+    private static Collection<DelayMeasurementStatHistory> buildApiDmHistFromYangDm(
+            DelayMeasurement dm, MdId mdName, MaIdShort maName, MepId mepId)
+                    throws SoamConfigException, CfmConfigException {
+
+        Collection<DelayMeasurementStatHistory> historyStatsCollection = new ArrayList<>();
+        if (dm.historyStats() != null) {
+            for (HistoryStats dmHistory:dm.historyStats()) {
+                DmStatHistoryBuilder historyBuilder =
+                        DefaultDelayMeasurementStatHistory.builder(
+                                SoamId.valueOf((int) dmHistory.id()),
+                                Duration.ofMillis(dmHistory.elapsedTime() * 10), //Values are in 1/100th sec
+                                dmHistory.suspectStatus() != null ?
+                                        dmHistory.suspectStatus().yangAutoPrefixBoolean() : false);
+                historyBuilder = historyBuilder.endTime(
+                        IetfYangTypesUtils.fromYangDateTimeToInstant(dmHistory.endTime()));
+
+                if (dmHistory.frameDelayTwoWayMin() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .frameDelayTwoWayMin(Duration.ofNanos(dmHistory.frameDelayTwoWayMin().uint32() * 1000));
+                }
+
+                if (dmHistory.frameDelayTwoWayMax() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .frameDelayTwoWayMax(Duration.ofNanos(dmHistory.frameDelayTwoWayMax().uint32() * 1000));
+                }
+
+                if (dmHistory.frameDelayTwoWayAverage() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                           .frameDelayTwoWayAvg(Duration.ofNanos(dmHistory.frameDelayTwoWayAverage().uint32() * 1000));
+                }
+
+                if (dmHistory.interFrameDelayVariationTwoWayMin() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .interFrameDelayVariationTwoWayMin(Duration.ofNanos(
+                                    dmHistory.interFrameDelayVariationTwoWayMin().uint32() * 1000));
+                }
+
+                if (dmHistory.interFrameDelayVariationTwoWayMax() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .interFrameDelayVariationTwoWayMax(Duration.ofNanos(
+                                    dmHistory.interFrameDelayVariationTwoWayMax().uint32() * 1000));
+                }
+
+                if (dmHistory.interFrameDelayVariationTwoWayAverage() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .interFrameDelayVariationTwoWayAvg(Duration.ofNanos(
+                                    dmHistory.interFrameDelayVariationTwoWayAverage().uint32() * 1000));
+                }
+
+                if (dmHistory.soamPdusReceived() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .soamPdusReceived(Integer.valueOf((int) dmHistory.soamPdusReceived().uint32()));
+                }
+
+                if (dmHistory.bins() != null && dmHistory.bins().frameDelay() != null) {
+                    Map<Duration, Integer> frameDelayTwoWayBins = new HashMap<>();
+                    for (FrameDelay fdBin:dmHistory.bins().frameDelay()) {
+                        frameDelayTwoWayBins.put(
+                                Duration.ofNanos(fdBin.lowerBound().uint32() * 1000),
+                                Integer.valueOf((int) fdBin.counter().uint32()));
+                    }
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .frameDelayTwoWayBins(frameDelayTwoWayBins);
+                }
+
+                if (dmHistory.bins() != null && dmHistory.bins().interFrameDelayVariation() != null) {
+                    Map<Duration, Integer> ifdvTwoWayBins = new HashMap<>();
+                    for (InterFrameDelayVariation ifdvBin:dmHistory.bins().interFrameDelayVariation()) {
+                        ifdvTwoWayBins.put(
+                                Duration.ofNanos(ifdvBin.lowerBound().uint32() * 1000),
+                                Integer.valueOf((int) ifdvBin.counter().uint32()));
+                    }
+                    historyBuilder =
+                            (DmStatHistoryBuilder) historyBuilder.interFrameDelayVariationTwoWayBins(ifdvTwoWayBins);
+                }
+
+                historyStatsCollection.add((DelayMeasurementStatHistory) historyBuilder.build());
+            }
+        }
+        return historyStatsCollection;
+    }
+
+    private static DelayMeasurementStatCurrent buildApiDmCurrFromYangDmCurr(
+            DelayMeasurement dm, MdId mdName, MaIdShort maName, MepId mepId)
+                    throws SoamConfigException, CfmConfigException {
+        if (dm == null || dm.currentStats() == null || mdName == null ||
+                maName == null || mepId == null) {
+            return null;
+        }
+
+        DmStatCurrentBuilder statCurrBuilder =
+           DefaultDelayMeasurementStatCurrent.builder(
+                Duration.ofMillis(dm.currentStats().elapsedTime() * 10), //Values are in 1/100th sec
+                dm.currentStats().suspectStatus() != null ?
+                    dm.currentStats().suspectStatus().yangAutoPrefixBoolean() : false);
+        statCurrBuilder = statCurrBuilder.startTime(
+                IetfYangTypesUtils.fromYangDateTimeToInstant(dm.currentStats().startTime()));
+
+        if (dm.currentStats().frameDelayTwoWayMin() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .frameDelayTwoWayMin(Duration.ofNanos(
+                            dm.currentStats().frameDelayTwoWayMin().uint32() * 1000));
+        }
+
+        if (dm.currentStats().frameDelayTwoWayMax() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .frameDelayTwoWayMax(Duration.ofNanos(
+                            dm.currentStats().frameDelayTwoWayMax().uint32() * 1000));
+        }
+
+        if (dm.currentStats().frameDelayTwoWayAverage() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                   .frameDelayTwoWayAvg(Duration.ofNanos(
+                           dm.currentStats().frameDelayTwoWayAverage().uint32() * 1000));
+        }
+
+        if (dm.currentStats().interFrameDelayVariationTwoWayMin() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .interFrameDelayVariationTwoWayMin(Duration.ofNanos(
+                            dm.currentStats().interFrameDelayVariationTwoWayMin().uint32() * 1000));
+        }
+
+        if (dm.currentStats().interFrameDelayVariationTwoWayMax() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .interFrameDelayVariationTwoWayMax(Duration.ofNanos(
+                            dm.currentStats().interFrameDelayVariationTwoWayMax().uint32() * 1000));
+        }
+
+        if (dm.currentStats().interFrameDelayVariationTwoWayAverage() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .interFrameDelayVariationTwoWayAvg(Duration.ofNanos(
+                            dm.currentStats().interFrameDelayVariationTwoWayAverage().uint32() * 1000));
+        }
+
+        if (dm.currentStats().soamPdusReceived() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .soamPdusReceived(Integer.valueOf((int) dm.currentStats().soamPdusReceived().uint32()));
+        }
+
+        if (dm.currentStats().bins() != null && dm.currentStats().bins().frameDelay() != null) {
+            Map<Duration, Integer> frameDelayTwoWayBins = new HashMap<>();
+            for (FrameDelay fdBin:dm.currentStats().bins().frameDelay()) {
+                frameDelayTwoWayBins.put(
+                        Duration.ofNanos(fdBin.lowerBound().uint32() * 1000),
+                        Integer.valueOf((int) fdBin.counter().uint32()));
+            }
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder.frameDelayTwoWayBins(frameDelayTwoWayBins);
+        }
+
+        if (dm.currentStats().bins() != null && dm.currentStats().bins().interFrameDelayVariation() != null) {
+            Map<Duration, Integer> ifdvTwoWayBins = new HashMap<>();
+            for (InterFrameDelayVariation ifdvBin:dm.currentStats().bins().interFrameDelayVariation()) {
+                ifdvTwoWayBins.put(
+                        Duration.ofNanos(ifdvBin.lowerBound().uint32() * 1000),
+                        Integer.valueOf((int) ifdvBin.counter().uint32()));
+            }
+            statCurrBuilder =
+                    (DmStatCurrentBuilder) statCurrBuilder.interFrameDelayVariationTwoWayBins(ifdvTwoWayBins);
+        }
+
+        return (DelayMeasurementStatCurrent) statCurrBuilder.build();
+    }
+
+    private Collection<DelayMeasurementEntry> getAllDmsOrOneDm(
+            MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId, DmEntryParts parts)
+                    throws CfmConfigException, SoamConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session =
+                controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        Collection<DelayMeasurementEntry> dmResults = new ArrayList<>();
+        try {
+            MseaCfm mseacfm =
+                    mseaCfmService.getSoamDm(mdName, maName, mepId, dmId, parts, session);
+            for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                    .MaintenanceDomain replyMd:mseacfm.mefCfm().maintenanceDomain()) {
+                for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
+                        .mefcfm.maintenancedomain.MaintenanceAssociation replyMa:
+                            replyMd.maintenanceAssociation()) {
+                    for (MaintenanceAssociationEndPoint replyMep:
+                            replyMa.maintenanceAssociationEndPoint()) {
+                        AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+                                replyMep.augmentation(
+                                        DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+                        if (augmentedMep == null ||
+                                augmentedMep.delayMeasurements() == null ||
+                                augmentedMep.delayMeasurements()
+                                        .delayMeasurement().isEmpty()) {
+                            log.info("No Delay Measurements retrieved from MEP " +
+                                        mdName + "/" + maName + "/" + mepId);
+                        } else {
+                            for (org.onosproject.yang.gen.v1.mseasoampm.rev20160229
+                                    .mseasoampm.mefcfm.maintenancedomain.maintenanceassociation
+                                    .maintenanceassociationendpoint
+                                    .augmentedmseacfmmaintenanceassociationendpoint
+                                    .delaymeasurements.DelayMeasurement dm
+                                        :augmentedMep.delayMeasurements().delayMeasurement()) {
+                                dmResults.add(buildApiDmFromYangDm(dm, mdName, maName, mepId));
+                            }
+                        }
+                    }
+                }
+            }
+            return dmResults;
+        } catch (NetconfException e) {
+            log.error("Unable to get MEP {}/{}/{} on device {}",
+                    mdName, maName, mepId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to create MEP :" + e.getMessage());
+        }
+    }
+
+
+    protected static BitSet getMeasurementEnabledSet(
+            Collection<MeasurementOption> measEnabled) throws SoamConfigException {
+        BitSet measurementEnable = new BitSet();
+        try {
+            measEnabled.forEach(mo -> {
+                    MeasurementEnable me = MeasurementEnable.valueOf(mo.name());
+                    measurementEnable.set(me.measurementEnable());
+            });
+        } catch (IllegalArgumentException e) {
+            throw new SoamConfigException(
+                    "Measurement Option is not supported on EA1000: ", e);
+        }
+
+        return measurementEnable;
+    }
+
+    protected static Collection<MeasurementOption> getMeasurementOptions(BitSet meBs) {
+        Collection<MeasurementOption> meList = new ArrayList<>();
+        if (meBs != null && !meBs.isEmpty()) {
+            for (int i = 0; i < meBs.size(); i++) {
+                if (meBs.get(i)) {
+                    meList.add(MeasurementOption.valueOf(MeasurementEnable.of(i).name()));
+                }
+            }
+        }
+
+        return meList;
+    }
+}
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java
index d10b750..1bc32ca 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java
@@ -15,6 +15,10 @@
  */
 package org.onosproject.drivers.microsemi.yang;
 
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
 import org.onosproject.netconf.DatastoreId;
 import org.onosproject.netconf.NetconfException;
 import org.onosproject.netconf.NetconfSession;
@@ -34,32 +38,48 @@
 public interface MseaCfmNetconfService {
 
     /**
-     * Returns attributes of MEP.
+     * Returns minimal set of attributes of MEP.
      *
-     * @param mdName The name of the MD
-     * @param maName The name of the MA
+     * @param mdId The name of the MD
+     * @param maId The name of the MA
      * @param mepId The ID of the MEP
      * @param session An active NETCONF session
      * @return mseaCfm
      * @throws NetconfException if the session has any error
      */
-    MseaCfm getMepEssentials(String mdName, String maName, int mepId,
-            NetconfSession session) throws NetconfException;
+    MseaCfm getMepEssentials(MdId mdId, MaIdShort maId, MepId mepId,
+                             NetconfSession session) throws NetconfException;
 
+    /**
+     * Returns full set of attributes of MEP.
+     * This returns config and state attributes of all children of the MEP
+     * except for Delay Measurements and Loss Measurements - these have to be
+     * retrieved separately, because of their potential size
+     * @param mdId The name of the MD
+     * @param maId The name of the MA
+     * @param mepId The ID of the MEP
+     * @param session An active NETCONF session
+     * @return mseaCfm
+     * @throws NetconfException if the session has any error
+     */
+    MseaCfm getMepFull(MdId mdId, MaIdShort maId, MepId mepId,
+            NetconfSession session) throws NetconfException;
 
     /**
      * Returns attributes of DM.
      *
-     * @param mdName The name of the MD
-     * @param maName The name of the MA
+     * @param mdId The name of the MD
+     * @param maId The name of the MA
      * @param mepId The ID of the MEP
-     * @param dmId The Id of the Delay Measurement
+     * @param dmId The Id of the Delay Measurement - if null then all DMs
+     * @param parts The parts of the DM to return
      * @param session An active NETCONF session
      * @return mseaCfm
      * @throws NetconfException if the session has any error
      */
-    MseaCfm getSoamDm(String mdName, String maName, int mepId,
-            int dmId, NetconfSession session) throws NetconfException;
+    MseaCfm getSoamDm(MdId mdId, MaIdShort maId, MepId mepId,
+                  SoamId dmId, DmEntryParts parts, NetconfSession session)
+                    throws NetconfException;
 
     /**
      * Sets the value to attribute mseaCfm.
@@ -74,6 +94,33 @@
                        DatastoreId targetDs) throws NetconfException;
 
     /**
+     * Deletes named Meps of mseaCfm.
+     * Expects to see a list of Meps
+     *
+     * @param mseaCfm value of mseaCfm
+     * @param session An active NETCONF session
+     * @param targetDs one of running, candidate or startup
+     * @return Boolean to indicate success or failure
+     * @throws NetconfException if the session has any error
+     */
+    boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session,
+                            DatastoreId targetDs) throws NetconfException;
+
+
+    /**
+     * Deletes named delay measurements of mseaCfm.
+     * Expects to see a list of Delay Measurements
+     *
+     * @param mseaCfm value of mseaCfm
+     * @param session An active NETCONF session
+     * @param targetDs one of running, candidate or startup
+     * @return Boolean to indicate success or failure
+     * @throws NetconfException if the session has any error
+     */
+    boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session,
+                       DatastoreId targetDs) throws NetconfException;
+
+    /**
      * Service interface of transmitLoopback.
      *
      * @param inputVar input of service interface transmitLoopback
@@ -103,4 +150,10 @@
      */
     TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar,
               NetconfSession session) throws NetconfException;
+
+    public enum DmEntryParts {
+        ALL_PARTS,
+        CURRENT_ONLY,
+        HISTORY_ONLY;
+    }
 }
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
index 8339501..27c1e86 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
@@ -35,6 +35,8 @@
 import org.onosproject.netconf.DatastoreId;
 import org.onosproject.netconf.NetconfException;
 import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.CcmIntervalEnum;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.lossmeasurements.lossmeasurement.MessagePeriodEnum;
 import org.onosproject.yang.model.ModelConverter;
 import org.onosproject.yang.model.ModelObjectData;
 import org.onosproject.yang.model.ResourceData;
@@ -100,7 +102,8 @@
             Pattern.compile("(<data/>)");
     protected static final Pattern REGEX_RPC_REPLY_CLOSE =
             Pattern.compile("(</rpc-reply>)");
-
+    protected static final Pattern REGEX_RPC_OK =
+            Pattern.compile("\\R?\\s*(<ok/>)\\R?");
     @Activate
     public void activate() {
         Set<YangSerializer> yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers();
@@ -189,18 +192,65 @@
         if (moConfig == null) {
             throw new NetconfException("Query object cannot be null");
         } else if (session == null) {
-            throw new NetconfException("Session is null when calling getMseaSaFiltering()");
+            throw new NetconfException("Session is null when calling setNetconfObject()");
         } else if (targetDs == null) {
-            throw new NetconfException("TargetDs is null when calling getMseaSaFiltering()");
+            throw new NetconfException("TargetDs is null when calling setNetconfObject()");
         }
 
         String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations);
         log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
                 ":\n" + xmlQueryStr);
 
+        //Some encoded values just have to be replaced
+        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX3MS.toString(), "3ms");
+        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX10MS.toString(), "10ms");
+        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX100MS.toString(), "100ms");
+        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX1000MS.toString(), "1000ms");
+
+        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX3_3MS.toString(), "3.3ms");
+        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX10MS.toString(), "10ms");
+        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX100MS.toString(), "100ms");
+        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX1S.toString(), "1s");
+
         return session.editConfig(targetDs, null, xmlQueryStr);
     }
 
+    /**
+     * Internal method to generically call a NETCONF custom RPC from a set of YANG objects.
+     *
+     * @param customRpcInput A YANG object model
+     * @param rpcName The name of the RPC - replaces 'input' in the XML payload
+     * @param session A NETCONF session
+     * @return ModelObjectData value indicating success or failure of command
+     * @throws NetconfException if the session has any error
+     */
+    protected final ModelObjectData customRpcNetconf(
+            ModelObjectData customRpcInput, String rpcName, NetconfSession session)
+            throws NetconfException {
+        if (customRpcInput == null) {
+            throw new NetconfException("Input object cannot be null");
+        } else if (session == null) {
+            throw new NetconfException("Session is null when calling customRpcNetconf()");
+        }
+
+        String xmlQueryStr = encodeMoToXmlStr(customRpcInput, null);
+        xmlQueryStr = xmlQueryStr.replace("input", rpcName);
+        log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.doWrappedRpc(xmlQueryStr);
+        xmlResult = removeRpcReplyData(xmlResult);
+        if (REGEX_RPC_OK.matcher(xmlResult).matches()) {
+            return null;
+        }
+
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+    }
+
     protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter,
                                             List<AnnotatedNodeInfo> annotations)
             throws NetconfException {
@@ -231,8 +281,12 @@
         }
     }
 
-    protected static final String removeRpcReplyData(String rpcReplyXml) {
+    protected static final String removeRpcReplyData(String rpcReplyXml) throws NetconfException {
         rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst("");
+        if (rpcReplyXml.contains("<rpc-error")) {
+            throw new NetconfException("NETCONF rpc-error: " + rpcReplyXml);
+        }
+
         rpcReplyXml = REGEX_RPC_REPLY.matcher(rpcReplyXml).replaceFirst("");
         rpcReplyXml = REGEX_RPC_REPLY_DATA_NS.matcher(rpcReplyXml).replaceFirst("");
         rpcReplyXml = REGEX_RPC_REPLY_DATA.matcher(rpcReplyXml).replaceFirst("");
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
index 817c484..43be669 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
@@ -15,11 +15,17 @@
  */
 package org.onosproject.drivers.microsemi.yang.impl;
 
+import java.util.ArrayList;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Service;
 import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
 import org.onosproject.netconf.DatastoreId;
 import org.onosproject.netconf.NetconfException;
 import org.onosproject.netconf.NetconfSession;
@@ -27,14 +33,26 @@
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.CcmIntervalEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.lossmeasurements.lossmeasurement.MessagePeriodEnum;
 import org.onosproject.yang.model.DefaultModelObjectData;
 import org.onosproject.yang.model.ModelConverter;
 import org.onosproject.yang.model.ModelObject;
 import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
 import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
+import org.onosproject.yang.runtime.DefaultAnnotation;
 import org.onosproject.yang.runtime.DefaultCompositeStream;
 
 import java.io.ByteArrayInputStream;
@@ -49,6 +67,8 @@
 
     public static final String MSEA_CFM = "org.onosproject.drivers.microsemi.yang.mseacfmservice";
 
+    public static final String MSEA_CFM_NS = "http://www.microsemi.com/microsemi-edge-assure/msea-cfm";
+    public static final String MSEA_CFM_PM_NS = "http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm";
     @Activate
     public void activate() {
         super.activate();
@@ -63,20 +83,51 @@
     }
 
     @Override
-    public MseaCfm getMepEssentials(String mdName, String maName, int mepId,
-            NetconfSession session) throws NetconfException {
+    public MseaCfm getMepEssentials(MdId mdId, MaIdShort maId, MepId mepId,
+                                    NetconfSession session) throws NetconfException {
         if (session == null) {
             throw new NetconfException("Session is null when calling getMepEssentials()");
         }
 
-        String xmlQueryStr = buildMepQueryString(mdName, maName, mepId);
-        log.debug("Sending <get> for " +
+        String xmlQueryStr = buildMepEssentialsQueryString(mdId, maId, mepId);
+        log.debug("Sending <get> for MEP essentials" +
                 " query on NETCONF session " + session.getSessionId() +
                 ":\n" + xmlQueryStr);
 
         String xmlResult = session.get(xmlQueryStr, null);
-
         xmlResult = removeRpcReplyData(xmlResult);
+        xmlResult = removePrefixedMessagePeriod(xmlResult);
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(
+                compositeData.resourceData());
+
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        for (ModelObject mo:mod.modelObjects()) {
+            if (mo instanceof DefaultMefCfm) {
+                mseaCfm.mefCfm((DefaultMefCfm) mo);
+            }
+        }
+        return mseaCfm;
+    }
+
+    @Override
+    public MseaCfm getMepFull(MdId mdId, MaIdShort maId, MepId mepId,
+            NetconfSession session) throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getMepFull()");
+        }
+
+        String xmlQueryStr = buildMepFullQueryString(mdId, maId, mepId);
+        log.debug("Sending <get> for full MEP" +
+                " query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.get(xmlQueryStr, null);
+        xmlResult = removeRpcReplyData(xmlResult);
+        xmlResult = removePrefixedCcmInterval(xmlResult);
         DefaultCompositeStream resultDcs = new DefaultCompositeStream(
                 null, new ByteArrayInputStream(xmlResult.getBytes()));
         CompositeData compositeData = xSer.decode(resultDcs, yCtx);
@@ -94,41 +145,151 @@
     }
 
     @Override
-    public MseaCfm getSoamDm(String mdName, String maName, int mepId,
-            int dmId, NetconfSession session) throws NetconfException {
-        String xmlQueryStr = buildDmQueryString(mdName, maName, mepId, dmId);
-        throw new UnsupportedOperationException("Not yet implemented");
+    public MseaCfm getSoamDm(MdId mdName, MaIdShort maName, MepId mepId,
+                             SoamId dmId, DmEntryParts parts, NetconfSession session)
+                    throws NetconfException {
+        String xmlQueryStr = buildDmQueryString(mdName, maName, mepId, dmId, parts);
+        log.debug("Sending <get> for " +
+                " query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.get(xmlQueryStr, null);
+        xmlResult = removeRpcReplyData(xmlResult);
+        xmlResult = removePrefixedMessagePeriod(xmlResult);
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        for (ModelObject mo:mod.modelObjects()) {
+            if (mo instanceof DefaultMefCfm) {
+                mseaCfm.mefCfm((DefaultMefCfm) mo);
+            }
+        }
+
+        return mseaCfm;
     }
 
     @Override
     public boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session,
-              DatastoreId targetDs) throws NetconfException {
-        ModelObjectData moEdit = DefaultModelObjectData.builder()
-                .addModelObject(mseaCfm).build();
+            DatastoreId targetDs) throws NetconfException {
 
-        return setNetconfObject(moEdit, session, targetDs, null);
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+        return setNetconfObject(moQuery, session, targetDs, null);
     }
 
+    @Override
+    public boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session,
+                            DatastoreId targetDs) throws NetconfException {
+
+        ModelObjectData mseCfmDmList = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaCfm).build();
+
+        ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
+        if (mseaCfm != null && mseaCfm.mefCfm() != null) {
+            for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+                for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+                    for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) {
+                        AugmentedMseaCfmMaintenanceAssociationEndPoint mepAugment =
+                            mep.augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+                        if (mepAugment != null && mepAugment.delayMeasurements() != null) {
+                            for (DelayMeasurement dms:mepAugment.delayMeasurements().delayMeasurement()) {
+                                ResourceId.Builder ridBuilder = ResourceId.builder()
+                                        .addBranchPointSchema("/", null)
+                                        .addBranchPointSchema("mef-cfm", MSEA_CFM_NS)
+                                        .addBranchPointSchema("maintenance-domain", MSEA_CFM_NS)
+                                        .addKeyLeaf("id", MSEA_CFM_NS, md.id())
+                                        .addBranchPointSchema("maintenance-association", MSEA_CFM_NS)
+                                        .addKeyLeaf("id", MSEA_CFM_NS, ma.id())
+                                        .addBranchPointSchema("maintenance-association-end-point", MSEA_CFM_NS)
+                                        .addKeyLeaf("mep-id", MSEA_CFM_NS, mep.mepIdentifier())
+                                        .addBranchPointSchema("delay-measurements", MSEA_CFM_PM_NS)
+                                        .addBranchPointSchema("delay-measurement", MSEA_CFM_PM_NS)
+                                        .addKeyLeaf("dm-id", MSEA_CFM_PM_NS, mep.mepIdentifier());
+                                AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                                        .resourceId(ridBuilder.build())
+                                        .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                                        .build();
+                                anis.add(ani);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return setNetconfObject(mseCfmDmList, session, targetDs, anis);
+    }
+
+    @Override
+    public boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session,
+                                   DatastoreId targetDs) throws NetconfException {
+
+        ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+
+        ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
+        if (mseaCfm != null && mseaCfm.mefCfm() != null) {
+            for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+                for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+                    for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) {
+                        ResourceId.Builder ridBuilder = ResourceId.builder()
+                                .addBranchPointSchema("/", null)
+                                .addBranchPointSchema("mef-cfm", MSEA_CFM_NS)
+                                .addBranchPointSchema("maintenance-domain", MSEA_CFM_NS)
+                                .addBranchPointSchema("maintenance-association", MSEA_CFM_NS)
+                                .addBranchPointSchema("maintenance-association-end-point", MSEA_CFM_NS)
+                                .addKeyLeaf("mep-identifier", MSEA_CFM_NS, mep.mepIdentifier().uint16());
+                        AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                                .resourceId(ridBuilder.build())
+                                .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                                .build();
+                        anis.add(ani);
+                    }
+                }
+            }
+        }
+
+        return setNetconfObject(mseCfmMepList, session, targetDs, anis);
+    }
+
+
     /**
      * Call RPCs on the device through NETCONF.
      */
     @Override
-    public void transmitLoopback(TransmitLoopbackInput inputVar, NetconfSession session) throws NetconfException {
-        throw new UnsupportedOperationException("Not yet implemented");
+    public void transmitLoopback(TransmitLoopbackInput inputVar,
+            NetconfSession session) throws NetconfException {
+
+        ModelObjectData transLoopbackMo = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) inputVar).build();
+
+        customRpcNetconf(transLoopbackMo,
+                "transmit-loopback", session);
     }
 
     @Override
-    public void abortLoopback(AbortLoopbackInput inputVar, NetconfSession session) throws NetconfException {
-        throw new UnsupportedOperationException("Not yet implemented");
+    public void abortLoopback(AbortLoopbackInput inputVar,
+            NetconfSession session) throws NetconfException {
+        ModelObjectData abortLoopbackMo = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) inputVar).build();
+
+        customRpcNetconf(abortLoopbackMo, "abort-loopback", session);
     }
 
     @Override
-    public TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar, NetconfSession session)
+    public TransmitLinktraceOutput transmitLinktrace(
+            TransmitLinktraceInput inputVar, NetconfSession session)
             throws NetconfException {
         throw new UnsupportedOperationException("Not yet implemented");
     }
 
-    private String buildMepQueryString(String mdName, String maName, int mepId) {
+    @Deprecated //Replace this with a ModelObject defintion
+    private String buildMepEssentialsQueryString(MdId mdId, MaIdShort maId,
+            MepId mepId) {
         StringBuilder rpc = new StringBuilder();
 
         rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
@@ -136,29 +297,31 @@
         rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
         rpc.append("<maintenance-domain>\n");
         rpc.append("<id/>\n");
-        rpc.append("<name>" + mdName + "</name>\n");
-        rpc.append("<md-level/>\n");
+        rpc.append("<name>" + mdId.mdName() + "</name>\n");
         rpc.append("<maintenance-association>\n");
         rpc.append("<id/>\n");
-        rpc.append("<name>" + maName + "</name>\n");
+        rpc.append("<name>" + maId.maName() + "</name>\n");
         rpc.append("<ccm-interval>10ms</ccm-interval>\n");
         rpc.append("<remote-meps/>\n");
         rpc.append("<component-list/>\n");
         rpc.append("<maintenance-association-end-point>\n");
-        rpc.append("<mep-identifier>" + mepId + "</mep-identifier>\n");
-        rpc.append("<interface/>\n");
-        rpc.append("<primary-vid/>\n");
-        rpc.append("<administrative-state/>\n");
-        rpc.append("<ccm-ltm-priority/>\n");
-        rpc.append("<continuity-check/>\n");
+        rpc.append("<mep-identifier>" + mepId.id() + "</mep-identifier>\n");
         rpc.append("<mac-address/>\n");
-        rpc.append("<msea-soam-fm:port-status/>\n");
-        rpc.append("<msea-soam-fm:interface-status/>\n");
-        rpc.append("<msea-soam-fm:last-defect-sent/>\n");
-        rpc.append("<msea-soam-fm:rdi-transmit-status/>\n");
-        rpc.append("<loopback/>\n");
-        rpc.append("<remote-mep-database/>\n");
-        rpc.append("<linktrace/>\n");
+        rpc.append("<remote-mep-database>\n");
+        rpc.append("<remote-mep>\n");
+        rpc.append("<remote-mep-id/>\n");
+        rpc.append("</remote-mep>\n");
+        rpc.append("</remote-mep-database>\n");
+        rpc.append("<msea-soam-pm:delay-measurements>\n");
+        rpc.append("<msea-soam-pm:delay-measurement>\n");
+        rpc.append("<msea-soam-pm:dm-id/>\n");
+        rpc.append("</msea-soam-pm:delay-measurement>\n");
+        rpc.append("</msea-soam-pm:delay-measurements>\n");
+        rpc.append("<msea-soam-pm:loss-measurements>\n");
+        rpc.append("<msea-soam-pm:loss-measurement>\n");
+        rpc.append("<msea-soam-pm:lm-id/>\n");
+        rpc.append("</msea-soam-pm:loss-measurement>\n");
+        rpc.append("</msea-soam-pm:loss-measurements>\n");
         rpc.append("</maintenance-association-end-point>\n");
         rpc.append("</maintenance-association>\n");
         rpc.append("</maintenance-domain>\n");
@@ -167,8 +330,8 @@
         return rpc.toString();
     }
 
-
-    private String buildDmQueryString(String mdName, String maName, int mepId, int dmId) {
+    @Deprecated //Replace this with a ModelObject defintion
+    private String buildMepFullQueryString(MdId mdId, MaIdShort maId, MepId mepId) {
         StringBuilder rpc = new StringBuilder();
 
         rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
@@ -176,19 +339,28 @@
         rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
         rpc.append("<maintenance-domain>\n");
         rpc.append("<id/>\n");
-        rpc.append("<name>" + mdName + "</name>\n");
-        rpc.append("<md-level/>\n");
+        rpc.append("<name>" + mdId.mdName() + "</name>\n");
         rpc.append("<maintenance-association>\n");
         rpc.append("<id/>\n");
-        rpc.append("<name>" + maName + "</name>\n");
-        rpc.append("<ccm-interval>10ms</ccm-interval>\n");
+        rpc.append("<name>" + maId.maName() + "</name>\n");
         rpc.append("<maintenance-association-end-point>\n");
-        rpc.append("<mep-identifier>" + mepId + "</mep-identifier>\n");
-        rpc.append("<msea-soam-pm:delay-measurements>");
-        rpc.append("<msea-soam-pm:delay-measurement>");
-        rpc.append("<msea-soam-pm:dm-id>" + dmId + "</msea-soam-pm:dm-id>");
-        rpc.append("</msea-soam-pm:delay-measurement>");
-        rpc.append("</msea-soam-pm:delay-measurements>");
+        rpc.append("<mep-identifier>" + mepId.id() + "</mep-identifier>\n");
+        rpc.append("<interface/>\n");
+        //Direction will always be DOWN for EA1000
+        rpc.append("<primary-vid/>\n");
+        rpc.append("<administrative-state/>\n");
+        rpc.append("<mac-address/>\n");
+        rpc.append("<ccm-ltm-priority/>\n");
+        rpc.append("<continuity-check/>\n"); //Container
+        rpc.append("<loopback/>\n"); //Container
+        rpc.append("<linktrace/>\n"); //Container
+        rpc.append("<remote-mep-database/>\n"); //Container
+        rpc.append("<msea-soam-fm:operational-state/>\n");
+        rpc.append("<msea-soam-fm:connectivity-status/>\n");
+        rpc.append("<msea-soam-fm:port-status/>\n");
+        rpc.append("<msea-soam-fm:interface-status/>\n");
+        rpc.append("<msea-soam-fm:last-defect-sent/>\n");
+        rpc.append("<msea-soam-fm:rdi-transmit-status/>\n");
         rpc.append("</maintenance-association-end-point>\n");
         rpc.append("</maintenance-association>\n");
         rpc.append("</maintenance-domain>\n");
@@ -197,4 +369,95 @@
         return rpc.toString();
     }
 
+    @Deprecated //Replace this with a ModelObject defintion
+    private String buildDmQueryString(MdId mdId, MaIdShort maId, MepId mepId,
+            SoamId dmId, DmEntryParts parts) {
+        StringBuilder rpc = new StringBuilder();
+
+        rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
+        rpc.append(" xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" ");
+        rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
+        rpc.append("<maintenance-domain>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>" + mdId.mdName() + "</name>\n");
+        rpc.append("<maintenance-association>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>" + maId.maName() + "</name>\n");
+        rpc.append("<maintenance-association-end-point>\n");
+        rpc.append("<mep-identifier>" + mepId.id() + "</mep-identifier>\n");
+        if (dmId != null) {
+            rpc.append("<msea-soam-pm:delay-measurements>");
+            rpc.append("<msea-soam-pm:delay-measurement>\n");
+            rpc.append("<msea-soam-pm:dm-id>" + dmId.id() + "</msea-soam-pm:dm-id>\n");
+            rpc.append("<msea-soam-pm:mep-id/>");
+            rpc.append("<msea-soam-pm:mac-address/>");
+            rpc.append("<msea-soam-pm:administrative-state/>\n");
+            rpc.append("<msea-soam-pm:measurement-enable/>\n");
+            rpc.append("<msea-soam-pm:message-period/>\n");
+            rpc.append("<msea-soam-pm:priority/>\n");
+            rpc.append("<msea-soam-pm:frame-size/>\n");
+            rpc.append("<msea-soam-pm:measurement-interval/>\n");
+            rpc.append("<msea-soam-pm:number-intervals-stored/>\n");
+            rpc.append("<msea-soam-pm:session-status/>\n");
+            rpc.append("<msea-soam-pm:frame-delay-two-way/>\n");
+            rpc.append("<msea-soam-pm:inter-frame-delay-variation-two-way/>\n");
+            if (parts != null && (parts.equals(DmEntryParts.CURRENT_ONLY) ||
+                    parts.equals(DmEntryParts.ALL_PARTS))) {
+                rpc.append("<msea-soam-pm:current-stats/>\n");
+            }
+            if (parts != null && (parts.equals(DmEntryParts.HISTORY_ONLY) ||
+                    parts.equals(DmEntryParts.ALL_PARTS))) {
+                rpc.append("<msea-soam-pm:history-stats/>\n");
+            }
+            rpc.append("</msea-soam-pm:delay-measurement>\n");
+            rpc.append("</msea-soam-pm:delay-measurements>");
+        } else {
+            rpc.append("<msea-soam-pm:delay-measurements/>");
+        }
+        rpc.append("</maintenance-association-end-point>\n");
+        rpc.append("</maintenance-association>\n");
+        rpc.append("</maintenance-domain>\n");
+        rpc.append("</mef-cfm>");
+
+        return rpc.toString();
+    }
+
+    @Deprecated //Replace this with a ModelObject defintion
+    private String buildAbortLoopbackQueryString(Short mdId, Short maId,
+            Short mepId) {
+        StringBuilder rpc = new StringBuilder();
+
+        rpc.append("<abort-loopback xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">");
+        rpc.append("<maintenance-domain>" + mdId + "</maintenance-domain>");
+        rpc.append("<maintenance-association>" + maId + "</maintenance-association>");
+        rpc.append("<maintenance-association-end-point>" + mepId + "</maintenance-association-end-point>");
+        rpc.append("</abort-loopback>");
+
+        return rpc.toString();
+    }
+
+    private static final String removePrefixedMessagePeriod(String xmlResult) {
+        xmlResult = xmlResult.replace("message-period>3ms</",
+                "message-period>" + MessagePeriodEnum.YANGAUTOPREFIX3MS.toString() + "</");
+        xmlResult = xmlResult.replace("message-period>10ms</",
+                "message-period>" + MessagePeriodEnum.YANGAUTOPREFIX10MS.toString() + "</");
+        xmlResult = xmlResult.replace("message-period>100ms</",
+                "message-period>" + MessagePeriodEnum.YANGAUTOPREFIX100MS.toString() + "</");
+        xmlResult = xmlResult.replace("message-period>1000ms</",
+                "message-period>" + MessagePeriodEnum.YANGAUTOPREFIX1000MS.toString() + "</");
+        return xmlResult;
+    }
+
+    private static final String removePrefixedCcmInterval(String xmlResult) {
+        xmlResult = xmlResult.replace("ccm-interval>3.3ms</",
+                "ccm-interval>" + CcmIntervalEnum.YANGAUTOPREFIX3_3MS.toString() + "</");
+        xmlResult = xmlResult.replace("ccm-interval>10ms</",
+                "ccm-interval>" + CcmIntervalEnum.YANGAUTOPREFIX10MS.toString() + "</");
+        xmlResult = xmlResult.replace("ccm-interval>100ms</",
+                "ccm-interval>" + CcmIntervalEnum.YANGAUTOPREFIX100MS.toString() + "</");
+        xmlResult = xmlResult.replace("ccm-interval>1s</",
+                "ccm-interval>" + CcmIntervalEnum.YANGAUTOPREFIX1S.toString() + "</");
+        return xmlResult;
+    }
+
 }
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
index 6fec2c0..c0cba14 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
@@ -288,4 +288,4 @@
 
         return sb.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java
index ab51e75..7c67992 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.drivers.microsemi.yang.utils;
 
+import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.OffsetDateTime;
 import java.time.ZoneId;
@@ -61,4 +62,13 @@
 
         return LocalDateTime.ofInstant(odt.toInstant(), ZoneId.systemDefault());
     }
+
+    /**
+     * Convert a from Date and Time in a ietf-yang-types format to the Java Time API as an Instant.
+     * @param dateAndTime A date and time from a YANG object
+     * @return The date and time as an Instant
+     */
+    public static Instant fromYangDateTimeToInstant(DateAndTime dateAndTime) {
+        return Instant.from(OffsetDateTime.parse(dateAndTime.toString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME));
+    }
 }
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java
new file mode 100644
index 0000000..16e9686
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java
@@ -0,0 +1,73 @@
+/*
+ * 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.drivers.microsemi.yang.utils;
+
+import org.onlab.util.HexString;
+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 org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.YangIdentifier;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNamePrimaryVid;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameRfc2685VpnId;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameUint16;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameY1731Icc;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.nameprimaryvid.NamePrimaryVidUnion;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+
+/**
+ * This is a workaround for Checkstyle issue.
+ * https://github.com/checkstyle/checkstyle/issues/3850
+ * There are two types of DefaultNameCharacterString - one for MA and another for MD
+ * Putting both together in a file means that the full path has to be given which
+ * will then fail checkstyle
+ */
+public final class MaNameUtil {
+
+    private MaNameUtil() {
+        //Hidden
+    }
+
+    public static MaNameAndTypeCombo getYangMaNameFromApiMaId(MaIdShort maId)
+            throws CfmConfigException {
+        MaNameAndTypeCombo maName;
+        if (maId instanceof MaIdPrimaryVid) {
+            maName = new DefaultNamePrimaryVid();
+            ((DefaultNamePrimaryVid) maName).namePrimaryVid(NamePrimaryVidUnion.fromString(maId.maName()));
+        } else if (maId instanceof MaId2Octet) {
+            maName = new DefaultNameUint16();
+            ((DefaultNameUint16) maName).nameUint16(Integer.valueOf(maId.maName()));
+        } else if (maId instanceof MaIdRfc2685VpnId) {
+            maName = new DefaultNameRfc2685VpnId();
+            ((DefaultNameRfc2685VpnId) maName).nameRfc2685VpnId(HexString.fromHexString(maId.maName()));
+        } else if (maId instanceof MaIdIccY1731) {
+            maName = new DefaultNameY1731Icc();
+            ((DefaultNameY1731Icc) maName).nameY1731Icc(YangIdentifier.of(maId.maName()));
+        } else if (maId instanceof MaIdCharStr) {
+            maName = new DefaultNameCharacterString();
+            ((DefaultNameCharacterString) maName).name(Identifier45.fromString(maId.maName()));
+        } else {
+            throw new CfmConfigException("Unexpected error creating MD " +
+                    maId.getClass().getSimpleName());
+        }
+        return maName;
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil.java
new file mode 100644
index 0000000..cd1b9ef
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil.java
@@ -0,0 +1,46 @@
+/*
+ * 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.drivers.microsemi.yang.utils;
+
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.RemoteMep;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep.MepId;
+
+/**
+ * This is a workaround for Checkstyle issue.
+ * https://github.com/checkstyle/checkstyle/issues/3850
+ *
+ */
+public final class MepIdUtil {
+    private MepIdUtil() {
+        //Hidden
+    }
+
+    public static MepId convertRemoteMepId(RemoteMep rmep) {
+        return (MepId) rmep;
+    }
+
+    public static AugmentedMseaCfmMaintenanceAssociationEndPoint
+        convertPmAugmentedMep(MaintenanceAssociationEndPoint mep) {
+        AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+            (AugmentedMseaCfmMaintenanceAssociationEndPoint) mep
+            .augmentation(
+                    DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+        return augmentedMep;
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil2.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil2.java
new file mode 100644
index 0000000..36f3a3a
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil2.java
@@ -0,0 +1,48 @@
+/*
+ * 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.drivers.microsemi.yang.utils;
+
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.TargetAddress;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.MepId;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.MacAddress;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+
+/**
+ * This is a workaround for Checkstyle issue.
+ * https://github.com/checkstyle/checkstyle/issues/3850
+ *
+ */
+public final class MepIdUtil2 {
+    private MepIdUtil2() {
+        //Hidden
+    }
+
+    public static MepId convertTargetAddrToMepId(TargetAddress targetMep) {
+        return (MepId) targetMep.addressType();
+    }
+
+    public static MacAddress convertTargetAddrToMacAddress(TargetAddress targetMep) {
+        return (MacAddress) targetMep.addressType();
+    }
+
+    public static AugmentedMseaCfmMaintenanceAssociationEndPoint
+        convertFmAugmentedMep(MaintenanceAssociationEndPoint mep) {
+        return (AugmentedMseaCfmMaintenanceAssociationEndPoint) mep
+            .augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil3.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil3.java
new file mode 100644
index 0000000..37b6d7c
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil3.java
@@ -0,0 +1,29 @@
+/*
+ * 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.drivers.microsemi.yang.utils;
+
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.RemoteMep;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep.DefaultMepId;
+
+public final class MepIdUtil3 {
+    private MepIdUtil3() {
+        //Hidden
+    }
+
+    public static DefaultMepId convertPmRemoteMepToMepId(RemoteMep remoteMep) {
+        return (DefaultMepId) remoteMep;
+    }
+}
diff --git a/drivers/microsemi/src/main/resources/microsemi-drivers.xml b/drivers/microsemi/src/main/resources/microsemi-drivers.xml
index e8a1e9b..f1321d3 100644
--- a/drivers/microsemi/src/main/resources/microsemi-drivers.xml
+++ b/drivers/microsemi/src/main/resources/microsemi-drivers.xml
@@ -15,21 +15,23 @@
   ~ limitations under the License.
   -->
 <drivers>
-	<driver name="microsemi-netconf" extends="netconf" manufacturer="Microsemi"
-		hwVersion="EA1000">
-		<behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
-			impl="org.onosproject.drivers.microsemi.Ea1000DeviceDescription" />
-		<behaviour api="org.onosproject.net.behaviour.ConfigGetter"
-			impl="org.onosproject.drivers.microsemi.NetconfConfigGetter" />
-		<behaviour api="org.onosproject.net.behaviour.Pipeliner"
-			impl="org.onosproject.drivers.microsemi.EA1000Pipeliner" />
-		<behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
-			impl="org.onosproject.drivers.microsemi.EA1000FlowRuleProgrammable" />
-		<behaviour api="org.onosproject.net.behaviour.MeterQuery"
-			impl="org.onosproject.drivers.microsemi.FullMetersAvailable" />
-<!--         <behaviour api="org.onosproject.incubator.net.l2monitoring.cfm.CfmMepProgrammable" -->
-<!--             impl="org.onosproject.drivers.microsemi.EA1000CfmMepProgrammable"/> -->
-<!--         <behaviour api="org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable" -->
-<!--             impl="org.onosproject.drivers.microsemi.EA1000SoamDmProgrammable"/> -->
-	</driver>
+    <driver name="microsemi-netconf" extends="netconf" manufacturer="Microsemi"
+        hwVersion="EA1000">
+        <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
+            impl="org.onosproject.drivers.microsemi.Ea1000DeviceDescription" />
+        <behaviour api="org.onosproject.net.behaviour.ConfigGetter"
+            impl="org.onosproject.drivers.microsemi.NetconfConfigGetter" />
+        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
+            impl="org.onosproject.drivers.microsemi.EA1000Pipeliner" />
+        <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
+            impl="org.onosproject.drivers.microsemi.EA1000FlowRuleProgrammable" />
+        <behaviour api="org.onosproject.net.behaviour.MeterQuery"
+            impl="org.onosproject.drivers.microsemi.FullMetersAvailable" />
+        <behaviour
+            api="org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable"
+            impl="org.onosproject.drivers.microsemi.EA1000CfmMepProgrammable" />
+        <behaviour
+            api="org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable"
+            impl="org.onosproject.drivers.microsemi.EA1000SoamDmProgrammable" />
+    </driver>
 </drivers>
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java
new file mode 100644
index 0000000..1b8135c
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.drivers.microsemi;
+
+import static junit.framework.TestCase.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.onosproject.drivers.microsemi.yang.utils.MaNameUtil;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
+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.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+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.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo;
+
+/**
+ * Test of the CFM implementation on EA1000 through the incubator/net/l2monitoring interface.
+ */
+public class EA1000CfmMepProgrammableTest {
+    EA1000CfmMepProgrammable cfmProgrammable;
+    MdId mdId1 = MdIdCharStr.asMdId("md-1");
+    MaIdShort maId11 = MaIdCharStr.asMaId("ma-1-1");
+    MepId mep111 = MepId.valueOf((short) 1);
+
+    @Before
+    public void setUp() throws Exception {
+        cfmProgrammable = new EA1000CfmMepProgrammable();
+        cfmProgrammable.setHandler(new MockEa1000DriverHandler());
+        assertNotNull(cfmProgrammable.handler().data().deviceId());
+    }
+
+
+    @Ignore
+    @Test
+    public void testCreateMep() {
+        fail("Not yet implemented");
+    }
+
+    @Ignore
+    @Test
+    public void testGetAllMeps() {
+        fail("Not yet implemented");
+    }
+
+    @Test
+    public void testGetMep() throws CfmConfigException {
+        MepEntry mepEntry = cfmProgrammable.getMep(mdId1, maId11, mep111);
+
+        //Result will come from MockNetconfSessionEa1000.SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY
+        assertNotNull(mepEntry);
+        assertTrue(mepEntry.administrativeState());
+        assertTrue(mepEntry.cciEnabled());
+        assertEquals(Priority.PRIO5.name(), mepEntry.ccmLtmPriority().name());
+
+        assertTrue(mepEntry.activeMacStatusDefect()); //remote-mac-error
+        assertTrue(mepEntry.activeRdiCcmDefect()); //remote-rdi
+
+        assertNotNull(mepEntry.activeRemoteMepList());
+
+        //TODO Comment back in this test - this is a serious issue with onos-yang-tools that only 1 is found
+        // See https://gerrit.onosproject.org/#/c/15164/
+//        assertEquals("Expecting 2 Remote Meps", 2, mepEntry.activeRemoteMepList().size());
+        mepEntry.activeRemoteMepList().forEach(rmep -> {
+            if (rmep.remoteMepId().value() == 1) {
+                assertEquals(RemoteMepState.RMEP_FAILED.name(),
+                        rmep.state().toString());
+                assertEquals(54654654L, rmep.failedOrOkTime().toMillis());
+                assertEquals("aa:bb:cc:dd:ee:ff".toUpperCase(), rmep.macAddress().toString());
+                assertFalse(rmep.rdi());
+                assertEquals(PortStatusTlvType.PS_NO_STATUS_TLV.name(),
+                        rmep.portStatusTlvType().toString());
+                assertEquals(InterfaceStatusTlvType.IS_DORMANT.name(),
+                        rmep.interfaceStatusTlvType().toString());
+            }
+        });
+
+    }
+
+    /**
+     * For sampleXmlRegexDeleteMseaCfmMep.
+     * @throws CfmConfigException If an error occurs
+     */
+    @Test
+    public void testDeleteMep() throws CfmConfigException {
+        assertTrue(cfmProgrammable.deleteMep(mdId1, maId11, mep111));
+    }
+
+    /**
+     * For sampleXmlRegexTransmitLoopback.
+     * @throws CfmConfigException If an error occurs
+     */
+    @Test
+    public void testTransmitLoopback() throws CfmConfigException {
+        MepLbCreate.MepLbCreateBuilder lbCreate =
+                    DefaultMepLbCreate.builder(MepId.valueOf((short) 12));
+        lbCreate.numberMessages(5);
+//        lbCreate.dataTlvHex("AA:BB:CC:DD:EE");
+        lbCreate.vlanPriority(Priority.PRIO3);
+        lbCreate.vlanDropEligible(true);
+
+        cfmProgrammable.transmitLoopback(mdId1, maId11, mep111, lbCreate.build());
+    }
+
+    @Test
+    public void testAbortLoopback() throws CfmConfigException {
+        cfmProgrammable.abortLoopback(mdId1, maId11, mep111);
+    }
+
+//    @Test
+//    public void testTransmitLinktrace() {
+//        fail("Not yet implemented");
+//    }
+
+    @Test
+    public void testGetYangMdNameFromApiMdId() throws CfmConfigException {
+        MdNameAndTypeCombo name = EA1000CfmMepProgrammable
+                .getYangMdNameFromApiMdId(MdIdCharStr.asMdId("md-1"));
+
+        assertEquals(org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                .maintenancedomain.mdnameandtypecombo
+                .DefaultNameCharacterString.class, name.getClass());
+
+//There's a problem with checkstyle for typecast on really long paths
+//        assertEquals("md-1", ((org.onosproject.yang.gen.v1.http.www.microsemi.com
+//                .microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.mefcfm
+//                .maintenancedomain.mdnameandtypecombo
+//                .DefaultNameCharacterString) name).name().string());
+    }
+
+    @Test
+    public void testGetYangMaNameFromApiMaId() throws CfmConfigException {
+        MaNameAndTypeCombo name = MaNameUtil
+                .getYangMaNameFromApiMaId(MaIdCharStr.asMaId("ma-1-1"));
+        assertEquals(org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                .maintenancedomain.maintenanceassociation.manameandtypecombo
+                .DefaultNameCharacterString.class, name.getClass());
+
+//There's a problem with checkstyle for typecast on really long paths
+//        assertEquals("ma-1-1", ((org.onosproject.yang.gen.v1.http.www.microsemi.com
+//                .microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.mefcfm
+//                .maintenancedomain.maintenanceassociation.manameandtypecombo
+//                .DefaultNameCharacterString) name).name().string());
+    }
+
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java
new file mode 100644
index 0000000..59c674e
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java
@@ -0,0 +1,267 @@
+/*
+ * 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.drivers.microsemi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+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.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmCreateBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus;
+
+public class EA1000SoamDmProgrammableTest {
+
+    EA1000SoamDmProgrammable dmProgrammable;
+    MdId mdId1 = MdIdCharStr.asMdId("md-1");
+    MaIdShort maId11 = MaIdCharStr.asMaId("ma-1-1");
+    MepId mep111 = MepId.valueOf((short) 1);
+
+    @Before
+    public void setUp() throws Exception {
+        dmProgrammable = new EA1000SoamDmProgrammable();
+        dmProgrammable.setHandler(new MockEa1000DriverHandler());
+        assertNotNull(dmProgrammable.handler().data().deviceId());
+    }
+
+    //TODO Implement all these tests
+//    @Test
+//    public void testEA1000SoamDmProgrammable() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetAllDms() {
+//        fail("Not yet implemented");
+//    }
+
+    /**
+     * From SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY.
+     * @throws CfmConfigException
+     * @throws SoamConfigException
+     */
+    @Test
+    public void testGetDm() throws CfmConfigException, SoamConfigException {
+        DelayMeasurementEntry dmEntry =
+                dmProgrammable.getDm(mdId1, maId11, mep111, SoamId.valueOf(1));
+        assertEquals(1, dmEntry.dmId().id().intValue());
+        assertEquals(2, dmEntry.measurementsEnabled().size());
+        assertEquals(SessionStatus.ACTIVE.name(), dmEntry.sessionStatus().name());
+        assertEquals(100, dmEntry.frameDelayTwoWay().toNanos() / 1000);
+        assertEquals(101, dmEntry.interFrameDelayVariationTwoWay().toNanos() / 1000);
+    }
+
+    @Test
+    public void testCreateDm() throws CfmConfigException, SoamConfigException {
+        DmCreateBuilder dmBuilder = (DmCreateBuilder) DefaultDelayMeasurementCreate
+            .builder(DmType.DMDMM, Version.Y17312011,
+                MepId.valueOf((short) 10), Priority.PRIO3)
+            .frameSize((short) 1200);
+
+        dmProgrammable.createDm(mdId1, maId11, mep111, dmBuilder.build());
+    }
+
+    @Test
+    public void testCreateDmWrongMsgPeriod()
+            throws CfmConfigException, SoamConfigException {
+        DmCreateBuilder dmBuilder = (DmCreateBuilder) DefaultDelayMeasurementCreate
+                .builder(DmType.DMDMM, Version.Y17312011,
+                        MepId.valueOf((short) 10), Priority.PRIO3)
+                .messagePeriod(Duration.ofMillis(1234));
+
+        try {
+            dmProgrammable.createDm(mdId1, maId11, mep111, dmBuilder.build());
+            fail("Expecting to get an exception");
+        } catch (SoamConfigException e) {
+            assertTrue(e.getMessage()
+                    .contains("EA1000 supports only Message Periods"));
+        }
+
+    }
+
+//    @Test
+//    public void testGetDmCurrentStat() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetDmHistoricalStats() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testAbortDmMdIdMaIdShortMepIdSoamId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testBuildApiDmFromYangDm() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testAbortDmMdIdMaIdShortMepId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testClearDelayHistoryStatsMdIdMaIdShortMepId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testClearDelayHistoryStatsMdIdMaIdShortMepIdSoamId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetAllLms() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetLm() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetLmCurrentStat() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetLmHistoricalStats() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testCreateLm() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testAbortLmMdIdMaIdShortMepId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testAbortLmMdIdMaIdShortMepIdSoamId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testClearLossHistoryStatsMdIdMaIdShortMepId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testClearLossHistoryStatsMdIdMaIdShortMepIdSoamId() {
+//        fail("Not yet implemented");
+//    }
+
+    @Test
+    public void testCreateTestSignal() {
+        try {
+            dmProgrammable.createTestSignal(mdId1, maId11, mep111, null);
+            fail("Expected an exception");
+        } catch (UnsupportedOperationException e) {
+            assertEquals("Not supported by EA1000", e.getMessage());
+        } catch (CfmConfigException e) {
+            fail("CfmConfigException was not expected");
+        }
+    }
+
+    @Test
+    public void testAbortTestSignal() {
+        try {
+            dmProgrammable.abortTestSignal(mdId1, maId11, mep111);
+            fail("Expected an exception");
+        } catch (UnsupportedOperationException e) {
+            assertEquals("Not supported by EA1000", e.getMessage());
+        } catch (CfmConfigException e) {
+            fail("CfmConfigException was not expected");
+        }
+    }
+
+    @Test
+    public void testMeasurementEnableCollectionOfMeasurementOption() {
+        BitSet meBs = BitSet.valueOf(new byte[]{0x05});
+        Collection<MeasurementOption> moSet =
+                EA1000SoamDmProgrammable.getMeasurementOptions(meBs);
+        assertTrue(moSet.contains(MeasurementOption.SOAM_PDUS_RECEIVED));
+        assertTrue(moSet.contains(MeasurementOption.FRAME_DELAY_TWO_WAY_MIN));
+    }
+
+    @Test
+    public void testMeasurementEnableBitSetEmpty() {
+        Collection<MeasurementOption> moSet = new ArrayList<>();
+        try {
+            BitSet bitSet = EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet);
+            assertEquals("{}", bitSet.toString());
+        } catch (SoamConfigException e) {
+            fail("Was not expecting exception here");
+        }
+    }
+
+    @Test
+    public void testMeasurementEnableBitSetInvalid() {
+        Collection<MeasurementOption> moSet = new ArrayList<>();
+        moSet.add(MeasurementOption.FRAME_DELAY_BACKWARD_BINS);
+        moSet.add(MeasurementOption.FRAME_DELAY_RANGE_BACKWARD_AVERAGE);
+        try {
+            EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet);
+            fail("Was expecting an exception");
+        } catch (SoamConfigException e) {
+            assertTrue(e.getMessage()
+                    .contains("Measurement Option is not supported on EA1000"));
+        }
+    }
+
+    @Test
+    public void testMeasurementEnableBitSet2Good() {
+        Collection<MeasurementOption> moSet = new ArrayList<>();
+        moSet.add(MeasurementOption.FRAME_DELAY_TWO_WAY_BINS);
+        moSet.add(MeasurementOption.FRAME_DELAY_TWO_WAY_AVERAGE);
+        try {
+            BitSet bitSet = EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet);
+            assertEquals("{1, 4}", bitSet.toString());
+        } catch (SoamConfigException e) {
+            fail("Was not expecting exception here");
+        }
+    }
+
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
index 75c6811..58a8a5b 100644
--- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
@@ -19,14 +19,18 @@
 import java.util.Map;
 
 import org.onosproject.core.CoreService;
+import org.onosproject.drivers.microsemi.yang.MockCfmMdService;
+import org.onosproject.drivers.microsemi.yang.MockMseaCfmManager;
 import org.onosproject.drivers.microsemi.yang.MockMseaSaFilteringManager;
 import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager;
 import org.onosproject.drivers.microsemi.yang.MockNetconfSessionEa1000;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
 import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
 import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
 import org.onosproject.drivers.netconf.MockCoreService;
 import org.onosproject.drivers.netconf.MockNetconfController;
 import org.onosproject.drivers.netconf.MockNetconfDevice;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.driver.Behaviour;
 import org.onosproject.net.driver.DefaultDriver;
@@ -53,6 +57,8 @@
     private NetconfController ncc;
     private MockMseaSaFilteringManager mseaSaFilteringService;
     private MockMseaUniEvcServiceManager mseaUniEvcService;
+    private MockMseaCfmManager mseaCfmService;
+    private MockCfmMdService mockMdService;
     private CoreService coreService;
 
     public MockEa1000DriverHandler() throws NetconfException {
@@ -63,7 +69,9 @@
         Map<String, String> properties = new HashMap<String, String>();
 
         Driver mockDriver =
-                new DefaultDriver("mockDriver", null, "ONOSProject", "1.0.0", "1.0.0", behaviours, properties);
+                new DefaultDriver("mockDriver", null,
+                        "ONOSProject", "1.0.0",
+                        "1.0.0", behaviours, properties);
         DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
         mockDriverData = new DefaultDriverData(mockDriver, mockDeviceId);
 
@@ -78,6 +86,12 @@
         mseaUniEvcService = new MockMseaUniEvcServiceManager();
         mseaUniEvcService.activate();
 
+        mseaCfmService = new MockMseaCfmManager();
+        mseaCfmService.activate();
+
+        mockMdService = new MockCfmMdService();
+        mockMdService.activate();
+
         coreService = new MockCoreService();
         coreService.registerApplication(MICROSEMI_DRIVERS);
     }
@@ -109,9 +123,14 @@
         } else if (serviceClass.equals(MseaUniEvcServiceNetconfService.class)) {
             return (T) mseaUniEvcService;
 
+        } else if (serviceClass.equals(MseaCfmNetconfService.class)) {
+            return (T) mseaCfmService;
+
         } else if (serviceClass.equals(CoreService.class)) {
             return (T) coreService;
 
+        } else if (serviceClass.equals(CfmMdService.class)) {
+            return (T) mockMdService;
         }
 
         return null;
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java
new file mode 100644
index 0000000..ba6d656
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java
@@ -0,0 +1,63 @@
+/*
+ * 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.drivers.microsemi.yang;
+
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+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.impl.CfmMdManager;
+import static org.easymock.EasyMock.*;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore;
+
+import java.util.Optional;
+
+public class MockCfmMdService extends CfmMdManager {
+
+    @Override
+    public void activate() {
+        store = createMock(MdStore.class);
+
+        try {
+            MaintenanceAssociation ma = DefaultMaintenanceAssociation
+                    .builder(MaIdCharStr.asMaId("ma-1-1"), 6)
+                    .maNumericId((short) 1)
+                    .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_3MS)
+                    .build();
+
+            MdId md1Name = MdIdCharStr.asMdId("md-1");
+            MaintenanceDomain md1 = DefaultMaintenanceDomain
+                    .builder(md1Name)
+                    .mdNumericId((short) 1)
+                    .mdLevel(MaintenanceDomain.MdLevel.LEVEL3)
+                    .addToMaList(ma)
+                    .build();
+
+            expect(store.createUpdateMaintenanceDomain(md1))
+                    .andReturn(true);
+            expect(store.getMaintenanceDomain(md1Name))
+                    .andReturn(Optional.of(md1)).anyTimes();
+            replay(store);
+
+        } catch (CfmConfigException e) {
+            throw new IllegalArgumentException("Error creating Md md-1 for test");
+        }
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java
index 8068cff..d2c07e5 100644
--- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java
@@ -72,10 +72,23 @@
 
     private Pattern sampleXmlRegexSaFiltering =
             Pattern.compile("(<\\?xml).*"
-                    + "(<rpc).*(<get>).*"
-                    + "(<filter type=\"subtree\">).*(<source-ipaddress-filtering).*"
-                    + "(</filter>).*(</get>).*(</rpc>).*"
-                    + "(]]>){2}", Pattern.DOTALL);
+                    + "(<rpc).*(<get>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<source-ipaddress-filtering).*(</source-ipaddress-filtering>)\\R?"
+                    + "(</filter>)\\R?(</get>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexSaFilteringErrorScenario =
+            Pattern.compile("(<\\?xml).*"
+                    + "(<rpc).*(<get>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<source-ipaddress-filtering).*"
+                    + "(<interface-eth0>)\\R?"
+                    + "(<source-address-range>)\\R?"
+                    + "(<range-id>)10(</range-id>)\\R?"
+                    + "(</source-address-range>)\\R?"
+                    + "(</interface-eth0>)\\R?"
+                    + "(</source-ipaddress-filtering>)\\R?"
+                    + "(</filter>)\\R?(</get>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
 
     private Pattern sampleXmlRegexEditConfigSaFilt =
             Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>).*"
@@ -328,7 +341,7 @@
                     + "(<maintenance-domain>)\\R?"
                     + "(<id/>)\\R?"
                     + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
-                    + "(<md-level/>)\\R?"
+                    + "(<md-level/>)?\\R?"
                     + "(<maintenance-association>)\\R?"
                     + "(<id/>)\\R?"
                     + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
@@ -337,19 +350,22 @@
                     + "(<component-list/>)\\R?"
                     + "(<maintenance-association-end-point>)\\R?"
                     + "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
-                    + "(<interface/>)\\R?"
-                    + "(<primary-vid/>)\\R?"
-                    + "(<administrative-state/>)\\R?"
-                    + "(<ccm-ltm-priority/>)\\R?"
-                    + "(<continuity-check/>)\\R?"
-                    + "(<mac-address/>)\\R?"
-                    + "(<msea-soam-fm:port-status/>)\\R?"
-                    + "(<msea-soam-fm:interface-status/>)\\R?"
-                    + "(<msea-soam-fm:last-defect-sent/>)\\R?"
-                    + "(<msea-soam-fm:rdi-transmit-status/>)\\R?"
-                    + "(<loopback/>)\\R?"
-                    + "(<remote-mep-database/>)\\R?"
-                    + "(<linktrace/>)\\R?"
+                    + "(<mac-address/>)?\\R?"
+                    + "((<remote-mep-database>)\\R?"
+                    + "(<remote-mep>)\\R?"
+                    + "(<remote-mep-id/>)\\R?"
+                    + "(</remote-mep>)\\R?"
+                    + "(</remote-mep-database>))?\\R?"
+                    + "((<msea-soam-pm:delay-measurements>)\\R?"
+                    + "(<msea-soam-pm:delay-measurement>)\\R?"
+                    + "((<msea-soam-pm:dm-id/>)|(<msea-soam-pm:dm-id>[0-9]*</msea-soam-pm:dm-id>))\\R?"
+                    + "(</msea-soam-pm:delay-measurement>)\\R?"
+                    + "(</msea-soam-pm:delay-measurements>))?\\R?"
+                    + "((<msea-soam-pm:loss-measurements>)\\R?"
+                    + "(<msea-soam-pm:loss-measurement>)\\R?"
+                    + "((<msea-soam-pm:lm-id/>)|(<msea-soam-pm:lm-id>[0-9]*</msea-soam-pm:lm-id>))\\R?"
+                    + "(</msea-soam-pm:loss-measurement>)\\R?"
+                    + "(</msea-soam-pm:loss-measurements>))?\\R?"
                     + "(</maintenance-association-end-point>)\\R?"
                     + "(</maintenance-association>)\\R?"
                     + "(</maintenance-domain>)\\R?"
@@ -359,6 +375,164 @@
                     + "(</rpc>)\\R?"
                     + "(]]>){2}", Pattern.DOTALL);
 
+    //For testGetConfigMseaCfmEssentials
+    private Pattern sampleXmlRegexGetMseaCfmFull =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "(<id/>)\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<md-level/>)?\\R?"
+                    + "(<maintenance-association>)\\R?"
+                    + "(<id/>)\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<maintenance-association-end-point>)\\R?"
+                    + "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
+                    + "(<interface/>)?\\R?"
+                    + "(<primary-vid/>)?\\R?"
+                    + "(<administrative-state/>)?\\R?"
+                    + "(<mac-address/>)?\\R?"
+                    + "(<ccm-ltm-priority/>)?\\R?"
+                    + "(<continuity-check/>)?\\R?"
+                    + "(<loopback/>)?\\R?"
+                    + "(<linktrace/>)?\\R?"
+                    + "(<remote-mep-database/>)\\R?"
+                    + "(<msea-soam-fm:operational-state/>)\\R?"
+                    + "(<msea-soam-fm:connectivity-status/>)\\R?"
+                    + "(<msea-soam-fm:port-status/>)\\R?"
+                    + "(<msea-soam-fm:interface-status/>)\\R?"
+                    + "(<msea-soam-fm:last-defect-sent/>)\\R?"
+                    + "(<msea-soam-fm:rdi-transmit-status/>)\\R?"
+                    + "(</maintenance-association-end-point>)\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</filter>)\\R?"
+                    + "(</get>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    //For testGetConfigMseaCfmEssentials
+    private Pattern sampleXmlRegexGetMseaDelay =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "(<id/>)\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<maintenance-association>)\\R?"
+                    + "(<id/>)\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<maintenance-association-end-point>)\\R?"
+                    + "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
+                    + "((<msea-soam-pm:delay-measurements>)\\R?"
+                    + "(<msea-soam-pm:delay-measurement>)\\R?"
+                    + "((<msea-soam-pm:dm-id/>)|(<msea-soam-pm:dm-id>[0-9]*</msea-soam-pm:dm-id>))\\R?"
+                    + "(<msea-soam-pm:mep-id/>)\\R?"
+                    + "(<msea-soam-pm:mac-address/>)\\R?"
+                    + "(<msea-soam-pm:administrative-state/>)\\R?"
+                    + "(<msea-soam-pm:measurement-enable/>)\\R?"
+                    + "(<msea-soam-pm:message-period/>)\\R?"
+                    + "(<msea-soam-pm:priority/>)\\R?"
+                    + "(<msea-soam-pm:frame-size/>)\\R?"
+                    + "(<msea-soam-pm:measurement-interval/>)\\R?"
+                    + "(<msea-soam-pm:number-intervals-stored/>)\\R?"
+                    + "(<msea-soam-pm:session-status/>)\\R?"
+                    + "(<msea-soam-pm:frame-delay-two-way/>)\\R?"
+                    + "(<msea-soam-pm:inter-frame-delay-variation-two-way/>)\\R?"
+                    + "(<msea-soam-pm:current-stats/>)?\\R?"
+                    + "(<msea-soam-pm:history-stats/>)?\\R?"
+                    + "(</msea-soam-pm:delay-measurement>)\\R?"
+                    + "(</msea-soam-pm:delay-measurements>))?\\R?"
+                    + "(</maintenance-association-end-point>)\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</filter>)\\R?"
+                    + "(</get>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    //For testGetConfigMseaCfmEssentials
+    private Pattern sampleXmlRegexDeleteMseaCfmMep =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target>\\R?<running/>\\R?</target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "(<id/>)?\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<maintenance-association>)\\R?"
+                    + "(<id/>)?\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<maintenance-association-end-point nc:operation=\"delete\">)\\R?"
+                    + "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
+                    + "(</maintenance-association-end-point>)\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</config>)\\R?"
+                    + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+
+    private Pattern sampleXmlRegexTransmitLoopback =
+            Pattern.compile("(<\\?xml).*(<rpc).*\\R?"
+                    + "(<transmit-loopback xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">)\\R?"
+                    + "((<number-of-messages>)[0-9]*(</number-of-messages>))?\\R?"
+                    + "((<data-tlv>)[a-zA-Z0-9+=/]*(</data-tlv>))?\\R?"
+                    + "((<vlan-priority>)[0-9]{1}(</vlan-priority>))?\\R?"
+                    + "((<vlan-drop-eligible>)((true)|(false))(</vlan-drop-eligible>))?\\R?"
+                    + "(<maintenance-association-end-point>)[0-9]{1,4}(</maintenance-association-end-point>)\\R?"
+                    + "(<maintenance-association>)[0-9]{1,5}(</maintenance-association>)\\R?"
+                    + "(<maintenance-domain>)[0-9]{1,5}(</maintenance-domain>)\\R?"
+                    + "(<target-address>)\\R?"
+                    + "((<mep-id>)[0-9]{1,4}(</mep-id>))?\\R?"
+                    + "((<mac-address>)[a-fA-F0-9:-]{17}(</mac-address>))?\\R?"
+                    + "(</target-address>)\\R?"
+                    + "(</transmit-loopback>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexAbortLoopback =
+            Pattern.compile("(<\\?xml).*(<rpc).*\\R?"
+                    + "(<abort-loopback xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">)\\R?"
+                    + "(<maintenance-association-end-point>)[0-9]{1,4}(</maintenance-association-end-point>)\\R?"
+                    + "(<maintenance-association>)[0-9]{1,5}(</maintenance-association>)\\R?"
+                    + "(<maintenance-domain>)[0-9]{1,5}(</maintenance-domain>)\\R?"
+                    + "(</abort-loopback>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    //For testCreateDm()
+    private Pattern sampleXmlRegexEditConfigDmCreate =
+        Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+            + "(<target>\\R?<running/>\\R?</target>)\\R?"
+            + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+            + "(<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">)\\R?"
+            + "(<maintenance-domain>)\\R?"
+            + "(<id>)[0-9]*(</id>)\\R?"
+            + "(<maintenance-association>)\\R?"
+            + "(<id>)[0-9]*(</id>)\\R?"
+            + "(<maintenance-association-end-point>)\\R?"
+            + "(<mep-identifier>)[0-9]*(</mep-identifier>)\\R?"
+            + "(<delay-measurements xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">)\\R?"
+            + "(<delay-measurement>)\\R?"
+            + "(<dm-id>)[0-9]*(</dm-id>)\\R?"
+            + "((<administrative-state>)(true|false)(</administrative-state>))?\\R?"
+            + "((<message-period>)(1000ms|100ms|10ms|3ms)(</message-period>))?\\R?"
+            + "(<priority>)[0-9]*(</priority>)\\R?"
+            + "((<frame-size>)[0-9]*(</frame-size>))?\\R?"
+            + "(<mep-id>)[0-9]*(</mep-id>)\\R?"
+            + "(</delay-measurement>)\\R?"
+            + "(</delay-measurements>)\\R?"
+            + "(</maintenance-association-end-point>)\\R?"
+            + "(</maintenance-association>)\\R?"
+            + "(</maintenance-domain>)\\R?"
+            + "(</mef-cfm>)\\R?"
+            + "(</config>)\\R?"
+            + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
 
     private static final String SAMPLE_SYSTEM_REPLY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
             + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
@@ -410,6 +584,17 @@
             + "</data>\n"
             + "</rpc-reply>";
 
+    private static final String SAMPLE_ERROR_REPLY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<rpc-error>"
+            + "<error-type>application</error-type>"
+            + "<error-tag>data-missing</error-tag>"
+            + "<error-severity>error</error-severity>"
+            + "<error-message>Request could not be completed because " +
+                "the relevant data model content does not exist.</error-message>"
+            + "</rpc-error>"
+            + "</rpc-reply>";
+
     private static final String SAMPLE_MSEAEVCUNI_REPLY_INIT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
             + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
             + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
@@ -592,7 +777,7 @@
             + "</data>\n"
             + "</rpc-reply>";
 
-    private static final String SAMPLE_MSEACFM_MD_MA_MEP_REPLY =
+    private static final String SAMPLE_MSEACFM_MD_MA_MEP_ESSENTIALS_REPLY =
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"47\">"
             + "<data>"
@@ -602,72 +787,41 @@
             + "<maintenance-domain>"
             + "<id>1</id>"
             + "<name>md-1</name>"
-            + "<md-level>3</md-level>"
             + "<maintenance-association>"
             + "<id>1</id>"
             + "<name>ma-1-1</name>"
-            + "<ccm-interval>10ms</ccm-interval>" //Causing problems on create of MA
-            + "<remote-meps>1</remote-meps>"
-            + "<remote-meps>2</remote-meps>"
-            + "<component-list>"
-            + "<vid>100</vid>"
-            + "<tag-type>vlan-stag</tag-type>"
-            + "</component-list>"
             + "<maintenance-association-end-point>"
             + "<mep-identifier>1</mep-identifier>"
-            + "<interface>eth1</interface>"
-            + "<primary-vid>100</primary-vid>"
-            + "<administrative-state>true</administrative-state>"
-            + "<ccm-ltm-priority>4</ccm-ltm-priority>"
-            + "<continuity-check>"
-            + "<cci-enabled>true</cci-enabled>"
-            + "<fng-state>report-defect</fng-state>"
-            + "<highest-priority-defect-found>remote-mac-error</highest-priority-defect-found>"
-            + "<active-defects> remote-mac-error invalid-ccm</active-defects>"
-            + "<last-error-ccm>U2FtcGxlIGxhc3QgZXJyb3IgY2NtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAA==</last-error-ccm>"
-            + "<ccm-sequence-error-count>10</ccm-sequence-error-count>"
-            + "<sent-ccms>15</sent-ccms>"
-            + "</continuity-check>"
-            + "<mac-address>53:65:61:6e:20:43</mac-address>"
-            + "<msea-soam-fm:port-status>no-status-tlv</msea-soam-fm:port-status>"
-            + "<msea-soam-fm:interface-status>no-status-tlv</msea-soam-fm:interface-status>"
-//            + "<msea-soam-fm:last-defect-sent/>" --Can't handle this at the moment
-            + "<msea-soam-fm:rdi-transmit-status>false</msea-soam-fm:rdi-transmit-status>"
-            + "<loopback>"
-            + "<replies-received>123</replies-received>"
-            + "<replies-transmitted>456</replies-transmitted>"
-            + "</loopback>"
+            + "<mac-address>00:b0:ae:03:ff:31</mac-address>"
             + "<remote-mep-database>"
             + "<remote-mep>"
+            + "<remote-mep-id>1</remote-mep-id>"
+            + "</remote-mep>"
+            + "<remote-mep>"
             + "<remote-mep-id>2</remote-mep-id>"
-            + "<remote-mep-state>ok</remote-mep-state>"
-            + "<failed-ok-time>1490692834</failed-ok-time>"
-            + "<mac-address>53:65:61:6e:20:43</mac-address>"
-            + "<rdi>true</rdi>"
-            + "<port-status-tlv>up</port-status-tlv>"
-            + "<interface-status-tlv>dormant</interface-status-tlv>"
             + "</remote-mep>"
             + "</remote-mep-database>"
-            + "<linktrace>"
-            + "<unexpected-replies-received>0</unexpected-replies-received>"
-            + "<msea-soam-fm:ltm-msgs-transmitted>2</msea-soam-fm:ltm-msgs-transmitted>"
-            + "<msea-soam-fm:ltm-msgs-received>2</msea-soam-fm:ltm-msgs-received>"
-            + "<msea-soam-fm:ltr-msgs-transmitted>2</msea-soam-fm:ltr-msgs-transmitted>"
-            + "<msea-soam-fm:ltr-msgs-received>2</msea-soam-fm:ltr-msgs-received>"
-            + "<linktrace-database/>"
-            + "</linktrace>"
+            + "<msea-soam-pm:delay-measurements>"
+            + "<msea-soam-pm:delay-measurement>"
+            + "<msea-soam-pm:dm-id>1</msea-soam-pm:dm-id>"
+            + "</msea-soam-pm:delay-measurement>"
+            + "</msea-soam-pm:delay-measurements>"
+            + "<msea-soam-pm:loss-measurements>"
+            + "<msea-soam-pm:loss-measurement>"
+            + "<msea-soam-pm:lm-id>1</msea-soam-pm:lm-id>"
+            + "</msea-soam-pm:loss-measurement>"
+            + "<msea-soam-pm:loss-measurement>"
+            + "<msea-soam-pm:lm-id>2</msea-soam-pm:lm-id>"
+            + "</msea-soam-pm:loss-measurement>"
+            + "</msea-soam-pm:loss-measurements>"
             + "</maintenance-association-end-point>"
-            + "<remote-meps>4</remote-meps>"
             + "</maintenance-association>"
             + "</maintenance-domain>"
             + "</mef-cfm>"
             + "</data>"
             + "</rpc-reply>";
 
-    private static final String SAMPLE_MSEACFM_MD_MA_MEP_REPLY2 =
+    private static final String SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY =
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"47\">"
             + "<data>"
@@ -676,63 +830,100 @@
             + "xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">"
             + "<maintenance-domain>"
             + "<id>1</id>"
-            + "<name>Microsemi</name>"
-            + "<md-level>2</md-level>"
+            + "<name>md-1</name>"
             + "<maintenance-association>"
             + "<id>1</id>"
-            + "<name>example-ma</name>"
-            + "<remote-meps>1</remote-meps>"
-            + "<remote-meps>2</remote-meps>"
-            + "<component-list>"
-            + "<vid>100</vid>"
-            + "<tag-type>vlan-stag</tag-type>"
-            + "</component-list>"
+            + "<name>ma-1-1</name>"
+            + "<ccm-interval>3.3ms</ccm-interval>"
             + "<maintenance-association-end-point>"
-            + "<mep-identifier>4</mep-identifier>"
-            + "<interface>eth1</interface>"
-            + "<primary-vid>100</primary-vid>"
+            + "<mep-identifier>1</mep-identifier>"
+            + "<interface>eth0</interface>"
+            + "<primary-vid>20</primary-vid>"
             + "<administrative-state>true</administrative-state>"
-            + "<ccm-ltm-priority>4</ccm-ltm-priority>"
+            + "<mac-address>00:b0:ae:03:ff:31</mac-address>"
+            + "<ccm-ltm-priority>5</ccm-ltm-priority>"
             + "<continuity-check>"
             + "<cci-enabled>true</cci-enabled>"
             + "<fng-state>defect-reported</fng-state>"
             + "<highest-priority-defect-found>remote-invalid-ccm</highest-priority-defect-found>"
-//            + "<active-defects> remote-invalid-ccm</active-defects>"
-            + "<active-defects/>"
+            + "<active-defects>remote-rdi remote-invalid-ccm</active-defects>"
             + "<ccm-sequence-error-count>0</ccm-sequence-error-count>"
-            + "<sent-ccms>41013</sent-ccms>"
+            + "<sent-ccms>197</sent-ccms>"
             + "</continuity-check>"
-            + "<mac-address>00:b0:ae:03:ff:31</mac-address>"
+            + "<loopback>"
+            + "</loopback>"
+            + "<linktrace>"
+            + "</linktrace>"
+            + "<remote-mep-database>"
+                + "<remote-mep>"
+                    + "<remote-mep-id>1</remote-mep-id>"
+                    + "<remote-mep-state>failed</remote-mep-state>"
+                    + "<failed-ok-time>54654654</failed-ok-time>"
+                    + "<mac-address>aa:bb:cc:dd:ee:ff</mac-address>"
+                    + "<rdi>false</rdi>"
+                    + "<port-status-tlv>no-status-tlv</port-status-tlv>"
+                    + "<interface-status-tlv>dormant</interface-status-tlv>"
+                + "</remote-mep>"
+                + "<remote-mep>"
+                    + "<remote-mep-id>2</remote-mep-id>"
+                    + "<remote-mep-state>failed</remote-mep-state>"
+                    + "<failed-ok-time>54654654</failed-ok-time>"
+                    + "<mac-address>aa:bb:cc:dd:ee:ff</mac-address>"
+                    + "<rdi>false</rdi>"
+                    + "<port-status-tlv>no-status-tlv</port-status-tlv>"
+                    + "<interface-status-tlv>dormant</interface-status-tlv>"
+                + "</remote-mep>"
+            + "</remote-mep-database>"
+            + "<msea-soam-fm:operational-state>enabled</msea-soam-fm:operational-state>"
+            + "<msea-soam-fm:connectivity-status>partially-active</msea-soam-fm:connectivity-status>"
             + "<msea-soam-fm:port-status>up</msea-soam-fm:port-status>"
             + "<msea-soam-fm:interface-status>up</msea-soam-fm:interface-status>"
+            + "<msea-soam-fm:last-defect-sent>remote-rdi remote-mac-error</msea-soam-fm:last-defect-sent>"
             + "<msea-soam-fm:rdi-transmit-status>true</msea-soam-fm:rdi-transmit-status>"
-            + "<loopback>"
-            + "<replies-received>0</replies-received>"
-            + "<replies-transmitted>0</replies-transmitted>"
-            + "</loopback>"
-            + "<remote-mep-database>"
-            + "<remote-mep>"
-            + "<remote-mep-id>1</remote-mep-id>"
-            + "<remote-mep-state>failed</remote-mep-state>"
-            + "<failed-ok-time>26315533</failed-ok-time>"
-            + "<mac-address>00:00:00:00:00:00</mac-address>"
-            + "<rdi>false</rdi>"
-            + "<port-status-tlv>no-status-tlv</port-status-tlv>"
-            + "<interface-status-tlv>no-status-tlv</interface-status-tlv>"
-            + "</remote-mep>"
-            + "<remote-mep>"
-            + "<remote-mep-id>2</remote-mep-id>"
-            + "<remote-mep-state>failed</remote-mep-state>"
-            + "<failed-ok-time>26315541</failed-ok-time>"
-            + "<mac-address>00:00:00:00:00:00</mac-address>"
-            + "<rdi>false</rdi>"
-            + "<port-status-tlv>no-status-tlv</port-status-tlv>"
-            + "<interface-status-tlv>no-status-tlv</interface-status-tlv>"
-            + "</remote-mep>"
-            + "</remote-mep-database>"
-            + "<linktrace />"
             + "</maintenance-association-end-point>"
-            + "<remote-meps>4</remote-meps>"
+            + "</maintenance-association>"
+            + "</maintenance-domain>"
+            + "</mef-cfm>"
+            + "</data>"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"47\">"
+            + "<data>"
+            + "<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" "
+            + "xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" "
+            + "xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">"
+            + "<maintenance-domain>"
+            + "<id>1</id>"
+            + "<name>md-1</name>"
+            + "<maintenance-association>"
+            + "<id>1</id>"
+            + "<name>ma-1-1</name>"
+            + "<maintenance-association-end-point>"
+            + "<mep-identifier>1</mep-identifier>"
+            + "<msea-soam-pm:delay-measurements>"
+            + "<msea-soam-pm:delay-measurement>"
+            + "<msea-soam-pm:dm-id>1</msea-soam-pm:dm-id>"
+            + "<msea-soam-pm:mep-id>10</msea-soam-pm:mep-id>"
+            + "<msea-soam-pm:administrative-state>true</msea-soam-pm:administrative-state>"
+            + "<msea-soam-pm:measurement-enable>frame-delay-two-way-bins "
+            + "frame-delay-two-way-max</msea-soam-pm:measurement-enable>"
+            + "<msea-soam-pm:message-period>3ms</msea-soam-pm:message-period>"
+            + "<msea-soam-pm:priority>6</msea-soam-pm:priority>"
+            + "<msea-soam-pm:frame-size>1000</msea-soam-pm:frame-size>"
+            + "<msea-soam-pm:measurement-interval>15</msea-soam-pm:measurement-interval>"
+            + "<msea-soam-pm:number-intervals-stored>32</msea-soam-pm:number-intervals-stored>"
+            + "<msea-soam-pm:session-status>active</msea-soam-pm:session-status>"
+            + "<msea-soam-pm:frame-delay-two-way>100</msea-soam-pm:frame-delay-two-way>"
+            + "<msea-soam-pm:inter-frame-delay-variation-two-way>101</msea-soam-pm:inter-frame-delay-variation-two-way>"
+//            + "<msea-soam-pm:current-stats>"
+//            + "</msea-soam-pm:current-stats>"
+//            + "<msea-soam-pm:history-stats>"
+//            + "</msea-soam-pm:history-stats>"
+            + "</msea-soam-pm:delay-measurement>"
+            + "</msea-soam-pm:delay-measurements>"
+            + "</maintenance-association-end-point>"
             + "</maintenance-association>"
             + "</maintenance-domain>"
             + "</mef-cfm>"
@@ -966,6 +1157,9 @@
         } else if (sampleXmlRegex2.matcher(request).matches()) {
             return SAMPLE_SYSTEM_REPLY_INIT;
 
+        } else if (sampleXmlRegexSaFilteringErrorScenario.matcher(request).matches()) {
+            return SAMPLE_ERROR_REPLY;
+
         } else if (sampleXmlRegexSaFiltering.matcher(request).matches()) {
             return SAMPLE_MSEASAFILTERING_FE_REPLY;
 
@@ -1009,7 +1203,25 @@
             return SAMPLE_REPLY_OK;
 
         } else if (sampleXmlRegexGetMseaCfmEssentials.matcher(request).matches()) {
-            return SAMPLE_MSEACFM_MD_MA_MEP_REPLY2;
+            return SAMPLE_MSEACFM_MD_MA_MEP_ESSENTIALS_REPLY;
+
+        } else if (sampleXmlRegexGetMseaCfmFull.matcher(request).matches()) {
+            return SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY;
+
+        } else if (sampleXmlRegexDeleteMseaCfmMep.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexGetMseaDelay.matcher(request).matches()) {
+            return SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY;
+
+        } else if (sampleXmlRegexEditConfigDmCreate.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexTransmitLoopback.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexAbortLoopback.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
 
         } else {
             throw new NetconfException("MocknetconfSession. No sendRequest() case for query: " +
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java
index 2908d53..fe99bf3 100644
--- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java
@@ -26,18 +26,42 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.packet.Ip4Address;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService.DmEntryParts;
 import org.onosproject.drivers.microsemi.yang.impl.MseaCfmManager;
+import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil;
+import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil2;
+import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil3;
+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.incubator.net.l2monitoring.soam.SoamId;
 import org.onosproject.netconf.NetconfDeviceInfo;
 import org.onosproject.netconf.NetconfException;
 import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.MacAddress;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.DefaultAbortLoopbackInput;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString;
 import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.AddressType;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMacAddress;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMepId;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.DefaultTransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.DefaultTargetAddress;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.lossmeasurements.lossmeasurement.MessagePeriodEnum;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.sessionstatustype.SessionStatusTypeEnum;
 import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
 
 public class MseaCfmManagerTest {
 
@@ -52,7 +76,8 @@
         } catch (UncheckedIOException e) {
             fail(e.getMessage());
         }
-        NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf", Ip4Address.valueOf("1.2.3.4"), 830);
+        NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf",
+                Ip4Address.valueOf("1.2.3.4"), 830);
         session = new MockNetconfSessionEa1000(deviceInfo);
     }
 
@@ -61,13 +86,92 @@
     }
 
     @Test
-    public void testGetConfigMseaCfmEssentials() throws NetconfException {
-        MseaCfm mseaCfm = mseaCfmService.getMepEssentials("md-1", "ma-1-1", 1, session);
+    public void testGetConfigMseaCfmEssentials()
+            throws NetconfException, CfmConfigException {
+        MseaCfm mseaCfm = mseaCfmService.getMepEssentials(
+                MdIdCharStr.asMdId("md-1"),
+                MaIdCharStr.asMaId("ma-1-1"),
+                MepId.valueOf((short) 1), session);
         assertNotNull(mseaCfm);
 
-        //See SAMPLE_MSEACFM_MD_MA_MEP_REPLY in MockNetconfSessionEa1000
+        //See SAMPLE_MSEACFM_MD_MA_MEP_ESSENTIALS_REPLY in MockNetconfSessionEa1000
         assertEquals(1, mseaCfm.mefCfm().maintenanceDomain().size());
-        assertEquals(2, mseaCfm.mefCfm().maintenanceDomain().get(0).mdLevel().uint8());
+    }
+
+    @Test
+    public void testGetConfigMseaCfmFull()
+            throws NetconfException, CfmConfigException {
+        MseaCfm mseaCfm = mseaCfmService.getMepFull(
+                MdIdCharStr.asMdId("md-1"),
+                MaIdCharStr.asMaId("ma-1-1"),
+                MepId.valueOf((short) 1), session);
+        assertNotNull(mseaCfm);
+
+        //See SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY in MockNetconfSessionEa1000
+        assertEquals(1, mseaCfm.mefCfm().maintenanceDomain().size());
+        MaintenanceAssociationEndPoint mep = mseaCfm.mefCfm()
+                .maintenanceDomain().get(0)
+                .maintenanceAssociation().get(0)
+                .maintenanceAssociationEndPoint().get(0);
+        assertTrue(mep.administrativeState());
+        assertEquals("00:b0:ae:03:ff:31", mep.macAddress().toString());
+
+        org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain
+        .maintenanceassociation.maintenanceassociationendpoint
+        .AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+            MepIdUtil2.convertFmAugmentedMep(mep);
+
+        assertEquals("partially-active", augmentedMep.connectivityStatus().toString());
+        assertEquals("up", augmentedMep.interfaceStatus().enumeration().toString());
+    }
+
+    /**
+     * Driven by SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY.
+     * @throws NetconfException If there's a problem
+     */
+    @Test
+    public void testGetSoamDm() throws NetconfException {
+        MseaCfm mseaCfmWithDm = mseaCfmService.getSoamDm(
+                MdIdCharStr.asMdId("md-1"),
+                MaIdCharStr.asMaId("ma-1-1"),
+                MepId.valueOf((short) 1),
+                SoamId.valueOf(1),
+                DmEntryParts.ALL_PARTS, session);
+
+        assertNotNull(mseaCfmWithDm);
+        MaintenanceAssociationEndPoint mep = mseaCfmWithDm.mefCfm()
+            .maintenanceDomain().get(0)
+            .maintenanceAssociation().get(0)
+            .maintenanceAssociationEndPoint().get(0);
+
+        //Because of a checkstyle problem with typecasts including really long
+        //package names, this has to be handed off to a different class
+        org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain
+        .maintenanceassociation.maintenanceassociationendpoint
+        .AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+                MepIdUtil.convertPmAugmentedMep(mep);
+
+        DelayMeasurement dm = augmentedMep.delayMeasurements().delayMeasurement().get(0);
+        assertEquals(true, dm.administrativeState());
+        assertTrue(dm.measurementEnable().get(3)); //frame-delay-two-way-bins
+        assertTrue(dm.measurementEnable().get(1)); //frame-delay-two-way-max
+
+        assertEquals(MessagePeriodEnum.YANGAUTOPREFIX3MS.name(), dm.messagePeriod().name());
+        assertEquals(6, dm.priority().uint8());
+        assertEquals(1000, dm.frameSize());
+        assertEquals(15, dm.measurementInterval());
+        assertEquals(32, dm.numberIntervalsStored());
+        assertEquals(SessionStatusTypeEnum.ACTIVE.name(),
+                dm.sessionStatus().enumeration().name());
+        assertEquals(100, dm.frameDelayTwoWay().uint32());
+        assertEquals(101, dm.interFrameDelayVariationTwoWay().uint32());
+
+        //The remoteMep of the DM is a choice, which for mepId is a leafref object
+        org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep
+        .DefaultMepId remoteMepId = MepIdUtil3.convertPmRemoteMepToMepId(dm.remoteMep());
+        assertNotNull(remoteMepId);
+        assertEquals(10, ((MepIdType) remoteMepId.mepId()).uint16());
+
     }
 
     /**
@@ -91,20 +195,67 @@
     }
 
     @Test
-    public void testTransmitLoopback() throws NetconfException {
+    /**
+     * Using Remote remote MEP ID and all arguments.
+     */
+    public void testTransmitLoopback1() {
+        TransmitLoopbackInput lbTr1 = new DefaultTransmitLoopbackInput();
+        lbTr1.maintenanceDomain(Short.valueOf((short) 1));
+        lbTr1.maintenanceAssociation(Short.valueOf((short) 2));
+        lbTr1.maintenanceAssociationEndPoint(Short.valueOf((short) 3));
+
+        DefaultTargetAddress ta = new DefaultTargetAddress();
+        DefaultMepId mepId = new DefaultMepId();
+        mepId.mepId(MepIdType.of(4));
+        ta.addressType((AddressType) mepId);
+        lbTr1.targetAddress(ta);
+
+//        lbTr1.dataTlv(new byte[]{0x01, 0x02, 0x03}); Not supported in onos-yang-tools just yet
+        lbTr1.numberOfMessages(10);
+        lbTr1.vlanDropEligible(true);
+        lbTr1.vlanPriority(PriorityType.of((short) 1));
         try {
-            mseaCfmService.transmitLoopback(null, session);
-        } catch (UnsupportedOperationException e) {
-            assertTrue(e.getMessage().contains("Not yet implemented"));
+            mseaCfmService.transmitLoopback(lbTr1, session);
+        } catch (NetconfException e) {
+            fail("Calling of TransmitLoopback failed: " + e.getMessage());
+        }
+    }
+
+    @Test
+    /**
+     * Using Remote Mac address in place of remote MEP ID and fewer arguments.
+     */
+    public void testTransmitLoopback2() {
+        TransmitLoopbackInput lbTr2 = new DefaultTransmitLoopbackInput();
+
+        lbTr2.maintenanceDomain(Short.valueOf((short) 63));
+        lbTr2.maintenanceAssociation(Short.valueOf((short) 62));
+        lbTr2.maintenanceAssociationEndPoint(Short.valueOf((short) 61));
+
+        DefaultTargetAddress ta = new DefaultTargetAddress();
+        DefaultMacAddress macAddr = new DefaultMacAddress();
+        macAddr.macAddress(MacAddress.of("FF:EE:DD:CC:BB:AA"));
+        ta.addressType(macAddr);
+        lbTr2.targetAddress(ta);
+        try {
+            mseaCfmService.transmitLoopback(lbTr2, session);
+        } catch (NetconfException e) {
+            fail("Calling of TransmitLoopback failed: " + e.getMessage());
         }
     }
 
     @Test
     public void testAbortLoopback() throws NetconfException {
+        AbortLoopbackInput lbAbort = new DefaultAbortLoopbackInput();
+
+        lbAbort.maintenanceDomain((short) 70);
+        lbAbort.maintenanceAssociation((short) 71);
+        lbAbort.maintenanceAssociationEndPoint((short) 72);
+
         try {
-            mseaCfmService.abortLoopback(null, session);
-        } catch (UnsupportedOperationException e) {
-            assertTrue(e.getMessage().contains("Not yet implemented"));
+            mseaCfmService.abortLoopback(lbAbort, session);
+        } catch (NetconfException e) {
+            fail("Calling of AbortLoopback failed: " + e.getMessage());
         }
     }
 
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java
index 1a3e779..29ac4a3 100644
--- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java
@@ -18,6 +18,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
 
 import java.io.UncheckedIOException;
 import java.util.List;
@@ -85,6 +86,32 @@
         }
     }
 
+    /**
+     * See sampleXmlRegexSaFilteringErrorScenario in MockNetconfSessionEa1000.
+     */
+    @Test
+    public void testGetMseaSaFilteringMseaSaFilteringOpParamNetconfSessionError() {
+
+        SourceAddressRange sar = new DefaultSourceAddressRange();
+        sar.rangeId((short) 10);
+
+        InterfaceEth0 eth0 = new DefaultInterfaceEth0();
+        eth0.addToSourceAddressRange(sar);
+
+        SourceIpaddressFiltering sip = new DefaultSourceIpaddressFiltering();
+        sip.interfaceEth0(eth0);
+
+        MseaSaFilteringOpParam mseaSaFilteringConfig = new MseaSaFilteringOpParam();
+        mseaSaFilteringConfig.sourceIpaddressFiltering(sip);
+
+        try {
+            MseaSaFiltering result = mseaSaSvc.getMseaSaFiltering(mseaSaFilteringConfig, session);
+            fail("Should have thrown exception");
+        } catch (NetconfException ne) {
+            assertTrue(ne.getMessage().startsWith("NETCONF rpc-error"));
+        }
+    }
+
     @Test
     public void testSetMseaSaFilteringMseaSaFilteringOpParamNetconfSessionNcDsType() {