Initial import of CFM and SOAM api

Change-Id: Icf5cc2d5fb34b75460e80e8cced0d70265bcd33b
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>