Updating Microsemi Driver to onos-yang-tools 2.x

Change-Id: I80e3348087518a8f9a742c813b6238371a3f8f97
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java
new file mode 100644
index 0000000..4df22ec
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java
@@ -0,0 +1,974 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.math.BigInteger;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
+
+import org.onlab.packet.EthType;
+import org.onlab.packet.EthType.EtherType;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.drivers.microsemi.yang.UniSide;
+import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnic;
+import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnin;
+import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowEntry.FlowEntryState;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleProgrammable;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanHeaderInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfDevice;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.DefaultSourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.DefaultInterfaceEth0;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.InterfaceEth0;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.DefaultSourceAddressRange;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.FilterAdminStateEnum;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.VlanIdType;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.DefaultFlowMapping;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagOverwrite;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPop;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPush;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagOverwrite;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPop;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPush;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.tagpush.tagpush.PushTagTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultUni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Uni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.DefaultEvc;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.Evc;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.DefaultEvcPerUni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.EvcPerUni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin;
+import org.slf4j.Logger;
+
+/**
+ * An implementation of the FlowRuleProgrammable behaviour for the EA10000 device.
+ *
+ * This device is not a native Open Flow device. It has only a NETCONF interface for configuration
+ * status retrieval and notifications. It supports only a small subset of OpenFlow rules.<br>
+ *
+ * The device supports only:<br>
+ * 1) Open flow rules that blocks certain IP address ranges, but only those incoming on Port 0
+ *    and has a limit of 10 such rules<br>
+ * 2) Open flow rules that PUSH, POP and OVERWRITE VLAN tags on both ports. This can push and overwrite
+ *    both C-TAGs (0x8100) and S-TAGs (0x88a8).
+ */
+public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
+
+    protected final Logger log = getLogger(getClass());
+    public static final String MICROSEMI_DRIVERS = "com.microsemi.drivers";
+    public static final int PRIORITY_DEFAULT = 50000;
+    //To protect the NETCONF session from concurrent access across flow addition and removal
+    static Semaphore sessionMutex = new Semaphore(1);
+
+    /**
+     * Get the flow entries that are present on the EA1000.
+     * Since the EA1000 does not have any 'real' flow entries these are retrieved from 2 configuration
+     * areas on the EA1000 NETCONF model - from SA filtering YANG model and from EVC UNI YANG model.<br>
+     * The flow entries must match exactly the FlowRule entries in the ONOS store. If they are not an
+     * exact match the device will be requested to remove those flows and the FlowRule will stay in a
+     * PENDING_ADD state.
+     * @return A collection of Flow Entries
+     */
+    @Override
+    public Collection<FlowEntry> getFlowEntries() {
+        Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
+
+        UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfDevice ncDevice = controller.getDevicesMap().get(handler().data().deviceId());
+        if (ncDevice == null) {
+            log.error("Internal ONOS Error. Device has been marked as reachable, " +
+                            "but deviceID {} is not in Devices Map. Continuing with empty description",
+                    handler().data().deviceId());
+            return flowEntryCollection;
+        }
+        NetconfSession session = ncDevice.getSession();
+        CoreService coreService = checkNotNull(handler().get(CoreService.class));
+        ApplicationId appId = coreService.getAppId(MICROSEMI_DRIVERS);
+        MseaSaFilteringNetconfService mseaSaFilteringService =
+                (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
+        MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
+                (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
+        log.debug("getFlowEntries() called on EA1000FlowRuleProgrammable");
+
+        //First get the MseaSaFiltering rules
+        SourceIpaddressFiltering sip =
+                new DefaultSourceIpaddressFiltering();
+
+        MseaSaFilteringOpParam op =
+                new MseaSaFilteringOpParam();
+        op.sourceIpaddressFiltering(sip);
+
+        try {
+            MseaSaFiltering saFilteringCurrent =
+                    mseaSaFilteringService.getMseaSaFiltering(op, session);
+            if (saFilteringCurrent != null &&
+                    saFilteringCurrent.sourceIpaddressFiltering() != null) {
+                flowEntryCollection.addAll(
+                        convertSaFilteringToFlowRules(saFilteringCurrent, appId));
+            }
+        } catch (NetconfException e) {
+            if (e.getCause() instanceof TimeoutException) {
+                log.warn("Timeout exception getting SA Filt Flow Entries from {}",
+                        handler().data().deviceId());
+                return flowEntryCollection;
+            } else {
+                log.error("Unexpected error on SA Filt getFlowEntries on {}",
+                        handler().data().deviceId(), e);
+            }
+        }
+
+
+        //Then get the EVCs - there will be a flow entry per EVC
+        MefServices mefServices = new DefaultMefServices();
+        mefServices.uni(new DefaultUni());
+
+        MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
+        mseaUniEvcServiceFilter.mefServices(mefServices);
+        try {
+            MseaUniEvcService uniEvcCurrent =
+                    mseaUniEvcServiceSvc.getConfigMseaUniEvcService(mseaUniEvcServiceFilter,
+                            session, DatastoreId.RUNNING);
+
+            flowEntryCollection.addAll(
+                    convertEvcUniToFlowRules(uniEvcCurrent, portAssignment));
+
+        } catch (NetconfException e) {
+            if (e.getCause() instanceof TimeoutException) {
+                log.warn("Timeout exception getting EVC Flow Entries from {}",
+                        handler().data().deviceId());
+                return flowEntryCollection;
+            } else {
+                log.error("Unexpected error on EVC getFlowEntries on {}",
+                        handler().data().deviceId(), e);
+            }
+        }
+
+        return flowEntryCollection;
+    }
+
+    /**
+     * Apply the flow entries to the EA1000.
+     * Since the EA1000 does not have any 'real' flow entries these are converted 2 configuration
+     * areas on the EA1000 NETCONF model - to SA filtering YANG model and to EVC UNI YANG model.<br>
+     * Only a subset of the possible OpenFlow rules are supported. Any rule that's not handled
+     * will not be in the returned set.
+     *
+     * @param rules A collection of Flow Rules to be applied to the EA1000
+     * @return A collection of the Flow Rules that have been added.
+     */
+    @Override
+    public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
+        Collection<FlowRule> frAdded = new HashSet<FlowRule>();
+        if (rules == null || rules.size() == 0) {
+            return rules;
+        }
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+        MseaSaFilteringNetconfService mseaSaFilteringService =
+                (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
+        MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
+                (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
+        log.debug("applyFlowRules() called on EA1000FlowRuleProgrammable with {} rules.", rules.size());
+        // FIXME: Change this so it's dynamically driven
+        UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
+
+        List<SourceAddressRange> saRangeList = new ArrayList<SourceAddressRange>();
+        Map<Integer, Evc> evcMap = new HashMap<>();
+
+        //Retrieve the list of actual EVCs and the CeVlanMaps from device
+        List<Evc> activeEvcs = new ArrayList<>();
+        try {
+            sessionMutex.acquire();
+            MseaUniEvcService evcResponse =
+                    mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING);
+            //There could be zero or more EVCs
+            if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) {
+                activeEvcs.addAll(evcResponse.mefServices().uni().evc());
+            }
+        } catch (NetconfException | InterruptedException e1) {
+            log.warn("Unexpected error on applyFlowRules", e1);
+        }
+
+        for (FlowRule fr : rules) {
+
+            // IP SA Filtering can only apply to Port 0 optics
+            if (fr.selector().getCriterion(Type.IPV4_SRC) != null &&
+                    fr.selector().getCriterion(Type.IN_PORT) != null &&
+                    ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) {
+                parseFrForSaRange(frAdded, saRangeList, fr);
+
+            // EVCs will be defined by Flow Rules relating to VIDs
+            } else if (fr.selector().getCriterion(Type.VLAN_VID) != null &&
+                    fr.selector().getCriterion(Type.IN_PORT) != null) {
+                //There could be many Flow Rules for one EVC depending on the ceVlanMap
+                //Cannot build up the EVC until we know the details - the key is the tableID and port
+                parseFrForEvcs(frAdded, evcMap, activeEvcs, portAssignment, fr);
+            } else {
+                log.info("Unexpected Flow Rule type applied: " + fr);
+            }
+        }
+
+        //If there are IPv4 Flow Rules created commit them now through the
+        //MseaSaFiltering service
+        if (saRangeList.size() > 0) {
+            try {
+                mseaSaFilteringService.setMseaSaFiltering(
+                            buildSaFilteringObject(saRangeList), session, DatastoreId.RUNNING);
+            } catch (NetconfException e) {
+                log.error("Error applying Flow Rules to SA Filtering - will try again: " + e.getMessage());
+                sessionMutex.release();
+                return frAdded;
+            }
+        }
+        //If there are EVC flow rules then populate the MseaUniEvc part of EA1000
+        if (evcMap.size() > 0) {
+            List<Evc> evcList = evcMap.entrySet().stream()
+                    .map(x -> x.getValue())
+                    .collect(Collectors.toList());
+            Uni uni = new DefaultUni();
+            URI deviceName = handler().data().deviceId().uri();
+            uni.name(new Identifier45("Uni-on-"
+                    + deviceName.getSchemeSpecificPart()));
+            uni.evc(evcList);
+
+            List<BwpGroup> bwpGroupList = new ArrayList<BwpGroup>();
+            BwpGroup bwpGrp = new DefaultBwpGroup();
+            bwpGrp.groupIndex((short) 0);
+            bwpGroupList.add(bwpGrp);
+            Profiles profiles = new DefaultProfiles();
+            profiles.bwpGroup(bwpGroupList);
+
+            MefServices mefServices = new DefaultMefServices();
+            mefServices.uni(uni);
+            mefServices.profiles(profiles);
+
+            MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
+            mseaUniEvcServiceFilter.mefServices(mefServices);
+            try {
+                mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, DatastoreId.RUNNING);
+            } catch (NetconfException e) {
+                log.error("Error applying Flow Rules to EVC - will try again: " + e.getMessage());
+                sessionMutex.release();
+                return frAdded;
+            }
+        }
+        sessionMutex.release();
+        return frAdded;
+    }
+
+    /**
+     * Remove flow rules from the EA1000.
+     * Since the EA1000 does not have any 'real' flow entries these are converted 2 configuration
+     * areas on the EA1000 NETCONF model - to SA filtering YANG model and to EVC UNI YANG model.
+     *
+     * @param rulesToRemove A collection of Flow Rules to be removed to the EA1000
+     * @return A collection of the Flow Rules that have been removed.
+     */
+    @Override
+    public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rulesToRemove) {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+        MseaSaFilteringNetconfService mseaSaFilteringService =
+                (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
+        MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
+                (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
+        UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
+        log.debug("removeFlowRules() called on EA1000FlowRuleProgrammable with {} rules.", rulesToRemove.size());
+
+        if (rulesToRemove.size() == 0) {
+            return rulesToRemove;
+        }
+
+        //Retrieve the list of actual EVCs and the CeVlanMaps from device
+        List<Evc> activeEvcs = new ArrayList<>();
+        List<Short> acvtiveFiltRanges = new ArrayList<>();
+        try {
+            sessionMutex.acquire();
+            MseaUniEvcService evcResponse =
+                    mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING);
+            //There could be zero or more EVCs
+            if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) {
+                activeEvcs.addAll(evcResponse.mefServices().uni().evc());
+            }
+            mseaSaFilteringService.getConfigMseaSaFilterIds(session).forEach(
+                    r -> acvtiveFiltRanges.add(r.rangeId()));
+
+        } catch (NetconfException | InterruptedException e1) {
+            log.warn("Error on removeFlowRules.", e1);
+        }
+
+        List<SourceAddressRange> saRangeList = new ArrayList<SourceAddressRange>();
+        Map<Integer, String> ceVlanMapMap = new HashMap<>();
+        Map<Integer, List<Short>> flowIdMap = new HashMap<>();
+
+        Collection<FlowRule> rulesRemoved = new HashSet<FlowRule>();
+        for (FlowRule ruleToRemove : rulesToRemove) {
+            // IP SA Filtering can only apply to Port 0 optics
+            if (ruleToRemove.selector().getCriterion(Type.IPV4_SRC) != null &&
+                    ruleToRemove.selector().getCriterion(Type.IN_PORT) != null &&
+                    ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) {
+                SourceAddressRange sar = new DefaultSourceAddressRange();
+                sar.rangeId((short) ruleToRemove.tableId());
+                acvtiveFiltRanges.remove(Short.valueOf((short) ruleToRemove.tableId()));
+                rulesRemoved.add(ruleToRemove);
+                saRangeList.add(sar);
+
+            } else if (ruleToRemove.selector().getCriterion(Type.VLAN_VID) != null &&
+                    ruleToRemove.selector().getCriterion(Type.IN_PORT) != null) {
+                PortNumber portNumber = ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port();
+                VlanId vlanId = ((VlanIdCriterion) ruleToRemove.selector().getCriterion(Type.VLAN_VID)).vlanId();
+                int evcId = ruleToRemove.tableId();
+                int evcKey = (evcId << 2) + (int) portNumber.toLong();
+                String activeCeVlanMap = "";
+                //If this is one of many VLANs belonging to an EVC then we should only remove this VLAN
+                // from the ceVlanMap and not the whole EVC
+                if (!ceVlanMapMap.containsKey(evcKey)) {
+                    for (Evc activeEvc:activeEvcs) {
+                        if (activeEvc.evcIndex() == evcId) {
+                            if (Ea1000Port.fromNum(portNumber.toLong()).nOrC(portAssignment) ==
+                                    UniSide.CUSTOMER) {
+                                activeCeVlanMap = activeEvc.evcPerUni().evcPerUnic().ceVlanMap().string();
+                            } else if (Ea1000Port.fromNum(portNumber.toLong()).nOrC(portAssignment) ==
+                                    UniSide.NETWORK) {
+                                activeCeVlanMap = activeEvc.evcPerUni().evcPerUnin().ceVlanMap().string();
+                            }
+                        }
+                    }
+                }
+
+                ceVlanMapMap.put(evcKey, CeVlanMapUtils.removeFromCeVlanMap(activeCeVlanMap, vlanId.id()));
+                if (!flowIdMap.containsKey(evcKey)) {
+                    flowIdMap.put(evcKey, new ArrayList<>());
+                }
+                flowIdMap.get(evcKey).add(vlanId.id());
+                rulesRemoved.add(ruleToRemove);
+
+            } else {
+                log.info("Unexpected Flow Rule type removal: " + ruleToRemove);
+            }
+        }
+
+        //If there are IPv4 Flow Rules created commit them now through the
+        //MseaSaFiltering service
+        if (saRangeList.size() > 0 && acvtiveFiltRanges.size() == 0) {
+            try {
+                SourceIpaddressFiltering saFilter =
+                        new DefaultSourceIpaddressFiltering();
+                MseaSaFilteringOpParam mseaSaFiltering = new MseaSaFilteringOpParam();
+                mseaSaFiltering.sourceIpaddressFiltering(saFilter);
+
+                mseaSaFilteringService.deleteMseaSaFilteringRange(
+                        mseaSaFiltering, session, DatastoreId.RUNNING);
+            } catch (NetconfException e) {
+                log.warn("Remove FlowRule on MseaSaFilteringService could not delete all SARules - "
+                        + "they may already have been deleted: " + e.getMessage());
+            }
+        } else if (saRangeList.size() > 0) {
+            try {
+                mseaSaFilteringService.deleteMseaSaFilteringRange(
+                        buildSaFilteringObject(saRangeList), session, DatastoreId.RUNNING);
+            } catch (NetconfException e) {
+                log.warn("Remove FlowRule on MseaSaFilteringService could not delete SARule - "
+                        + "it may already have been deleted: " + e.getMessage());
+            }
+        }
+
+        if (ceVlanMapMap.size() > 0) {
+            try {
+                mseaUniEvcServiceSvc.removeEvcUniFlowEntries(ceVlanMapMap, flowIdMap,
+                        session, DatastoreId.RUNNING, portAssignment);
+            } catch (NetconfException e) {
+                log.warn("Remove FlowRule on MseaUniEvcService could not delete EVC - "
+                        + "it may already have been deleted: " + e.getMessage());
+            }
+        }
+
+        sessionMutex.release();
+        return rulesRemoved;
+    }
+
+    /**
+     * An internal method for extracting one EVC from a list and returning its ceVlanMap.
+     *
+     * @param evcList - the list of known EVCs
+     * @param evcIndex - the index of the EVC we're looking for
+     * @param side - the side of the UNI
+     * @return - the CEVlanMap we're looking for
+     */
+    private String getCeVlanMapForIdxFromEvcList(List<Evc> evcList, long evcIndex, UniSide side) {
+        if (evcList != null && evcList.size() > 0) {
+            for (Evc evc:evcList) {
+                if (evc.evcIndex() == evcIndex && evc.evcPerUni() != null) {
+                    if (side == UniSide.CUSTOMER &&
+                        evc.evcPerUni().evcPerUnic() != null &&
+                        evc.evcPerUni().evcPerUnic().ceVlanMap() != null) {
+                        return evc.evcPerUni().evcPerUnic().ceVlanMap().string();
+                    } else if (side == UniSide.NETWORK &&
+                        evc.evcPerUni().evcPerUnin() != null &&
+                        evc.evcPerUni().evcPerUnin().ceVlanMap() != null) {
+                        return evc.evcPerUni().evcPerUnin().ceVlanMap().string();
+                    }
+                }
+            }
+        }
+
+        return ""; //The EVC required was not in the list
+    }
+
+    /**
+     * An internal method to convert from a FlowRule to SARange.
+     *
+     * @param frList A collection of flow rules
+     * @param saRangeList A list of SARanges
+     * @param fr A flow rule
+     */
+    private void parseFrForSaRange(Collection<FlowRule> frList, List<SourceAddressRange> saRangeList, FlowRule fr) {
+        String ipAddrStr = fr.selector().getCriterion(Type.IPV4_SRC).toString().substring(9);
+        log.debug("Applying IP address to " + ipAddrStr
+                + " (on Port 0) to IP SA Filtering on EA1000 through NETCONF");
+
+        SourceAddressRange sar =
+                new DefaultSourceAddressRange();
+
+        sar.rangeId((short) fr.tableId());
+        sar.name("Flow:" + fr.id().toString());
+        sar.ipv4AddressPrefix(ipAddrStr);
+
+        frList.add(fr);
+        saRangeList.add(sar);
+    }
+
+    private void parseFrForEvcs(Collection<FlowRule> frList, Map<Integer, Evc> evcMap,
+            List<Evc> activeEvcs, UniSideInterfaceAssignmentEnum portAssignment, FlowRule fr) {
+        //There could be many Flow Rules for one EVC depending on the ceVlanMap
+        //Cannot build up the EVC until we know the details - the key is the tableID and port
+        Ea1000Port port = Ea1000Port.fromNum(
+                ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong());
+        Integer evcKey = (fr.tableId() << 2) + port.portNum();
+        VlanId sourceVid = ((VlanIdCriterion) fr.selector().getCriterion(Type.VLAN_VID)).vlanId();
+        FlowMapping fm = new DefaultFlowMapping();
+        fm.ceVlanId(VlanIdType.of(sourceVid.id()));
+        fm.flowId(BigInteger.valueOf(fr.id().value()));
+
+        if (evcMap.containsKey(evcKey)) { //Is there an entry already for this EVC and port?
+            //Replace ceVlanMap
+            if (port.nOrC(portAssignment) == UniSide.CUSTOMER) {
+                evcMap.get(evcKey).evcPerUni().evcPerUnic().addToFlowMapping(fm);
+                ServiceListType newCeVlanMap = new ServiceListType(
+                        CeVlanMapUtils.addtoCeVlanMap(
+                                evcMap.get(evcKey).evcPerUni().evcPerUnic().ceVlanMap().toString(),
+                                sourceVid.toShort()));
+                evcMap.get(evcKey).evcPerUni().evcPerUnic().ceVlanMap(newCeVlanMap);
+            } else {
+                evcMap.get(evcKey).evcPerUni().evcPerUnin().addToFlowMapping(fm);
+                ServiceListType newCeVlanMap = new ServiceListType(
+                        CeVlanMapUtils.addtoCeVlanMap(
+                                evcMap.get(evcKey).evcPerUni().evcPerUnin().ceVlanMap().toString(),
+                                sourceVid.toShort()));
+                evcMap.get(evcKey).evcPerUni().evcPerUnin().ceVlanMap(newCeVlanMap);
+            }
+        } else if (evcMap.containsKey((evcKey ^ 1))) { //Is there an entry for this EVC but the opposite port?
+            TagManipulation tm = getTagManipulation(fr);
+            if (port.nOrC(portAssignment) == UniSide.NETWORK) {
+                ServiceListType newCeVlanMap = new ServiceListType(
+                        CeVlanMapUtils.addtoCeVlanMap(
+                                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ceVlanMap().toString(),
+                                sourceVid.toShort()));
+                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ceVlanMap(newCeVlanMap);
+                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().tagManipulation(tm);
+                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().addToFlowMapping(fm);
+                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ingressBwpGroupIndex(getMeterId(fr.treatment()));
+            } else {
+                ServiceListType newCeVlanMap = new ServiceListType(
+                        CeVlanMapUtils.addtoCeVlanMap(
+                                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ceVlanMap().toString(),
+                                sourceVid.toShort()));
+                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ceVlanMap(newCeVlanMap);
+                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().tagManipulation(tm);
+                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().addToFlowMapping(fm);
+                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ingressBwpGroupIndex(getMeterId(fr.treatment()));
+            }
+        } else {
+            Evc evc = new DefaultEvc();
+            EvcPerUnin epun = new CustomEvcPerUnin();
+            EvcPerUnic epuc = new CustomEvcPerUnic();
+            TagManipulation tm = getTagManipulation(fr);
+
+            UniSide side = port.nOrC(portAssignment);
+            String oldCeVlanMap = getCeVlanMapForIdxFromEvcList(activeEvcs, fr.tableId(), side);
+            String newCeVlanMap =
+                    CeVlanMapUtils.addtoCeVlanMap(oldCeVlanMap, sourceVid.id());
+            String oppositeCeVlanMap =
+                    getCeVlanMapForIdxFromEvcList(activeEvcs, fr.tableId(),
+                            port.opposite().nOrC(portAssignment));
+            oppositeCeVlanMap = oppositeCeVlanMap.isEmpty() ? "0" : oppositeCeVlanMap;
+            if (side == UniSide.NETWORK) {
+                epun.ceVlanMap(new ServiceListType(newCeVlanMap));
+                epun.tagManipulation(tm);
+                epun.addToFlowMapping(fm);
+                epun.ingressBwpGroupIndex(getMeterId(fr.treatment()));
+
+                epuc.ceVlanMap(new ServiceListType(oppositeCeVlanMap));
+                epuc.ingressBwpGroupIndex(new Long(0));
+            } else {
+                epuc.ceVlanMap(new ServiceListType(newCeVlanMap));
+                epuc.tagManipulation(tm);
+                epuc.addToFlowMapping(fm);
+                epuc.ingressBwpGroupIndex(getMeterId(fr.treatment()));
+
+                epun.ceVlanMap(new ServiceListType(oppositeCeVlanMap));
+                epun.ingressBwpGroupIndex(new Long(0));
+            }
+
+            evc.evcIndex(fr.tableId());
+            evc.name(new Identifier45("EVC-" + String.valueOf(fr.tableId())));
+
+            DefaultEvcPerUni epu = new DefaultEvcPerUni();
+            epu.evcPerUnin(epun);
+            epu.evcPerUnic(epuc);
+            evc.evcPerUni(epu);
+
+            evcMap.put(evcKey, evc);
+        }
+
+        frList.add(fr);
+    }
+
+
+    private MseaSaFilteringOpParam buildSaFilteringObject(List<SourceAddressRange> saRangeList) {
+        InterfaceEth0 saIf = new DefaultInterfaceEth0();
+        for (SourceAddressRange sa:saRangeList) {
+            saIf.addToSourceAddressRange(sa);
+        }
+        saIf.filterAdminState(FilterAdminStateEnum.BLACKLIST);
+
+        SourceIpaddressFiltering saFilter =
+                new DefaultSourceIpaddressFiltering();
+        saFilter.interfaceEth0(saIf);
+
+        MseaSaFilteringOpParam mseaSaFiltering = new MseaSaFilteringOpParam();
+        mseaSaFiltering.sourceIpaddressFiltering(saFilter);
+
+        return mseaSaFiltering;
+    }
+
+    private Collection<FlowEntry> convertSaFilteringToFlowRules(
+            MseaSaFiltering saFilteringCurrent, ApplicationId appId) {
+        Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
+
+        List<SourceAddressRange> saRangelist =
+                saFilteringCurrent.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
+        Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0));
+        TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();
+
+        if (saRangelist != null) {
+            for (SourceAddressRange sa : saRangelist) {
+                Criterion matchIpSrc = Criteria.matchIPSrc(IpPrefix.valueOf(sa.ipv4AddressPrefix()));
+
+                TrafficSelector selector = tsBuilder.add(matchIpSrc).add(matchInPort).build();
+
+                TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder();
+                TrafficTreatment treatment = trBuilder.drop().build();
+
+                FlowRule.Builder feBuilder = new DefaultFlowRule.Builder();
+                if (sa.name() != null && sa.name().startsWith("Flow:")) {
+                    String[] nameParts = sa.name().split(":");
+                    Long cookie = Long.valueOf(nameParts[1], 16);
+                    feBuilder = feBuilder.withCookie(cookie);
+                } else {
+                    feBuilder = feBuilder.fromApp(appId);
+                }
+
+                FlowRule fr = feBuilder
+                        .forDevice(handler().data().deviceId())
+                        .withSelector(selector)
+                        .withTreatment(treatment)
+                        .forTable(sa.rangeId())
+                        .makePermanent()
+                        .withPriority(PRIORITY_DEFAULT)
+                        .build();
+
+                flowEntryCollection.add(
+                        new DefaultFlowEntry(fr, FlowEntryState.ADDED, 0, 0, 0));
+            }
+        }
+        return flowEntryCollection;
+    }
+
+
+    private Collection<FlowEntry> convertEvcUniToFlowRules(
+            MseaUniEvcService uniEvcCurrent, UniSideInterfaceAssignmentEnum portAssignment) {
+        Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
+
+        if (uniEvcCurrent == null || uniEvcCurrent.mefServices() == null ||
+                uniEvcCurrent.mefServices().uni() == null || uniEvcCurrent.mefServices().uni().evc() == null) {
+            log.info("No EVC's found when getting flow rules");
+            return flowEntryCollection;
+        }
+
+        for (Evc evc:uniEvcCurrent.mefServices().uni().evc()) {
+            FlowRule.Builder frBuilder = new DefaultFlowRule.Builder();
+            TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();
+
+            TrafficTreatment uniNTreatment = treatmentForUniSde(evc.evcPerUni(), true);
+            //Depending on the ceVlanMap there may be multiple VLans and hence multiple flow entries
+            Short[] vlanIdsUniN =
+                    CeVlanMapUtils.getVlanSet(ceVlanMapForUniSide(evc.evcPerUni(), true));
+            for (Short vlanId:vlanIdsUniN) {
+                if (vlanId == 0) {
+                    continue;
+                }
+                Criterion uniNportCriterion = criterionPortForUniSide(portAssignment, true);
+                TrafficSelector tsUniN = tsBuilder.matchVlanId(VlanId.vlanId(vlanId)).add(uniNportCriterion).build();
+                long flowId = getFlowIdForVlan(evc.evcPerUni().evcPerUnin().flowMapping(), vlanId);
+
+                FlowRule frUniN = frBuilder
+                    .forDevice(handler().data().deviceId())
+                    .withSelector(tsUniN)
+                    .withTreatment(uniNTreatment)
+                    .forTable(new Long(evc.evcIndex()).intValue()) //narrowing to int
+                    .makePermanent()
+                    .withPriority(PRIORITY_DEFAULT)
+                    .withCookie(flowId)
+                    .build();
+                flowEntryCollection.add(new DefaultFlowEntry(frUniN, FlowEntryState.ADDED, 0, 0, 0));
+            }
+
+            TrafficTreatment uniCTreatment = treatmentForUniSde(evc.evcPerUni(), false);
+            //Depending on the ceVlanMap there may be multiple VLans and hence multiple flow entries
+            Short[] vlanIdsUniC =
+                    CeVlanMapUtils.getVlanSet(ceVlanMapForUniSide(evc.evcPerUni(), false));
+            if (vlanIdsUniC != null && vlanIdsUniC.length > 0) {
+                for (Short vlanId:vlanIdsUniC) {
+                    if (vlanId == 0) {
+                        continue;
+                    }
+                    Criterion uniCportCriterion = criterionPortForUniSide(portAssignment, false);
+                    TrafficSelector tsUniC =
+                            tsBuilder.matchVlanId(VlanId.vlanId(vlanId)).add(uniCportCriterion).build();
+                    long flowId = getFlowIdForVlan(evc.evcPerUni().evcPerUnic().flowMapping(), vlanId);
+
+                    FlowRule frUniC = frBuilder
+                            .forDevice(handler().data().deviceId())
+                            .withSelector(tsUniC)
+                            .withTreatment(uniCTreatment)
+                            .forTable(new Long(evc.evcIndex()).intValue()) //narrowing to int
+                            .makePermanent()
+                            .withPriority(PRIORITY_DEFAULT)
+                            .withCookie(flowId)
+                            .build();
+                    flowEntryCollection.add(new DefaultFlowEntry(frUniC, FlowEntryState.ADDED, 0, 0, 0));
+                }
+            }
+        }
+
+        return flowEntryCollection;
+    }
+
+    private long getFlowIdForVlan(List<FlowMapping> fmList, Short vlanId) {
+        if (fmList == null || vlanId == null) {
+            log.warn("Flow Mapping list is null when reading EVCs");
+            return -1L;
+        }
+        for (FlowMapping fm:fmList) {
+            if (fm.ceVlanId().uint16() == vlanId.intValue()) {
+                return fm.flowId().longValue();
+            }
+        }
+        return 0L;
+    }
+
+    private String ceVlanMapForUniSide(
+            EvcPerUni evcPerUni, boolean portN) {
+        if (portN) {
+            return evcPerUni.evcPerUnin().ceVlanMap().string();
+        } else {
+            return evcPerUni.evcPerUnic().ceVlanMap().string();
+        }
+    }
+
+    private Criterion criterionPortForUniSide(
+            UniSideInterfaceAssignmentEnum portAssignment, boolean portN) {
+        boolean cOnOptics = (portAssignment == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS);
+        int portNum = ((cOnOptics && portN) || (!cOnOptics && !portN)) ? 1 : 0;
+        return Criteria.matchInPort(PortNumber.portNumber(portNum));
+    }
+
+    private TrafficTreatment treatmentForUniSde(
+            EvcPerUni evcPerUni, boolean portN) {
+        TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder();
+
+        TagManipulation tm = null;
+        short meterId = 0;
+        if (portN) {
+            tm = evcPerUni.evcPerUnin().tagManipulation();
+            meterId = (short) evcPerUni.evcPerUnin().ingressBwpGroupIndex();
+        } else {
+            tm = evcPerUni.evcPerUnic().tagManipulation();
+            meterId = (short) evcPerUni.evcPerUnic().ingressBwpGroupIndex();
+        }
+
+        if (meterId > 0L) {
+            trBuilder = trBuilder.meter(MeterId.meterId((long) meterId));
+//            trBuilder = trBuilder.meter(MeterId.meterId(meterId)).transition(0);
+        }
+
+        if (tm == null) {
+            return trBuilder.build(); //no tag manipulation found
+        }
+
+        if (tm.getClass().equals(DefaultTagPush.class)) {
+            VlanId pushVlanNum = VlanId.vlanId((short) ((TagPush) tm).tagPush().outerTagVlan().uint16());
+            PushTagTypeEnum pushTagType = ((TagPush) tm).tagPush().pushTagType();
+            //Note - the order of elements below MUST match the order of the Treatment in the stored FlowRule
+            // to be an exactMatch. See DefaultFlowRule.exactMatch()
+            trBuilder = trBuilder
+                    .pushVlan(pushTagType.equals(PushTagTypeEnum.PUSHCTAG) ?
+                            EtherType.VLAN.ethType() : EtherType.QINQ.ethType())
+                    .setVlanId(pushVlanNum).transition(Integer.valueOf(0));
+
+        } else if (tm.getClass().equals(DefaultTagPop.class)) {
+            trBuilder = trBuilder.popVlan();
+
+        } else if (tm.getClass().equals(DefaultTagOverwrite.class)) {
+            TagOverwrite to = (TagOverwrite) tm;
+            VlanId ovrVlanNum = VlanId
+                    .vlanId((short) (
+                            //There are 2 classes TagOverwrite - the other one is already imported
+                            to
+                            .tagOverwrite()
+                            .outerTagVlan()
+                            .uint16()));
+            trBuilder = trBuilder.setVlanId(ovrVlanNum);
+
+        }
+
+        return trBuilder.build();
+    }
+
+    private static TagManipulation getTagManipulation(FlowRule fr) {
+        boolean isPop = false;
+        boolean isPush = false;
+        VlanId vlanId = null;
+        EthType ethType = EtherType.VLAN.ethType(); //Default
+        for (Instruction inst:fr.treatment().allInstructions()) {
+            if (inst.type() == Instruction.Type.L2MODIFICATION) {
+                L2ModificationInstruction l2Mod = (L2ModificationInstruction) inst;
+                if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) {
+                    isPop = true;
+                } else if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
+                    isPush = true;
+                    ethType = ((ModVlanHeaderInstruction) l2Mod).ethernetType();
+                } else if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_ID) {
+                    vlanId = ((ModVlanIdInstruction) l2Mod).vlanId();
+                }
+            }
+        }
+
+        if (isPop) {
+            //The should be no vlanId in this case
+            TagPop pop = new DefaultTagPop();
+            org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
+                .evcperuniextensionattributes.tagmanipulation
+                .tagpop.TagPop popInner =
+                    new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
+                        .mseaunievcservice.evcperuniextensionattributes
+                        .tagmanipulation.tagpop.DefaultTagPop();
+            pop.tagPop(popInner);
+            return pop;
+
+        } else if (isPush && vlanId != null) {
+            TagPush push = new DefaultTagPush();
+            org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
+                .evcperuniextensionattributes.tagmanipulation
+                .tagpush.TagPush pushInner =
+                    new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
+                        .mseaunievcservice.evcperuniextensionattributes
+                        .tagmanipulation.tagpush.DefaultTagPush();
+            pushInner.outerTagVlan(new VlanIdType(vlanId.id()));
+            pushInner.pushTagType(ethType.equals(EtherType.VLAN.ethType()) ?
+                                PushTagTypeEnum.PUSHCTAG : PushTagTypeEnum.PUSHSTAG);
+            push.tagPush(pushInner);
+            return push;
+
+        } else if (vlanId != null) { //This is overwrite, as it has vlanId, but not push or pop
+            TagOverwrite ovr = new DefaultTagOverwrite();
+            org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
+                .evcperuniextensionattributes.tagmanipulation
+                .tagoverwrite.TagOverwrite ovrInner =
+                    new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
+                        .mseaunievcservice.evcperuniextensionattributes
+                        .tagmanipulation.tagoverwrite.DefaultTagOverwrite();
+            ovrInner.outerTagVlan(new VlanIdType(vlanId.id()));
+            ovr.tagOverwrite(ovrInner);
+            return ovr;
+        }
+
+        return null;
+    }
+
+    private static long getMeterId(TrafficTreatment treatment) {
+        return (treatment.metered() != null && treatment.metered().meterId() != null)
+                ? treatment.metered().meterId().id() : 0L;
+    }
+
+    /**
+     * An enumerated type that characterises the 2 port layout of the EA1000 device.
+     * The device is in an SFP package and has only 2 ports, the HOST port which
+     * plugs in to the chassis (Port 1) and the Optics Port on the rear (Port 0).
+     */
+    public enum Ea1000Port {
+        HOST(1),
+        OPTICS(0);
+
+        private int num = 0;
+        private Ea1000Port(int num) {
+            this.num = num;
+        }
+
+        /**
+         * The numerical assignment of this port.
+         * @return The port number
+         */
+        public int portNum() {
+            return num;
+        }
+
+        /**
+         * Return the enumerated value from a port number.
+         * @param num The port number
+         * @return An enumerated value
+         */
+        public static Ea1000Port fromNum(long num) {
+            for (Ea1000Port a:Ea1000Port.values()) {
+                if (a.num == num) {
+                    return a;
+                }
+            }
+            return HOST;
+        }
+
+        /**
+         * Get the port that the UNI-N is present on.
+         * @param side The assignment of UNI-side to port
+         * @return An enumerated value
+         */
+        public static Ea1000Port uniNNum(UniSideInterfaceAssignmentEnum side) {
+            if (side.equals(UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST)) {
+                return OPTICS;
+            } else {
+                return HOST;
+            }
+        }
+
+        /**
+         * Get the port that the UNI-C is present on.
+         * @param side The assignment of UNI-side to port
+         * @return An enumerated value
+         */
+        public static Ea1000Port uniCNum(UniSideInterfaceAssignmentEnum side) {
+            if (side.equals(UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST)) {
+                return HOST;
+            } else {
+                return OPTICS;
+            }
+        }
+
+        /**
+         * Get the port opposite the current port.
+         * @return An enumerated value for the opposite side
+         */
+        public Ea1000Port opposite() {
+            if (this.equals(HOST)) {
+                return OPTICS;
+            } else {
+                return HOST;
+            }
+        }
+
+        /**
+         * Evaluate which side of the UNI on the EA1000 device this port refers to.
+         * @param side The assignment of UNI-side to port
+         * @return An enumerated value representing the UniSide
+         */
+        public UniSide nOrC(UniSideInterfaceAssignmentEnum side) {
+            if ((this == HOST && side == UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST) ||
+                    (this == OPTICS && side == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS)) {
+                return UniSide.CUSTOMER;
+            } else {
+                return UniSide.NETWORK;
+            }
+        }
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java
new file mode 100644
index 0000000..226ad2f
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi;
+
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+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.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.CoreService;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.Meter.Unit;
+import org.onosproject.net.meter.MeterOperation;
+import org.onosproject.net.meter.MeterOperations;
+import org.onosproject.net.meter.MeterProvider;
+import org.onosproject.net.meter.MeterProviderRegistry;
+import org.onosproject.net.meter.MeterProviderService;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+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.mseatypes.rev20160229.mseatypes.CosColorType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.coscolortype.CosColorTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.Cos;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultCos;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.Bwp;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.DefaultBwp;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.DefaultEvcCosTypeEvcColorId;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.EvcCosTypeEvcColorId;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.DefaultEvcCosTypeAll8PrioTo1EvcColor;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.EvcCosTypeAll8PrioTo1EvcColor;
+import org.slf4j.Logger;
+
+/**
+ * Provider which uses an NETCONF controller to handle meters.
+ *
+ * TODO: move this to an architecture similar to FlowRuleDriverProvider in order
+ * to use a behavior to discover meters.
+ */
+@Component(immediate = true, enabled = true)
+public class EA1000MeterProvider extends AbstractProvider implements MeterProvider {
+
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetconfController controller;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected MeterProviderRegistry providerRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc;
+
+    private MeterProviderService providerService;
+
+    private static final int COS_INDEX_1 = 1;
+    private static final short DEFAULT_OUTGOING_PRIO = 3;
+
+    /**
+     * Creates a OpenFlow meter provider.
+     */
+    public EA1000MeterProvider() {
+        super(new ProviderId("netconf", "org.onosproject.provider.meter.microsemi"));
+    }
+
+    @Activate
+    public void activate() {
+        providerService = providerRegistry.register(this);
+
+    }
+
+    @Deactivate
+    public void deactivate() {
+        providerRegistry.unregister(this);
+
+        providerService = null;
+    }
+
+    @Override
+    public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) {
+        log.debug("Adding meterOps to Microsemi Meter Store");
+    }
+
+    @Override
+    public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) {
+        if (meterOp == null || deviceId == null) {
+            log.warn("Missing argument for performMeterOperation()");
+            return;
+        }
+        log.debug("{} meterOp {} to Microsemi Meter Store", meterOp.type(), meterOp);
+
+        long meterId = meterOp.meter().id().id();
+        String deviceName = deviceId.uri().getSchemeSpecificPart();
+        Unit unit = meterOp.meter().unit();
+
+        Profiles profiles = new DefaultProfiles();
+        if (meterOp.type() == MeterOperation.Type.ADD || meterOp.type() == MeterOperation.Type.MODIFY) {
+            Bwp bwp = new DefaultBwp();
+            bwp.cosIndex(COS_INDEX_1);
+            bwp.name("BWP-" + String.valueOf(meterId) + "-" + deviceName);
+
+            long cirRateKbps = 0L;
+            long cbsRateKbps = 0L;
+            long eirRateKbps = 0L;
+            long ebsRateKbps = 0L;
+            for (Band band:meterOp.meter().bands()) {
+                if (band.type() == Band.Type.REMARK) {
+                    //This relates to CIR/CBS
+                    cirRateKbps = toBitsPerSec(band.rate(), unit);
+                    cbsRateKbps = band.burst(); //Already in kbps
+                } else if (band.type() == Band.Type.DROP) {
+                    //This relates to EIR/EBS
+                    eirRateKbps = toBitsPerSec(band.rate(), unit);
+                    ebsRateKbps = band.burst(); //Already in kbps
+                }
+            }
+            bwp.committedInformationRate(cirRateKbps);
+            bwp.excessInformationRate(eirRateKbps - cirRateKbps);
+            if (meterOp.meter().isBurst()) {
+                bwp.committedBurstSize(cbsRateKbps);
+                bwp.excessBurstSize(ebsRateKbps - cbsRateKbps);
+            }
+
+            BwpGroup bwpg = new DefaultBwpGroup();
+            bwpg.groupIndex((short) meterId);
+            bwpg.addToBwp(bwp);
+
+            //Create cos-1 as referenced above - we only support 1 at the moment
+            Cos cos = new DefaultCos();
+            cos.cosIndex(COS_INDEX_1);
+            cos.name("COS-1");
+            cos.outgoingCosValue(PriorityType.of(DEFAULT_OUTGOING_PRIO));
+            cos.colorAware(true);
+            cos.colorForward(true);
+
+            EvcCosTypeAll8PrioTo1EvcColor ect =
+                    new DefaultEvcCosTypeAll8PrioTo1EvcColor();
+            ect.evcAll8ColorTo(CosColorType.of(CosColorTypeEnum.GREEN));
+            profiles.addToBwpGroup(bwpg);
+
+            EvcCosTypeEvcColorId cid = new DefaultEvcCosTypeEvcColorId();
+            cid.evcCosTypeAll8PrioTo1EvcColor(ect);
+            cos.cosTypeChoice(cid);
+            profiles.addToCos(cos);
+        } else if (meterOp.type() == MeterOperation.Type.REMOVE) {
+            BwpGroup bwpg = new DefaultBwpGroup();
+            bwpg.groupIndex((short) meterId);
+
+            profiles.addToBwpGroup(bwpg);
+        }
+
+        MefServices mefServices = new DefaultMefServices();
+        mefServices.profiles(profiles);
+
+        MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
+        mseaUniEvcServiceFilter.mefServices(mefServices);
+
+        NetconfSession session = controller.getDevicesMap().get(deviceId).getSession();
+        try {
+            if (meterOp.type() == MeterOperation.Type.REMOVE) {
+                mseaUniEvcServiceSvc.deleteMseaUniEvcService(mseaUniEvcServiceFilter,
+                        session, DatastoreId.RUNNING);
+            } else {
+                mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter,
+                        session, DatastoreId.RUNNING);
+            }
+        } catch (NetconfException e) {
+            //This can fail if the BWP Group is deleted before the EVC that is dependent on it
+            //The delete of the EVC will be called on a separate thread to that should proceed
+            //within a few seconds after which we should try again
+            AtomicInteger retry = new AtomicInteger(4);
+            if (meterOp.type() == MeterOperation.Type.REMOVE &&
+                    e.getMessage().startsWith("Failed to run edit-config through NETCONF")) {
+                while (retry.getAndDecrement() > 0) {
+                    try {
+                        Thread.sleep(1000L);
+                        log.debug("Retrying deletion of Bandwith Profile Group {}",
+                                String.valueOf(meterId));
+                        mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter,
+                                session, DatastoreId.RUNNING);
+                        return; //If it did not throw an exception
+                    } catch (InterruptedException e1) {
+                        log.debug("Error when deleting BWP profile on EA1000" +
+                                " - trying again in 1 sec", e1);
+                    } catch (NetconfException e1) {
+                        log.debug("NETCONF failed to delete profile - trying again in 1 sec", e1);
+                    }
+                }
+                log.error("Error deleting BWPGroup {} from {} after 4 tries: {}",
+                        meterId, deviceId, e.getMessage());
+            } else {
+                log.error("Error adding BWPGroup {} from {}: {}",
+                        meterId, deviceId, e.getMessage());
+                throw new UnsupportedOperationException(e);
+            }
+        }
+    }
+
+    private static long toBitsPerSec(long rate, Unit unit) {
+        if (unit == Unit.KB_PER_SEC) {
+            return rate * 8;
+        } else {
+            return -1;
+        }
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java
new file mode 100644
index 0000000..308bdff
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.drivers.microsemi.EA1000FlowRuleProgrammable.Ea1000Port;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.NextGroup;
+import org.onosproject.net.behaviour.Pipeliner;
+import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.slf4j.Logger;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
+import com.google.common.cache.RemovalNotification;
+
+/**
+ * Support for FlowObjectives in the EA1000.
+ *
+ * Used with the CarrierEthernet App
+ *
+ */
+public class EA1000Pipeliner extends AbstractHandlerBehaviour implements Pipeliner {
+
+    protected final Logger log = getLogger(getClass());
+    protected ServiceDirectory serviceDirectory;
+    protected FlowRuleService flowRuleService;
+    protected DeviceId deviceId;
+    protected Cache<Integer, NextObjective> pendingNext;
+    protected Integer evcIdBase = 1;
+
+    @Override
+    public void init(DeviceId deviceId, PipelinerContext context) {
+        this.serviceDirectory = context.directory();
+        this.deviceId = deviceId;
+
+        flowRuleService = serviceDirectory.get(FlowRuleService.class);
+
+        pendingNext = CacheBuilder.newBuilder()
+                .expireAfterWrite(20, TimeUnit.SECONDS)
+                .removalListener((RemovalNotification<Integer, NextObjective> notification) -> {
+                    if (notification.getCause() == RemovalCause.EXPIRED) {
+                        notification.getValue().context()
+                                .ifPresent(c -> c.onError(notification.getValue(),
+                                        ObjectiveError.FLOWINSTALLATIONFAILED));
+                    }
+                }).build();
+
+        log.debug("Loaded handler behaviour EA1000Pipeliner for " + handler().data().deviceId().uri());
+    }
+
+    @Override
+    public void filter(FilteringObjective filterObjective) {
+        TrafficTreatment.Builder actions;
+        boolean oppositePort = false;
+        int evcId = -1;
+        switch (filterObjective.type()) {
+            case PERMIT:
+                if (filterObjective.meta() == null) {
+                    actions = DefaultTrafficTreatment.builder().add(Instructions.popVlan());
+                } else {
+                    oppositePort = true; //Experimental - push happens on the opposite port
+                    actions = DefaultTrafficTreatment.builder(filterObjective.meta());
+                    if (filterObjective.meta().metered() != null) {
+                        actions.meter(filterObjective.meta().metered().meterId());
+                    }
+                    actions.transition(0);
+                    boolean isPush = false;
+                    int vid = 0;
+                    for (Instruction inst:filterObjective.meta().immediate()) {
+                        if (inst.type() == Instruction.Type.L2MODIFICATION) {
+                            L2ModificationInstruction l2mod = (L2ModificationInstruction) inst;
+                            if (l2mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
+                                isPush = true;
+                            } else if (l2mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_ID) {
+                                vid = ((ModVlanIdInstruction) l2mod).vlanId().id();
+                            }
+                        }
+                    }
+                    if (isPush && vid > 0) {
+                        evcId = vid;
+                    }
+                }
+                break;
+            case DENY:
+                actions = (filterObjective.meta() == null) ?
+                        DefaultTrafficTreatment.builder() :
+                        DefaultTrafficTreatment.builder(filterObjective.meta());
+                actions.drop();
+                break;
+            default:
+                log.warn("Unknown filter type: {}", filterObjective.type());
+                actions = DefaultTrafficTreatment.builder().drop();
+        }
+
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+
+        for (Criterion c:filterObjective.conditions()) {
+            if (c.type() == Type.VLAN_VID && evcId == -1) {
+                evcId = ((VlanIdCriterion) c).vlanId().id();
+            }
+            selector.add(c);
+        }
+
+        if (filterObjective.key() != null) {
+            if (oppositePort) {
+                //Experimental
+                Ea1000Port port = Ea1000Port.fromNum(((PortCriterion) filterObjective.key()).port().toLong());
+                selector.matchInPort(PortNumber.portNumber(port.opposite().portNum()));
+            } else {
+                selector.add(filterObjective.key());
+            }
+        }
+
+        FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+                .forDevice(deviceId)
+                .withSelector(selector.build())
+                .withTreatment(actions.build())
+                .fromApp(filterObjective.appId())
+                .forTable(evcId)
+                .withPriority(filterObjective.priority());
+
+        if (filterObjective.permanent()) {
+            ruleBuilder.makePermanent();
+        } else {
+            ruleBuilder.makeTemporary(filterObjective.timeout());
+        }
+
+        installObjective(ruleBuilder, filterObjective);
+
+        log.debug("filter() of EA1000Pipeliner called for "
+                + handler().data().deviceId().uri()
+                + ". Objective: " + filterObjective);
+    }
+
+    @Override
+    public void forward(ForwardingObjective forwardObjective) {
+        TrafficSelector selector = forwardObjective.selector();
+
+        if (forwardObjective.treatment() != null) {
+            List<Instruction> instructions = forwardObjective.treatment().immediate();
+            if (instructions != null && instructions.size() == 1
+                    && instructions.get(0).type() == Instruction.Type.OUTPUT
+                    && ((OutputInstruction) instructions.get(0)).port() == PortNumber.CONTROLLER) {
+                Set<Criterion> criteria = forwardObjective.selector().criteria();
+                log.info("EA1000 does not yet implement forwarding to CONTROLLER for flow objective for: "
+                        + handler().data().deviceId().uri()
+                        + ". "
+                        + forwardObjective);
+                return;
+            } else {
+                FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+                        .forDevice(deviceId)
+                        .withSelector(selector)
+                        .fromApp(forwardObjective.appId())
+                        .withPriority(forwardObjective.priority())
+                        .withTreatment(forwardObjective.treatment());
+
+                if (forwardObjective.permanent()) {
+                    ruleBuilder.makePermanent();
+                } else {
+                    ruleBuilder.makeTemporary(forwardObjective.timeout());
+                }
+                installObjective(ruleBuilder, forwardObjective);
+            }
+        } else {
+            NextObjective nextObjective = pendingNext.getIfPresent(forwardObjective.nextId());
+            if (nextObjective != null) {
+                pendingNext.invalidate(forwardObjective.nextId());
+                nextObjective.next().forEach(treat -> {
+                    FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+                            .forDevice(deviceId)
+                            .withSelector(selector)
+                            .fromApp(forwardObjective.appId())
+                            .withPriority(forwardObjective.priority())
+                            .withTreatment(treat);
+
+                    if (forwardObjective.permanent()) {
+                        ruleBuilder.makePermanent();
+                    } else {
+                        ruleBuilder.makeTemporary(forwardObjective.timeout());
+                    }
+                    installObjective(ruleBuilder, forwardObjective);
+                });
+            } else {
+                forwardObjective.context().ifPresent(c -> c.onError(forwardObjective,
+                        ObjectiveError.GROUPMISSING));
+            }
+        }
+        log.debug("EA1000: Unhandled Forwarding Objective for: "
+                + handler().data().deviceId().uri()
+                + ". "
+                + forwardObjective);
+    }
+
+    @Override
+    public void next(NextObjective nextObjective) {
+        pendingNext.put(nextObjective.id(), nextObjective);
+        nextObjective.context().ifPresent(context -> context.onSuccess(nextObjective));
+
+        log.debug("next() of EA1000Pipeliner called for "
+                + handler().data().deviceId().uri()
+                + ". Objective: " + nextObjective);
+    }
+
+    @Override
+    public List<String> getNextMappings(NextGroup nextGroup) {
+        log.debug("getNextMappings() of EA1000Pipeliner called for "
+                + handler().data().deviceId().uri()
+                + ". Objective: " + nextGroup);
+        return new ArrayList<String>();
+    }
+
+    protected void installObjective(FlowRule.Builder ruleBuilder, Objective objective) {
+        FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
+        switch (objective.op()) {
+
+            case ADD:
+                flowBuilder.add(ruleBuilder.build());
+                break;
+            case REMOVE:
+                flowBuilder.remove(ruleBuilder.build());
+                break;
+            default:
+                log.warn("Unknown operation {}", objective.op());
+        }
+
+        flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
+            @Override
+            public void onSuccess(FlowRuleOperations ops) {
+                objective.context().ifPresent(context -> context.onSuccess(objective));
+            }
+
+            @Override
+            public void onError(FlowRuleOperations ops) {
+                objective.context()
+                        .ifPresent(context -> context.onError(objective, ObjectiveError.FLOWINSTALLATIONFAILED));
+            }
+        }));
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java
new file mode 100644
index 0000000..dfb8480
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onlab.packet.ChassisId;
+import org.onosproject.drivers.microsemi.yang.IetfSystemNetconfService;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DefaultPortDescription;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceDescriptionDiscovery;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfDevice;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.AugmentedSysSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.DefaultAugmentedSysSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.AugmentedSysPlatform;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.DefaultAugmentedSysPlatform;
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.DateAndTime;
+import org.slf4j.Logger;
+
+public class Ea1000DeviceDescription extends AbstractHandlerBehaviour implements DeviceDescriptionDiscovery {
+
+    private String serialNumber = "unavailable";
+    private String swVersion = "unavailable";
+    private String longitudeStr = null;
+    private String latitudeStr = null;
+    private final Logger log = getLogger(getClass());
+
+    public Ea1000DeviceDescription() {
+        log.info("Loaded handler behaviour Ea1000DeviceDescription.");
+    }
+
+    @Override
+    public DeviceDescription discoverDeviceDetails() {
+        log.info("Adding description for EA1000 device");
+
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfDevice ncDevice = controller.getDevicesMap().get(handler().data().deviceId());
+        if (ncDevice == null) {
+            log.error("Internal ONOS Error. Device has been marked as reachable, " +
+                    "but deviceID {} is not in Devices Map. Continuing with empty description",
+                    handler().data().deviceId());
+            return null;
+        }
+        NetconfSession session = ncDevice.getSession();
+        IetfSystemNetconfService ietfSystemService =
+                (IetfSystemNetconfService) checkNotNull(handler().get(IetfSystemNetconfService.class));
+
+        try {
+            IetfSystem system = ietfSystemService.getIetfSystemInit(session);
+            if (system != null && system.systemState() != null) {
+                swVersion = system.systemState().platform().osRelease();
+                AugmentedSysPlatform augmentedSysPlatform =
+                        (AugmentedSysPlatform) system.systemState()
+                        .platform().augmentation(DefaultAugmentedSysPlatform.class);
+                serialNumber = augmentedSysPlatform.deviceIdentification().serialNumber();
+                DateAndTime deviceDateAndTime = system.systemState().clock().currentDatetime();
+                OffsetDateTime odt =
+                        OffsetDateTime.parse(deviceDateAndTime.string(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+                if (odt.getYear() < OffsetDateTime.now(ZoneId.of("UTC")).getYear()) {
+                    OffsetDateTime nowUtc = OffsetDateTime.now(ZoneId.of("UTC"));
+                    log.warn("Date on device is in the past: {}. Setting it to {}", odt.toString(), nowUtc);
+                    ietfSystemService.setCurrentDatetime(nowUtc, session);
+                }
+            }
+
+            if (system != null && system.system() != null) {
+                AugmentedSysSystem augmentedSystem =
+                        (AugmentedSysSystem) system.system().augmentation(DefaultAugmentedSysSystem.class);
+                longitudeStr = augmentedSystem.longitude().toPlainString();
+                latitudeStr = augmentedSystem.latitude().toPlainString();
+            }
+        } catch (NetconfException e) {
+            log.error("Unable to retrieve init data from device: " + handler().data().deviceId().toString()
+                    + " Error: " + e.getMessage());
+            e.printStackTrace();
+        }
+
+        DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
+        DeviceId deviceId = handler().data().deviceId();
+        Device device = deviceService.getDevice(deviceId);
+        DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder();
+        if (longitudeStr != null && latitudeStr != null) {
+            annotationsBuilder.set(AnnotationKeys.LONGITUDE, longitudeStr)
+                    .set(AnnotationKeys.LATITUDE, latitudeStr).build();
+        } else {
+            log.warn("Longitude and latitude could not be retrieved from device " + deviceId);
+        }
+
+        return new DefaultDeviceDescription(device.id().uri(), Device.Type.OTHER, "Microsemi", "EA1000", swVersion,
+                serialNumber, new ChassisId(), annotationsBuilder.build());
+    }
+
+    @Override
+    public List<PortDescription> discoverPortDetails() {
+
+        List<PortDescription> ports = new ArrayList<PortDescription>();
+
+        DefaultAnnotations annotationOptics = DefaultAnnotations.builder().set(AnnotationKeys.PORT_NAME, "Optics")
+                .build();
+        PortDescription optics = new DefaultPortDescription(PortNumber.portNumber(0), true, Port.Type.FIBER, 1000,
+                annotationOptics);
+        ports.add(optics);
+
+        DefaultAnnotations annotationHost = DefaultAnnotations.builder().set(AnnotationKeys.PORT_NAME, "Host").build();
+        PortDescription host = new DefaultPortDescription(PortNumber.portNumber(1), true, Port.Type.COPPER, 1000,
+                annotationHost);
+        ports.add(host);
+
+        return ports;
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java
new file mode 100644
index 0000000..724792e
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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 org.onosproject.net.behaviour.MeterQuery;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+
+/**
+ * Driver which always responds that all Meters are available for the Device.
+ */
+public class FullMetersAvailable extends AbstractHandlerBehaviour implements MeterQuery {
+
+    private static final long MAX_METER = 0x00000FFF;
+
+    @Override
+    public long getMaxMeters() {
+        return MAX_METER;
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java
new file mode 100644
index 0000000..b7f0e68
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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 org.apache.felix.scr.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+
+/**
+ * Loader for Microsemi device drivers.
+ */
+@Component(immediate = true)
+public class MicrosemiDriversLoader extends AbstractDriverLoader {
+
+    public MicrosemiDriversLoader() {
+        super("/microsemi-drivers.xml");
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java
new file mode 100644
index 0000000..53151bb
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.io.IOException;
+
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.ConfigGetter;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+import org.onosproject.netconf.NetconfController;
+import org.slf4j.Logger;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Used with the onos:device-configuration CLI command.
+ *
+ * This allows the full configuration to be retrieved from the device
+ */
+public class NetconfConfigGetter extends AbstractHandlerBehaviour implements ConfigGetter {
+
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PacketService packetService;
+
+    private PacketProcessor testProcessor;
+
+    // FIXME the error string should be universal for all implementations of
+    // ConfigGetter
+    public static final String UNABLE_TO_READ_CONFIG = "config retrieval error";
+
+    @Override
+    public String getConfiguration(String type) {
+        DriverHandler handler = handler();
+        NetconfController controller = handler.get(NetconfController.class);
+
+        DeviceId ofDeviceId = handler.data().deviceId();
+        Preconditions.checkNotNull(controller, "Netconf controller is null");
+        if (type == null ||
+                (!type.equalsIgnoreCase("running")
+                        && !type.equalsIgnoreCase("candidate")
+                        && !type.equalsIgnoreCase("startup"))) {
+            log.error("Configuration type must be either 'running', 'startup' or 'candidate'. '{}' is invalid", type);
+            return UNABLE_TO_READ_CONFIG;
+        }
+        try {
+            return controller.getDevicesMap().get(ofDeviceId).getSession().getConfig(type.replace("cfgType=", ""));
+        } catch (IOException e) {
+            log.error("Configuration could not be retrieved {}", e.getMessage());
+        }
+        return UNABLE_TO_READ_CONFIG;
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java
new file mode 100644
index 0000000..7589ea7
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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;
+
+public final class RpcResultParser {
+
+    private RpcResultParser() {
+        //Not called
+    }
+
+    public static String parseXml(final String deviceDescriptionResponse, final String keyWord) {
+
+        int end = deviceDescriptionResponse.lastIndexOf(keyWord);
+        end = deviceDescriptionResponse.lastIndexOf('<', end);
+        int start = deviceDescriptionResponse.lastIndexOf('>', end);
+        if (start > 1 && end > start) {
+            return deviceDescriptionResponse.substring(start + 1, end);
+        } else {
+            return null;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/package-info.java
new file mode 100644
index 0000000..de883d1
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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 for Microsemi device drivers.
+ */
+package org.onosproject.drivers.microsemi;
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java
new file mode 100644
index 0000000..44c62f6
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import java.time.OffsetDateTime;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.systemrestart.SystemRestartInput;
+
+/**
+ * Extension of ietfSystemService to include NETCONF sessions.
+ *
+ * This is manually extended and should be revised if the ietf-system.yang file changes
+ */
+public interface IetfSystemNetconfService {
+    /**
+     * Returns the attribute ietfSystem.
+     *
+     * @param ietfSystem value of ietfSystem
+     * @param session An active NETCONF session
+     * @return ietfSystem
+     * @throws NetconfException if the session has any error
+     */
+    IetfSystem getIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session) throws NetconfException;
+
+    /**
+     * Returns the result of the init query.
+     *
+     * @param session An active NETCONF session
+     * @return ietfSystem
+     * @throws NetconfException if the session has any error
+     */
+    IetfSystem getIetfSystemInit(NetconfSession session) throws NetconfException;
+
+    /**
+     * Sets the value to attribute ietfSystem.
+     *
+     * @param ietfSystem value of ietfSystem
+     * @param session An active NETCONF session
+     * @param ncDs datastore type running, startup or candidate
+     * @return Boolean to indicate success or failure
+     * @throws NetconfException if the session has any error
+     */
+    boolean setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session,
+          DatastoreId ncDs) throws NetconfException;
+
+    /**
+     * Service interface of setCurrentDatetime.
+     *
+     * @param date input of service interface setCurrentDatetime
+     * @param session An active NETCONF session
+     * @throws NetconfException if the session has any error
+     */
+    void setCurrentDatetime(OffsetDateTime date, NetconfSession session) throws NetconfException;
+
+    /**
+     * Service interface of systemRestart.
+     *
+     * @param inputVar input of service interface systemRestart
+     * @param session An active NETCONF session
+     * @throws NetconfException if the session has any error
+     */
+    void systemRestart(SystemRestartInput inputVar, NetconfSession session) throws NetconfException;
+
+    /**
+     * Service interface of systemShutdown.
+     *
+     * @param session An active NETCONF session
+     * @throws NetconfException if the session has any error
+     */
+    void systemShutdown(NetconfSession session) throws NetconfException;
+
+    /**
+     * Service interface of doUpgradeAndReboot.
+     *
+     * @param inputVar input of service interface doUpgradeAndReboot
+     * @param session An active NETCONF session
+     * @return doUpgradeAndRebootOutput output of service interface doUpgradeAndReboot
+     * @throws NetconfException if the session has any error
+     */
+    DoUpgradeAndRebootOutput doUpgradeAndReboot(DoUpgradeAndRebootInput inputVar, NetconfSession session)
+            throws NetconfException;
+
+    /**
+     * Service interface of pullUpdateTarFromTftp.
+     *
+     * @param inputVar input of service interface pullUpdateTarFromTftp
+     * @param session An active NETCONF session
+     * @throws NetconfException if the session has any error
+     */
+    void pullUpdateTarFromTftp(PullUpdateTarFromTftpInput inputVar, NetconfSession session)
+            throws NetconfException;
+
+    /**
+     * Service interface of readFromSyslog.
+     *
+     * @param inputVar input of service interface readFromSyslog
+     * @param session An active NETCONF session
+     * @return readFromSyslogOutput output of service interface readFromSyslog
+     * @throws NetconfException if the session has any error
+     */
+    ReadFromSyslogOutput readFromSyslog(ReadFromSyslogInput inputVar, NetconfSession session)
+            throws NetconfException;
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java
new file mode 100644
index 0000000..6cf8031
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.yang.AbstractYangModelRegistrator;
+import org.onosproject.yang.gen.v1.entitystatetcmib.rev20051122.EntityStateTcMib;
+import org.onosproject.yang.gen.v1.fpgainternal.rev20151130.FpgaInternal;
+import org.onosproject.yang.gen.v1.ianacrypthash.rev20140806.IanaCryptHash;
+import org.onosproject.yang.gen.v1.ianaiftype.rev20140508.IanaIfType;
+import org.onosproject.yang.gen.v1.ieeetypes.rev20080522.IeeeTypes;
+import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.IetfInetTypes;
+import org.onosproject.yang.gen.v1.ietfinterfaces.rev20140508.IetfInterfaces;
+import org.onosproject.yang.gen.v1.ietfnetconf.rev20110601.IetfNetconf;
+import org.onosproject.yang.gen.v1.ietfnetconfacm.rev20120222.IetfNetconfAcm;
+import org.onosproject.yang.gen.v1.ietfnetconfmonitoring.rev20101004.IetfNetconfMonitoring;
+import org.onosproject.yang.gen.v1.ietfnetconfnotifications.rev20120206.IetfNetconfNotifications;
+import org.onosproject.yang.gen.v1.ietfnetconfwithdefaults.rev20100609.IetfNetconfWithDefaults;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.IetfSystemMicrosemi;
+import org.onosproject.yang.gen.v1.ietfsystemtlsauth.rev20140524.IetfSystemTlsAuth;
+import org.onosproject.yang.gen.v1.ietfx509certtoname.rev20130326.IetfX509CertToName;
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.IetfYangTypes;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.MseaSoamFm;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.MseaSoamPm;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.MseaTypes;
+import org.onosproject.yang.gen.v1.mseaunievcinterface.rev20160317.MseaUniEvcInterface;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.ncnotifications.rev20080714.NcNotifications;
+import org.onosproject.yang.gen.v1.netopeercfgnetopeer.rev20130214.NetopeerCfgnetopeer;
+import org.onosproject.yang.gen.v1.notifications.rev20080714.Notifications;
+import org.onosproject.yang.gen.v1.rfc2544.rev20151020.Rfc2544;
+import org.onosproject.yang.gen.v1.svcactivationtypes.rev20151027.SvcActivationTypes;
+import org.onosproject.yang.gen.v1.y1564.rev20151029.Y1564;
+import org.onosproject.yang.model.DefaultYangModuleId;
+import org.onosproject.yang.model.YangModuleId;
+import org.onosproject.yang.runtime.AppModuleInfo;
+import org.onosproject.yang.runtime.DefaultAppModuleInfo;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Representation of Microsemi model registrator which registers Microsemi device
+ * models.
+ */
+@Component(immediate = true)
+public class MicrosemiModelRegistrator extends AbstractYangModelRegistrator {
+
+    public MicrosemiModelRegistrator() {
+        super(IetfSystem.class, getAppInfo());
+    }
+
+    private static Map<YangModuleId, AppModuleInfo> getAppInfo() {
+        Map<YangModuleId, AppModuleInfo> appInfo = new HashMap<>();
+
+        appInfo.put(new DefaultYangModuleId("fpga-internal", "2015-11-30"),
+                new DefaultAppModuleInfo(FpgaInternal.class, null));
+        appInfo.put(new DefaultYangModuleId("iana-if-type", "2014-05-08"),
+                new DefaultAppModuleInfo(IanaIfType.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-yang-types", "2013-07-15"),
+                new DefaultAppModuleInfo(IetfYangTypes.class, null));
+        appInfo.put(new DefaultYangModuleId("msea-sa-filtering", "2016-04-12"),
+                new DefaultAppModuleInfo(MseaSaFiltering.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-x509-cert-to-name", "2013-03-26"),
+                new DefaultAppModuleInfo(IetfX509CertToName.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-system", "2014-08-06"),
+                new DefaultAppModuleInfo(IetfSystem.class, null));
+        appInfo.put(new DefaultYangModuleId("msea-types", "2016-02-29"),
+                new DefaultAppModuleInfo(MseaTypes.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-inet-types", "2013-07-15"),
+                new DefaultAppModuleInfo(IetfInetTypes.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-netconf-with-defaults", "2010-06-09"),
+                new DefaultAppModuleInfo(IetfNetconfWithDefaults.class, null));
+        appInfo.put(new DefaultYangModuleId("msea-uni-evc-service", "2016-03-17"),
+                new DefaultAppModuleInfo(MseaUniEvcService.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-netconf-monitoring", "2010-10-04"),
+                new DefaultAppModuleInfo(IetfNetconfMonitoring.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-netconf-acm", "2012-02-22"),
+                new DefaultAppModuleInfo(IetfNetconfAcm.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-system-tls-auth", "2014-05-24"),
+                new DefaultAppModuleInfo(IetfSystemTlsAuth.class, null));
+        appInfo.put(new DefaultYangModuleId("rfc-2544", "2015-10-20"),
+                new DefaultAppModuleInfo(Rfc2544.class, null));
+        appInfo.put(new DefaultYangModuleId("msea-cfm", "2016-02-29"),
+                new DefaultAppModuleInfo(MseaCfm.class, null));
+        appInfo.put(new DefaultYangModuleId("netopeer-cfgnetopeer", "2013-02-14"),
+                new DefaultAppModuleInfo(NetopeerCfgnetopeer.class, null));
+        appInfo.put(new DefaultYangModuleId("ENTITY-STATE-TC-MIB", "2005-11-22"),
+                new DefaultAppModuleInfo(EntityStateTcMib.class, null));
+        appInfo.put(new DefaultYangModuleId("msea-soam-fm", "2016-02-29"),
+                new DefaultAppModuleInfo(MseaSoamFm.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-netconf-notifications", "2012-02-06"),
+                new DefaultAppModuleInfo(IetfNetconfNotifications.class, null));
+        appInfo.put(new DefaultYangModuleId("nc-notifications", "2008-07-14"),
+                new DefaultAppModuleInfo(NcNotifications.class, null));
+        appInfo.put(new DefaultYangModuleId("iana-crypt-hash", "2014-08-06"),
+                new DefaultAppModuleInfo(IanaCryptHash.class, null));
+        appInfo.put(new DefaultYangModuleId("msea-uni-evc-interface", "2016-03-17"),
+                new DefaultAppModuleInfo(MseaUniEvcInterface.class, null));
+        appInfo.put(new DefaultYangModuleId("msea-soam-pm", "2016-02-29"),
+                new DefaultAppModuleInfo(MseaSoamPm.class, null));
+        appInfo.put(new DefaultYangModuleId("ieee-types", "2008-05-22"),
+                new DefaultAppModuleInfo(IeeeTypes.class, null));
+        appInfo.put(new DefaultYangModuleId("svc-activation-types", "2015-10-27"),
+                new DefaultAppModuleInfo(SvcActivationTypes.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-netconf", "2011-06-01"),
+                new DefaultAppModuleInfo(IetfNetconf.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-system-microsemi", "2016-05-05"),
+                new DefaultAppModuleInfo(IetfSystemMicrosemi.class, null));
+        appInfo.put(new DefaultYangModuleId("notifications", "2008-07-14"),
+                new DefaultAppModuleInfo(Notifications.class, null));
+        appInfo.put(new DefaultYangModuleId("y-1564", "2015-10-29"),
+                new DefaultAppModuleInfo(Y1564.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-interfaces", "2014-05-08"),
+                new DefaultAppModuleInfo(IetfInterfaces.class, null));
+        return ImmutableMap.copyOf(appInfo);
+    }
+}
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
new file mode 100644
index 0000000..cdd3700
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.netconf.DatastoreId;
+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.abortloopback.AbortLoopbackInput;
+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;
+
+/**
+ * Extension of mseaCfmService to include NETCONF sessions.
+ *
+ * This is manually extended and should be revised if the msea-cfm.yang,
+ * msea-soam-pm.yang or msea-soam-fm.yang files change
+ */
+public interface MseaCfmNetconfService {
+
+    /**
+     * Returns attributes of MEP.
+     *
+     * @param mdName The name of the MD
+     * @param maName 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;
+
+
+    /**
+     * Returns attributes of DM.
+     *
+     * @param mdName The name of the MD
+     * @param maName The name of the MA
+     * @param mepId The ID of the MEP
+     * @param dmId The Id of the Delay Measurement
+     * @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;
+
+    /**
+     * Sets the value to attribute mseaCfm.
+     *
+     * @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 setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session,
+                       DatastoreId targetDs) throws NetconfException;
+
+    /**
+     * Service interface of transmitLoopback.
+     *
+     * @param inputVar input of service interface transmitLoopback
+     * @param session An active NETCONF session
+     * @throws NetconfException if the session has any error
+     */
+    void transmitLoopback(TransmitLoopbackInput inputVar,
+                          NetconfSession session) throws NetconfException;
+
+    /**
+     * Service interface of abortLoopback.
+     *
+     * @param inputVar input of service interface abortLoopback
+     * @param session An active NETCONF session
+     * @throws NetconfException if the session has any error
+     */
+    void abortLoopback(AbortLoopbackInput inputVar,
+                       NetconfSession session) throws NetconfException;
+
+    /**
+     * Service interface of transmitLinktrace.
+     *
+     * @param inputVar input of service interface transmitLinktrace
+     * @param session An active NETCONF session
+     * @return transmitLinktraceOutput output of service interface transmitLinktrace
+     * @throws NetconfException if the session has any error
+     */
+    TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar,
+              NetconfSession session) throws NetconfException;
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java
new file mode 100644
index 0000000..f9788f3
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
+
+import java.util.List;
+
+/**
+ * Extension of mseaSaFilteringService to include NETCONF sessions.
+ *
+ * This is manually extended and should be revised if the msea-sa-filtering.yang file changes
+ */
+public interface MseaSaFilteringNetconfService {
+    /**
+     * Returns the attribute mseaSaFiltering.
+     *
+     * @param mseaSaFiltering value of mseaSaFiltering
+     * @param session  An active NETCONF session
+     * @return mseaSaFiltering
+     * @throws NetconfException if the session has any error
+     */
+    MseaSaFiltering getMseaSaFiltering(
+            MseaSaFilteringOpParam mseaSaFiltering, final NetconfSession session)
+            throws NetconfException;
+
+    /**
+     * Get a filtered subset of the config model.
+     *
+     * @param session  An active NETCONF session
+     * @return mseaSaFiltering
+     * @throws NetconfException if the session has any error
+     */
+    public List<SourceAddressRange> getConfigMseaSaFilterIds(NetconfSession session)
+            throws NetconfException;
+
+    /**
+     * Sets the value to attribute mseaSaFiltering.
+     *
+     * @param mseaSaFiltering value of mseaSaFiltering
+     * @param session An active NETCONF session
+     * @param targetDs The NETCONF datastore to edit
+     * @return Boolean to indicate success or failure
+     * @throws NetconfException if the session has any error
+     */
+    boolean setMseaSaFiltering(MseaSaFilteringOpParam mseaSaFiltering,
+            NetconfSession session, DatastoreId targetDs) throws NetconfException;
+
+    /**
+     * Deletes the value to attribute mseaSaFiltering.
+     *
+     * @param mseaSaFiltering value of mseaSaFiltering
+     * @param session An active NETCONF session
+     * @param targetDs The NETCONF datastore to edit
+     * @return Boolean to indicate success or failure
+     * @throws NetconfException if the session has any error
+     */
+    boolean deleteMseaSaFilteringRange(MseaSaFilteringOpParam mseaSaFiltering,
+              NetconfSession session, DatastoreId targetDs) throws NetconfException;
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java
new file mode 100644
index 0000000..a7f85bf
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi.yang;
+
+import java.util.List;
+import java.util.Map;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
+
+/**
+ * Extension of mseaUniEvcServiceService to include NETCONF sessions.
+ *
+ * This is manually extended and should be revised if the msea-uni-evc-service.yang
+ * file changes
+ */
+public interface MseaUniEvcServiceNetconfService {
+    /**
+     * Returns the configuration and state attributes of the running mseaUniEvcService.
+     *
+     * @param mseaUniEvcService value of mseaUniEvcService
+     * @param session The NETCONF session
+     * @return mseaUniEvcService
+     * @throws NetconfException if the session has any error
+     */
+    MseaUniEvcService getMseaUniEvcService(
+            MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session)
+            throws NetconfException;
+
+    /**
+     * Returns the configuration only attributes of mseaUniEvcService.
+     *
+     * @param mseaUniEvcService value of mseaUniEvcService
+     * @param session The NETCONF session
+     * @param targetDs one of running, candidate or startup
+     * @return mseaUniEvcService
+     * @throws NetconfException if the session has any error
+     */
+    MseaUniEvcService getConfigMseaUniEvcService(
+            MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session,
+            DatastoreId targetDs) throws NetconfException;
+
+    /**
+     * Sets the value to attribute mseaUniEvcService.
+     *
+     * @param mseaUniEvcService value of mseaUniEvcService
+     * @param session The 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 setMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+            NetconfSession session, DatastoreId targetDs)
+            throws NetconfException;
+
+    /**
+     * Deletes the objects in mseaUniEvcService.
+     *
+     * @param mseaUniEvcService value of mseaUniEvcService
+     * @param session The 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 deleteMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+             NetconfSession session, DatastoreId targetDs) throws NetconfException;
+
+    /**
+     * Returns a list of the CeVlanMaps on both sides of the EVC.
+     *
+     * @param session A NETCONF Session
+     * @param ncDs The datastore to affect - running, candidate or startup
+     * @return The Object Model with the VLans
+     * @throws NetconfException if the session has any error
+     */
+    MseaUniEvcService getmseaUniEvcCeVlanMaps(
+            NetconfSession session, DatastoreId ncDs)
+            throws NetconfException;
+
+    /**
+     * Replace ceVlans or delete EVCs from a device.
+     *
+     * It is necessary to have a custom command for this as the YCH cannot
+     * handle the intricacies of putting a replace operation on the
+     * ceVlanMap leaf at present
+     *
+     * @param ceVlanUpdates A Map of CeVlanMap entries to change, as flows are deleted
+     * @param flowVlanIds The IDs of flows that are being removed
+     * @param session A NETCONF Session
+     * @param targetDs The datastore to affect - running, candidate or startup
+     * @param portAssign The port assignment of the device
+     * @throws NetconfException if the session has any error
+     */
+    void removeEvcUniFlowEntries(
+            Map<Integer, String> ceVlanUpdates,
+            Map<Integer, List<Short>> flowVlanIds,
+            NetconfSession session,
+            DatastoreId targetDs,
+            UniSideInterfaceAssignmentEnum portAssign)
+                    throws NetconfException;
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java
new file mode 100644
index 0000000..8ced81c
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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;
+
+/**
+ * An enumeration to describe the side of a UNI - Customer or Network.
+ * For reference see MEF 6.2
+ */
+public enum UniSide {
+    CUSTOMER,
+    NETWORK
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java
new file mode 100644
index 0000000..fbf89be
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.custom;
+
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.EvcPerUniServiceTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnic;
+
+import java.util.List;
+
+/**
+ * Extend the DefaultEvcPerUnic so that the ceVlanMap can always be initialized at 0.
+ */
+public class CustomEvcPerUnic extends DefaultEvcPerUnic {
+    @Override
+    public ServiceListType ceVlanMap() {
+        if (ceVlanMap == null) {
+            return new ServiceListType("0");
+        }
+        return ceVlanMap;
+    }
+    @Override
+    public Object ingressBwpGroupIndex() {
+        return ingressBwpGroupIndex;
+    }
+
+    @Override
+    public EvcPerUniServiceTypeEnum evcPerUniServiceType() {
+        return evcPerUniServiceType;
+    }
+
+    @Override
+    public TagManipulation tagManipulation() {
+        return tagManipulation;
+    }
+
+    @Override
+    public List<FlowMapping> flowMapping() {
+        return flowMapping;
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java
new file mode 100644
index 0000000..d8712dc
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.custom;
+
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.EvcPerUniServiceTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnin;
+
+import java.util.List;
+
+/**
+ * Extend the DefaultEvcPerUnin so that the ceVlanMap can always be initialized at 0.
+ */
+public class CustomEvcPerUnin extends DefaultEvcPerUnin {
+    @Override
+    public ServiceListType ceVlanMap() {
+        if (ceVlanMap == null) {
+            return new ServiceListType("0");
+        }
+        return ceVlanMap;
+    }
+    @Override
+    public Object ingressBwpGroupIndex() {
+        return ingressBwpGroupIndex;
+    }
+
+    @Override
+    public EvcPerUniServiceTypeEnum evcPerUniServiceType() {
+        return evcPerUniServiceType;
+    }
+
+    @Override
+    public TagManipulation tagManipulation() {
+        return tagManipulation;
+    }
+
+    @Override
+    public List<FlowMapping> flowMapping() {
+        return flowMapping;
+    }
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java
new file mode 100644
index 0000000..1a7a471
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 for Microsemi device drivers support for NETCONF for EA1000.
+ */
+package org.onosproject.drivers.microsemi.yang.custom;
\ No newline at end of file
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
new file mode 100644
index 0000000..3867a2f
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.ByteSource;
+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.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaContext;
+import org.onosproject.yang.model.SchemaContextProvider;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.CompositeStream;
+import org.onosproject.yang.runtime.DefaultCompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+import org.onosproject.yang.runtime.DefaultYangSerializerContext;
+import org.onosproject.yang.runtime.YangModelRegistry;
+import org.onosproject.yang.runtime.YangSerializer;
+import org.onosproject.yang.runtime.YangSerializerContext;
+import org.onosproject.yang.runtime.YangSerializerRegistry;
+import org.onosproject.yang.serializers.xml.XmlSerializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract class that implements some of the core functions of a YANG model service.
+ *
+ */
+@Component(immediate = true)
+@Service
+public abstract class AbstractYangServiceImpl {
+    public static final String NC_OPERATION = "nc:operation";
+    public static final String OP_DELETE = "delete";
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+    protected boolean alreadyLoaded = false;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected YangModelRegistry yangModelRegistry;
+
+//    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+//    protected SchemaContextProvider schemaContextProvider;
+
+    protected ApplicationId appId;
+
+    // xSer is not a service and is a class variable. Can be lost on deactivate.
+    // Must be recreated on activate
+    protected XmlSerializer xSer;
+    protected YangSerializerContext yCtx;
+
+    protected static final Pattern REGEX_XML_HEADER =
+            Pattern.compile("(<\\?xml).*(\\?>)", Pattern.DOTALL);
+    protected static final Pattern REGEX_RPC_REPLY =
+            Pattern.compile("(<rpc-reply)[ ]*" +
+                    "(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\")[ ]*" +
+                    "(message-id=\")[0-9]*(\">)", Pattern.DOTALL);
+    protected static final Pattern REGEX_RPC_REPLY_DATA_NS =
+            Pattern.compile("(<data)[ ]*(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)");
+    protected static final Pattern REGEX_RPC_REPLY_DATA =
+            Pattern.compile("(<data>)");
+    protected static final Pattern REGEX_RPC_REPLY_DATA_CLOSE =
+            Pattern.compile("(</data>)");
+    protected static final Pattern REGEX_RPC_REPLY_DATA_EMPTY =
+            Pattern.compile("(<data/>)");
+    protected static final Pattern REGEX_RPC_REPLY_CLOSE =
+            Pattern.compile("(</rpc-reply>)");
+
+    @Activate
+    public void activate() {
+        Set<YangSerializer> yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers();
+        yangSer.forEach(ser -> {
+            if (ser instanceof XmlSerializer) {
+                xSer = (XmlSerializer) ser;
+            }
+        });
+        SchemaContext context = ((SchemaContextProvider) yangModelRegistry)
+                .getSchemaContext(ResourceId.builder().addBranchPointSchema("/", null).build());
+
+        yCtx = new DefaultYangSerializerContext(context, null);
+    };
+
+    @Deactivate
+    public void deactivate() {
+        alreadyLoaded = false;
+    }
+
+    /**
+     * Internal method to generically make a NETCONF get query from YANG objects.
+     * @param moFilter A YANG object model
+     * @param session A NETCONF session
+     * @return YangObjectModel
+     * @throws NetconfException if the session has any error
+     */
+    protected final ModelObjectData getNetconfObject(
+            ModelObjectData moFilter, NetconfSession session)
+                throws NetconfException {
+
+        return getConfigNetconfObject(moFilter, session, null);
+    }
+
+    /**
+     * Internal method to generically make a NETCONF get-config query from YANG objects.
+     *
+     * @param moFilter A YANG object model
+     * @param session A NETCONF session
+     * @param targetDs - running,candidate or startup
+     * @return YangObjectModel
+     * @throws NetconfException if the session has any error
+     */
+    protected final ModelObjectData getConfigNetconfObject(
+            ModelObjectData moFilter, NetconfSession session, DatastoreId targetDs)
+                throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getConfigNetconfObject()");
+        }
+
+        if (moFilter == null) {
+            throw new NetconfException("Query object cannot be null");
+        }
+
+        String xmlQueryStr = encodeMoToXmlStr(moFilter, null);
+
+        log.debug("Sending <get-(config)> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+        String xmlResult;
+        if (targetDs == null) {
+            xmlResult = session.get(xmlQueryStr, null);
+        } else {
+            xmlResult = session.getConfig(targetDs, xmlQueryStr);
+        }
+        xmlResult = removeRpcReplyData(xmlResult);
+
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+    }
+
+    /**
+     * Internal method to generically make a NETCONF edit-config call from a set of YANG objects.
+     *
+     * @param moConfig A YANG object model
+     * @param session A NETCONF session
+     * @param targetDs - running,candidate or startup
+     * @param annotations A list of AnnotatedNodeInfos to be added to the DataNodes
+     * @return Boolean value indicating success or failure of command
+     * @throws NetconfException if the session has any error
+     */
+    protected final boolean setNetconfObject(
+            ModelObjectData moConfig, NetconfSession session, DatastoreId targetDs,
+            List<AnnotatedNodeInfo> annotations) throws NetconfException {
+        if (moConfig == null) {
+            throw new NetconfException("Query object cannot be null");
+        } else if (session == null) {
+            throw new NetconfException("Session is null when calling getMseaSaFiltering()");
+        } else if (targetDs == null) {
+            throw new NetconfException("TargetDs is null when calling getMseaSaFiltering()");
+        }
+
+        String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations);
+        log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        return session.editConfig(targetDs, null, xmlQueryStr);
+    }
+
+    protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter,
+                                            List<AnnotatedNodeInfo> annotations)
+            throws NetconfException {
+        //Convert the param to XML to use as a filter
+        ResourceData rd = ((ModelConverter) yangModelRegistry).createDataNode(yangObjectOpParamFilter);
+
+        DefaultCompositeData.Builder cdBuilder =
+                        DefaultCompositeData.builder().resourceData(rd);
+        if (annotations != null) {
+            for (AnnotatedNodeInfo ani : annotations) {
+                cdBuilder.addAnnotatedNodeInfo(ani);
+            }
+        }
+        CompositeStream cs = xSer.encode(cdBuilder.build(), yCtx);
+        //Convert the param to XML to use as a filter
+
+        try {
+            ByteSource byteSource = new ByteSource() {
+                @Override
+                public InputStream openStream() throws IOException {
+                    return cs.resourceData();
+                }
+            };
+
+            return byteSource.asCharSource(Charsets.UTF_8).read();
+        } catch (IOException e) {
+            throw new NetconfException("Error decoding CompositeStream to String", e);
+        }
+    }
+
+    protected static final String removeRpcReplyData(String rpcReplyXml) {
+        rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA_NS.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA_CLOSE.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA_EMPTY.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_CLOSE.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = rpcReplyXml.replace("\t", "");
+        return rpcReplyXml;
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java
new file mode 100644
index 0000000..3673594
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.impl;
+
+import java.io.ByteArrayInputStream;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+
+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.IetfSystemNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystemState;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.systemrestart.SystemRestartInput;
+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.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+/**
+ * Implementation of the IetfService YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class IetfSystemManager extends AbstractYangServiceImpl
+    implements IetfSystemNetconfService {
+
+    protected static final String IETF_SYSTEM = "org.onosproject.drivers.microsemi.yang.ietfsystem";
+
+    @Activate
+    public void activate() {
+        super.activate();
+        appId = coreService.registerApplication(IETF_SYSTEM);
+        log.info("IetfSystemManager Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        super.deactivate();
+        log.info("IetfSystemManager Stopped");
+    }
+
+    /**
+     * Get a filtered subset of the model.
+     * This is meant to filter the current live model
+     * against the attribute(s) given in the argument
+     * and return the filtered model.
+     * @throws NetconfException if the session has any error
+     */
+    @Override
+    public IetfSystem getIetfSystem(IetfSystemOpParam ietfSystemFilter, NetconfSession session)
+            throws NetconfException {
+
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) ietfSystemFilter.system())
+                .build();
+
+        ModelObjectData moReply = getNetconfObject(moQuery, session);
+
+        IetfSystemOpParam ietfSystem = new IetfSystemOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof DefaultSystem) {
+                ietfSystem.system((DefaultSystem) mo);
+            } else if (mo instanceof DefaultSystemState) {
+                ietfSystem.systemState((DefaultSystemState) mo);
+            }
+        }
+
+        return ietfSystem;
+    }
+
+    @Override
+    public IetfSystem getIetfSystemInit(NetconfSession session) throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getIetfSystemInit()");
+        }
+
+        String xmlResult = session.get(getInitRequestBuilder(), null);
+
+        xmlResult = removeRpcReplyData(xmlResult);
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        IetfSystemOpParam ietfSystem = new IetfSystemOpParam();
+        for (ModelObject mo:mod.modelObjects()) {
+            if (mo instanceof DefaultSystem) {
+                ietfSystem.system((DefaultSystem) mo);
+            } else if (mo instanceof DefaultSystemState) {
+                ietfSystem.systemState((DefaultSystemState) mo);
+            }
+        }
+
+        return ietfSystem;
+    }
+
+    /**
+     * Call NETCONF edit-config with a configuration.
+     */
+    @Override
+    public boolean setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session,
+                              DatastoreId ncDs) throws NetconfException {
+        ModelObjectData mo = DefaultModelObjectData.builder()
+                                .addModelObject(ietfSystem).build();
+        return setNetconfObject(mo, session, ncDs, null);
+    }
+
+    @Override
+    public void setCurrentDatetime(OffsetDateTime date, NetconfSession session)
+            throws NetconfException {
+        String xmlQueryStr = getSetCurrentDatetimeBuilder(date);
+        log.info("Sending <get> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.doWrappedRpc(xmlQueryStr);
+        log.info("Result from NETCONF RPC <set-current-datetime>: {}", xmlResult);
+    }
+
+    @Override
+    public void systemRestart(SystemRestartInput inputVar, NetconfSession session) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void systemShutdown(NetconfSession session) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public DoUpgradeAndRebootOutput doUpgradeAndReboot(DoUpgradeAndRebootInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void pullUpdateTarFromTftp(PullUpdateTarFromTftpInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public ReadFromSyslogOutput readFromSyslog(ReadFromSyslogInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+
+    /**
+     * Builds a request crafted to get the configuration required to create
+     * details descriptions for the device.
+     *
+     * @return The request string.
+     */
+    private static String getInitRequestBuilder() {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<system-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\" ");
+        rpc.append("xmlns:sysms=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">");
+        rpc.append("<platform>");
+        rpc.append("<os-release/>");
+        rpc.append("<sysms:device-identification>");
+        rpc.append("<sysms:serial-number/>");
+        rpc.append("</sysms:device-identification>");
+        rpc.append("</platform>");
+        rpc.append("<clock>");
+        rpc.append("<current-datetime/>");
+        rpc.append("</clock>");
+        rpc.append("</system-state>");
+        rpc.append("<system xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\" ");
+        rpc.append("xmlns:sysms=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">");
+        rpc.append("<sysms:longitude/>");
+        rpc.append("<sysms:latitude/>");
+        rpc.append("</system>");
+        return rpc.toString();
+    }
+
+    private static String getSetCurrentDatetimeBuilder(OffsetDateTime date) {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<set-current-datetime xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\">");
+        rpc.append("<current-datetime>");
+        rpc.append(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxxx")));
+        rpc.append("</current-datetime>");
+        rpc.append("</set-current-datetime>");
+
+        return rpc.toString();
+    }
+}
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
new file mode 100644
index 0000000..36f48c4
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.impl;
+
+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.netconf.DatastoreId;
+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.abortloopback.AbortLoopbackInput;
+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.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+import java.io.ByteArrayInputStream;
+
+/**
+ * Implementation of the MseaCfmServiceNetconf YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaCfmManager extends AbstractYangServiceImpl
+    implements MseaCfmNetconfService {
+
+    public static final String MSEA_CFM = "org.onosproject.drivers.microsemi.yang.mseacfmservice";
+
+    @Activate
+    public void activate() {
+        super.activate();
+        appId = coreService.registerApplication(MSEA_CFM);
+        log.info("MseaCfmService Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        super.deactivate();
+        log.info("MseaCfmService Stopped");
+    }
+
+    @Override
+    public MseaCfm getMepEssentials(String mdName, String maName, int 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 " +
+                " query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.get(xmlQueryStr, null);
+
+        xmlResult = removeRpcReplyData(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 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");
+    }
+
+    @Override
+    public boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session,
+              DatastoreId targetDs) throws NetconfException {
+        ModelObjectData moEdit = DefaultModelObjectData.builder()
+                .addModelObject(mseaCfm).build();
+
+        return setNetconfObject(moEdit, session, targetDs, null);
+    }
+
+    /**
+     * Call RPCs on the device through NETCONF.
+     */
+    @Override
+    public void transmitLoopback(TransmitLoopbackInput inputVar, NetconfSession session) throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void abortLoopback(AbortLoopbackInput inputVar, NetconfSession session) throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    private String buildMepQueryString(String mdName, String maName, int mepId) {
+        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>" + mdName + "</name>\n");
+        rpc.append("<md-level/>\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("<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("<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("</maintenance-association-end-point>\n");
+        rpc.append("</maintenance-association>\n");
+        rpc.append("</maintenance-domain>\n");
+        rpc.append("</mef-cfm>");
+
+        return rpc.toString();
+    }
+
+
+    private String buildDmQueryString(String mdName, String maName, int mepId, int dmId) {
+        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>" + mdName + "</name>\n");
+        rpc.append("<md-level/>\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("<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("</maintenance-association-end-point>\n");
+        rpc.append("</maintenance-association>\n");
+        rpc.append("</maintenance-domain>\n");
+        rpc.append("</mef-cfm>");
+
+        return rpc.toString();
+    }
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
new file mode 100644
index 0000000..01af138
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.impl;
+
+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.MseaSaFilteringNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
+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;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of the MseaSaFiltering YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaSaFilteringManager extends AbstractYangServiceImpl
+    implements MseaSaFilteringNetconfService {
+    public static final String MSEA_SA_FILTERING =
+            "org.onosproject.drivers.microsemi.yang.mseasafiltering";
+    public static final String MSEA_SA_FILTERING_NS =
+            "http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering";
+
+    @Activate
+    public void activate() {
+        super.activate();
+        appId = coreService.registerApplication(MSEA_SA_FILTERING);
+        log.info("MseaSaFilteringManager Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        super.deactivate();
+        log.info("MseaSaFilteringManager Stopped");
+    }
+
+    /**
+     * Get a filtered subset of the model.
+     * This is meant to filter the current live model
+     * against the attribute(s) given in the argument
+     * and return the filtered model.
+     */
+    @Override
+    public MseaSaFiltering getMseaSaFiltering(
+            MseaSaFilteringOpParam mseaSaFilteringFilter, NetconfSession session)
+            throws NetconfException {
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaSaFilteringFilter
+                        .sourceIpaddressFiltering())
+                .build();
+
+
+        ModelObjectData moReply = getNetconfObject(moQuery, session);
+
+        MseaSaFiltering reply = new MseaSaFilteringOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof SourceIpaddressFiltering) {
+                reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo);
+            }
+        }
+        return reply;
+    }
+
+    /**
+     * Get a filtered subset of the config model (from running)
+     * This is meant to filter the current live model
+     * against the attribute(s) given in the argument
+     * and return the filtered model.
+     */
+    @Override
+    public List<SourceAddressRange> getConfigMseaSaFilterIds(NetconfSession session)
+            throws NetconfException {
+
+        String xmlResult = session.getConfig(DatastoreId.RUNNING, saFilterQuery());
+        xmlResult = removeRpcReplyData(xmlResult);
+
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData moReply = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        MseaSaFiltering reply = new MseaSaFilteringOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof SourceIpaddressFiltering) {
+                reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo);
+            }
+        }
+        if (reply != null && reply.sourceIpaddressFiltering() != null &&
+                reply.sourceIpaddressFiltering().interfaceEth0() != null) {
+            return reply.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
+        } else {
+            return new ArrayList<SourceAddressRange>();
+        }
+    }
+
+    /**
+     * Call NETCONF edit-config with a configuration.
+     */
+    @Override
+    public boolean setMseaSaFiltering(MseaSaFilteringOpParam mseaSaFiltering,
+           NetconfSession session, DatastoreId ncDs) throws NetconfException {
+
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaSaFiltering
+                        .sourceIpaddressFiltering()).build();
+
+        return setNetconfObject(moQuery, session, ncDs, null);
+    }
+
+    @Override
+    public boolean deleteMseaSaFilteringRange(MseaSaFilteringOpParam mseaSaFiltering,
+                                      NetconfSession session, DatastoreId ncDs) throws NetconfException {
+
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaSaFiltering
+                        .sourceIpaddressFiltering()).build();
+
+        ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
+        if (mseaSaFiltering.sourceIpaddressFiltering().interfaceEth0() != null &&
+                mseaSaFiltering.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange() != null) {
+
+            for (SourceAddressRange sar:mseaSaFiltering.sourceIpaddressFiltering()
+                    .interfaceEth0().sourceAddressRange()) {
+                String sarRangeIdStr = String.valueOf(sar.rangeId());
+
+                ResourceId.Builder ridBuilder = ResourceId.builder()
+                        .addBranchPointSchema("/", null)
+                        .addBranchPointSchema("source-ipaddress-filtering", MSEA_SA_FILTERING_NS)
+                        .addBranchPointSchema("interface-eth0", MSEA_SA_FILTERING_NS)
+                        .addBranchPointSchema("source-address-range", MSEA_SA_FILTERING_NS)
+                        .addKeyLeaf("range-id", MSEA_SA_FILTERING_NS, sarRangeIdStr);
+
+                AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                        .resourceId(ridBuilder.build())
+                        .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                        .build();
+
+                anis.add(ani);
+            }
+        } else {
+            //Delete all
+            ResourceId.Builder ridBuilder = ResourceId.builder()
+                    .addBranchPointSchema("/", null)
+                    .addBranchPointSchema("source-ipaddress-filtering", MSEA_SA_FILTERING_NS);
+            AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                    .resourceId(ridBuilder.build())
+                    .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                    .build();
+            anis.add(ani);
+        }
+
+        return setNetconfObject(moQuery, session, ncDs, anis);
+    }
+
+
+    private static String saFilterQuery() {
+        StringBuilder sb = new StringBuilder("<source-ipaddress-filtering " +
+                "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering\">");
+        sb.append("<interface-eth0>");
+        sb.append("<filter-admin-state>blacklist</filter-admin-state>");
+        sb.append("<source-address-range>");
+        sb.append("<range-id/>");
+        sb.append("</source-address-range>");
+        sb.append("</interface-eth0>");
+        sb.append("</source-ipaddress-filtering>");
+        return sb.toString();
+    }
+}
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
new file mode 100644
index 0000000..f965541
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.impl;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+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.MseaUniEvcServiceNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
+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;
+
+/**
+ * Implementation of the MseaUniEvcServiceService YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaUniEvcServiceManager extends AbstractYangServiceImpl
+        implements MseaUniEvcServiceNetconfService {
+    public static final String MSEA_UNI_EVC_SVC =
+            "org.onosproject.drivers.microsemi.yang.mseaunievcservice";
+    public static final String MSEA_UNI_EVC_SVC_NS =
+            "http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service";
+
+    @Activate
+    public void activate() {
+        super.activate();
+        appId = coreService.registerApplication(MSEA_UNI_EVC_SVC);
+        log.info("MseaUniEvcServiceManager Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        super.deactivate();
+        log.info("MseaUniEvcServiceManager Stopped");
+    }
+
+    @Override
+    public MseaUniEvcService getMseaUniEvcService(
+            MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session)
+            throws NetconfException {
+
+        return getConfigMseaUniEvcService(mseaUniEvcService, session, null);
+    }
+
+    @Override
+    public MseaUniEvcService getConfigMseaUniEvcService(
+            MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session,
+            DatastoreId targetDs) throws NetconfException {
+
+        ModelObjectData moFilter = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+        ModelObjectData moReply = getConfigNetconfObject(moFilter, session, targetDs);
+
+        MseaUniEvcService reply = new MseaUniEvcServiceOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof MefServices) {
+                reply.mefServices((MefServices) mo);
+            }
+        }
+        return reply;
+    }
+
+    /**
+     * Modify the configuration.
+     */
+    @Override
+    public boolean setMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+                 NetconfSession session, DatastoreId ncDs) throws NetconfException {
+        ModelObjectData moEdit = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+        return setNetconfObject(moEdit, session, ncDs, null);
+    }
+
+    /**
+     * Delete the configuration.
+     */
+    @Override
+    public boolean deleteMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+                NetconfSession session, DatastoreId ncDs) throws NetconfException {
+        ModelObjectData moEdit = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+        ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
+        for (BwpGroup bwpGrp:mseaUniEvcService.mefServices().profiles().bwpGroup()) {
+            String bwpGroupIndex = String.valueOf(bwpGrp.groupIndex());
+
+            ResourceId.Builder ridBuilder = ResourceId.builder()
+                    .addBranchPointSchema("/", null)
+                    .addBranchPointSchema("mef-services", MSEA_UNI_EVC_SVC_NS)
+                    .addBranchPointSchema("profiles", MSEA_UNI_EVC_SVC_NS)
+                    .addBranchPointSchema("bwp-group", MSEA_UNI_EVC_SVC_NS)
+                    .addKeyLeaf("group-index", MSEA_UNI_EVC_SVC_NS, bwpGroupIndex);
+
+            AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                    .resourceId(ridBuilder.build())
+                    .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                    .build();
+
+            anis.add(ani);
+        }
+
+
+        return setNetconfObject(moEdit, session, ncDs, anis);
+    }
+
+
+    @Override
+    public MseaUniEvcService getmseaUniEvcCeVlanMaps(
+            NetconfSession session, DatastoreId ncDs)
+            throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getMseaSaFiltering()");
+        }
+
+        String xmlResult = session.getConfig(ncDs, evcFilterQuery());
+        xmlResult = removeRpcReplyData(xmlResult);
+
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData moReply = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        MseaUniEvcService reply = new MseaUniEvcServiceOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof MefServices) {
+                reply.mefServices((MefServices) mo);
+            }
+        }
+        return reply;
+    }
+
+    @Override
+    public void removeEvcUniFlowEntries(
+            Map<Integer, String> ceVlanUpdates,
+            Map<Integer, List<Short>> flowVlanIds,
+            NetconfSession session, DatastoreId targetDs,
+            UniSideInterfaceAssignmentEnum portAssign) throws NetconfException {
+
+        List<Integer> evcAlreadyHandled = new ArrayList<>();
+        StringBuilder xmlEvcUpdate = new StringBuilder(evcUniOpener());
+        for (Integer evcKey:ceVlanUpdates.keySet()) {
+            int evcId = (evcKey & ((1 << 8) - 100)) >> 2;
+            if (evcAlreadyHandled.contains(new Integer(evcId))) {
+                continue;
+            }
+            evcAlreadyHandled.add(evcId);
+            int port = (evcKey & 3);
+            String ceVlanMapThis = ceVlanUpdates.get(evcKey);
+            String ceVlanMapOpposite = ceVlanUpdates.get(evcKey ^ 1);
+
+            if ((ceVlanMapThis == null || ceVlanMapThis.isEmpty()) &&
+                    (ceVlanMapOpposite == null || ceVlanMapOpposite.isEmpty())) {
+                xmlEvcUpdate.append("<evc nc:operation=\"delete\">\n<evc-index>");
+                xmlEvcUpdate.append(Integer.toString(evcId));
+                xmlEvcUpdate.append("</evc-index>\n</evc>\n");
+            } else {
+                xmlEvcUpdate.append("<evc>\n<evc-index>");
+                xmlEvcUpdate.append(Integer.toString(evcId));
+                xmlEvcUpdate.append("</evc-index>\n<evc-per-uni>\n");
+                if (port == 0 && portAssign == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS ||
+                        port == 1 && portAssign == UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST) {
+                    if (ceVlanMapThis != null) {
+                        xmlEvcUpdate.append("<evc-per-uni-c>\n<ce-vlan-map nc:operation=\"replace\">");
+                        xmlEvcUpdate.append(ceVlanMapThis);
+                        xmlEvcUpdate.append("</ce-vlan-map>\n");
+                        xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey)));
+                        xmlEvcUpdate.append("</evc-per-uni-c>\n");
+                    }
+                    if (ceVlanMapOpposite != null) {
+                        xmlEvcUpdate.append("<evc-per-uni-n>\n<ce-vlan-map nc:operation=\"replace\">");
+                        xmlEvcUpdate.append(ceVlanMapOpposite);
+                        xmlEvcUpdate.append("</ce-vlan-map>\n");
+                        xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey ^ 1)));
+                        xmlEvcUpdate.append("</evc-per-uni-n>\n");
+                    }
+                } else {
+                    if (ceVlanMapThis != null) {
+                        xmlEvcUpdate.append("<evc-per-uni-n>\n<ce-vlan-map nc:operation=\"replace\">");
+                        xmlEvcUpdate.append(ceVlanMapThis);
+                        xmlEvcUpdate.append("</ce-vlan-map>\n");
+                        xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey)));
+                        xmlEvcUpdate.append("</evc-per-uni-n>\n");
+                    }
+                    if (ceVlanMapOpposite != null) {
+                        xmlEvcUpdate.append("<evc-per-uni-c>\n<ce-vlan-map nc:operation=\"replace\">");
+                        xmlEvcUpdate.append(ceVlanMapOpposite);
+                        xmlEvcUpdate.append("</ce-vlan-map>\n");
+                        xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey ^ 1)));
+                        xmlEvcUpdate.append("</evc-per-uni-c>\n");
+                    }
+                }
+
+                xmlEvcUpdate.append("</evc-per-uni>\n</evc>\n");
+            }
+        }
+        xmlEvcUpdate.append("</uni>\n</mef-services>");
+
+        log.info("Sending XML <edit-config> on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlEvcUpdate.toString());
+
+
+        session.editConfig(targetDs, null, xmlEvcUpdate.toString());
+    }
+
+
+    private static String deleteFlowMapping(List<Short> vlanIds) {
+        if (vlanIds == null || vlanIds.size() == 0) {
+            return "";
+        }
+        StringBuilder fmXmlBuilder = new StringBuilder();
+        for (long vlanId:vlanIds) {
+            fmXmlBuilder.append("<flow-mapping nc:operation=\"delete\">\n");
+            fmXmlBuilder.append("<ce-vlan-id>");
+            fmXmlBuilder.append(String.valueOf(vlanId));
+            fmXmlBuilder.append("</ce-vlan-id>\n");
+            fmXmlBuilder.append("</flow-mapping>\n");
+        }
+
+        return fmXmlBuilder.toString();
+    }
+
+    private String evcFilterQuery() {
+        StringBuilder sb = new StringBuilder("<mef-services "
+                + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">");
+        sb.append("<uni>");
+        sb.append("<evc>");
+        sb.append("<evc-index/>");
+        sb.append("<evc-per-uni>");
+        sb.append("<evc-per-uni-c>");
+        sb.append("<ce-vlan-map/>");
+        sb.append("<flow-mapping/>");
+        sb.append("<ingress-bwp-group-index/>");
+        sb.append("</evc-per-uni-c>");
+        sb.append("<evc-per-uni-n>");
+        sb.append("<ce-vlan-map/>");
+        sb.append("<flow-mapping/>");
+        sb.append("<ingress-bwp-group-index/>");
+        sb.append("</evc-per-uni-n>");
+        sb.append("</evc-per-uni>");
+        sb.append("</evc>");
+        sb.append("</uni>");
+        sb.append("</mef-services>");
+
+        return sb.toString();
+    }
+
+    private String evcUniOpener() {
+        StringBuilder sb = new StringBuilder("<mef-services ");
+        sb.append("xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">\n");
+        sb.append("<uni>\n");
+
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java
new file mode 100644
index 0000000..ccf0dd2
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 for Microsemi device drivers support for NETCONF for EA1000.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java
new file mode 100644
index 0000000..d886c69
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 for Microsemi device drivers support for NETCONF for EA1000.
+ */
+package org.onosproject.drivers.microsemi.yang;
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
new file mode 100644
index 0000000..52ede6d
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.lang.ArrayUtils;
+
+/**
+ * A set of static utilities that allow a ce-vlan-map to be decomposed.
+ *
+ * This is an implementation specific to Microsemi that encodes ce-vlan-map
+ * in a similar way to Section 7.9 in the MEF 10.2 specification. That specification
+ * suggests comma delimited lists of VIDs - this implementation adds on colons to
+ * specify a contiguous range of IDs
+ */
+public final class CeVlanMapUtils {
+
+    private CeVlanMapUtils() {
+        //Do not allow this utility class to be instantiated
+    }
+
+    /**
+     * Calculate the ceVlanMap in to a Set of values.
+     *
+     * From Yang description
+     *   "This object indicates the CE-VLANs associated with the specific
+     *   EVC on a UNI. CE-VLAN IDs have value of 0 to 4095. The CE-VLAN ID
+     *   list can be a single value or multiple values separated by a delimiter.
+     *   Some valid values are: '100', '1:10', '10,20,30', '1:4095'. In the
+     *   first example only CE-VLAN ID 100 is associated with the VLAN map.
+     *   In the second example the CE-VLAN map includes CE-VLAN IDs 1 through
+     *   10 (range of values). The third example indicates three separate values
+     *   that make up the CE-VLAN map. The last example indicates all CE-VLAN IDs
+     *   are included in the map (range of values). ";
+     *  reference
+     *   "[MEF 6.1] 6.1; [MEF 7.2] 6.2.1.3";
+     * @param ceVlanMap A list of vlan id's in the format described above
+     * @return A set of vlan ids
+     */
+    public static Short[] getVlanSet(String ceVlanMap) {
+        if (ceVlanMap == null || ceVlanMap.isEmpty()) {
+            return new Short[0];
+        }
+        Set<Short> ceVlanSet = new TreeSet<Short>();
+
+        String[] ceVlanMapCommas = ceVlanMap.split(",");
+        for (String ceVlanMapComma:ceVlanMapCommas) {
+            String[] ceVlanMapColon = ceVlanMapComma.split(":");
+            if (ceVlanMapColon.length == 1) {
+                ceVlanSet.add(Short.decode(ceVlanMapColon[0]));
+            } else {
+                short start = Short.decode(ceVlanMapColon[0]);
+                short end = Short.decode(ceVlanMapColon[1]);
+                if ((start < 0 || end > 4095)) {
+                    return null;
+                } else {
+                    for (short i = start; i <= end; i++) {
+                        ceVlanSet.add(i);
+                    }
+                }
+            }
+        }
+
+        return ceVlanSet.toArray(new Short[ceVlanSet.size()]);
+    }
+
+    /**
+     * Convert an array of vlan ids in to a string representation.
+     * @param vlanArray An array of vlan ids
+     * @return A string representation delimited by commas and colons
+     */
+    public static String vlanListAsString(Short[] vlanArray) {
+        boolean colonPending = false;
+        StringBuilder ceVlanMapBuilder = new StringBuilder();
+        if (vlanArray.length == 0) {
+            return "";
+        } else if (vlanArray.length == 1 && vlanArray[0] == 0) {
+            return "0";
+        }
+
+        //To ensure that there are no repeated or out-of-order elements we must convert to TreeSet
+        TreeSet<Short> vlanSet = new TreeSet<>(Arrays.asList(vlanArray));
+
+        if (vlanSet.first() == 0) {
+            vlanSet.remove(vlanSet.first());
+        }
+        short prev = vlanSet.first();
+        for (short s:vlanSet) {
+            if (s == prev) {
+                ceVlanMapBuilder.append(Short.valueOf(s));
+                continue;
+            } else if (prev == (s - 1)) {
+                colonPending = true;
+            } else {
+                if (colonPending) {
+                    ceVlanMapBuilder.append(":" + Short.valueOf(prev));
+                    colonPending = false;
+                }
+                ceVlanMapBuilder.append("," + Short.valueOf(s));
+            }
+            prev = s;
+        }
+        if (colonPending) {
+            ceVlanMapBuilder.append(":" + Short.valueOf(prev));
+        }
+
+        return ceVlanMapBuilder.toString();
+    }
+
+    /**
+     * Add an additional vlan id to an existing string representation.
+     * @param existingMap An array of vlan ids
+     * @param newVlan The new vlan ID to add
+     * @return A string representation delimited by commas and colons
+     */
+    public static String addtoCeVlanMap(String existingMap, Short newVlan) {
+        Short[] vlanArray = getVlanSet(existingMap);
+        TreeSet<Short> vlanSet = new TreeSet<>();
+        for (Short vlan:vlanArray) {
+            vlanSet.add(vlan);
+        }
+
+        vlanSet.add(newVlan);
+
+        return vlanListAsString(vlanSet.toArray(new Short[vlanSet.size()]));
+    }
+
+    /**
+     * If a string representation contains a '0' then remove it.
+     *
+     * Zero is an invalid VLAN id, and is used here as a place holder for null. Null can't
+     * be used in the EA1000 device. Once any other vlan ids are added then the zero should
+     * be removed. It is safe to call this method even if no zero is present - the method will
+     * make no change in that case.
+     *
+     * @param existingMap An string representation of vlan ids, possibly containing a zero
+     * @return A string representation delimited by commas and colons without zero
+     */
+    public static String removeZeroIfPossible(String existingMap) {
+        if (existingMap == null || existingMap.isEmpty()) {
+            return "0";
+        } else if (existingMap == "0") {
+            return existingMap;
+        }
+        return removeFromCeVlanMap(existingMap, (short) 0);
+    }
+
+    /**
+     * Remove a vlan id from an existing string representation.
+     * @param existingMap An array of vlan ids
+     * @param vlanRemove The vlan ID to remove
+     * @return A string representation delimited by commas and colons
+     */
+    public static String removeFromCeVlanMap(String existingMap, Short vlanRemove) {
+        Short[] vlanArray = getVlanSet(existingMap);
+        TreeSet<Short> vlanSet = new TreeSet<>();
+        for (Short vlan:vlanArray) {
+            if (vlan.shortValue() != vlanRemove.shortValue()) {
+                vlanSet.add(vlan);
+            }
+        }
+
+        return vlanListAsString(vlanSet.toArray(new Short[vlanSet.size()]));
+    }
+
+    /**
+     * Combine vlan ids from two existing string representations.
+     *
+     * If there are overlapping elements and ranges, these are consolidated in to one.
+     *
+     * @param set1 A string containing a set of vlan ids
+     * @param set2 A string containing a set of vlan ids
+     * @return A string representation delimited by commas and colons
+     */
+    public static String combineVlanSets(String set1, String set2) {
+        Short[] set1Array = getVlanSet(set1);
+        Short[] set2Array = getVlanSet(set2);
+        return vlanListAsString((Short[]) ArrayUtils.addAll(set1Array, set2Array));
+    }
+}
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
new file mode 100644
index 0000000..275dc25
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.DateAndTime;
+
+/**
+ * A utility class to change various YANG types to general purpose classes.
+ */
+public final class IetfYangTypesUtils {
+    private IetfYangTypesUtils() {
+        //Hiding the public constructor for this utility class
+    }
+
+    /**
+     * Convert from Date and Time in a ietf-yang-types format to the Java Time API.
+     * @param dateAndTime A date and time from a YANG object
+     * @return A Date and Time with a Time Zone offset
+     */
+    public static OffsetDateTime fromYangDateTime(DateAndTime dateAndTime) {
+        return OffsetDateTime.parse(dateAndTime.toString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+    }
+
+    /**
+     * Convert a from Date and Time in a ietf-yang-types format to the Java Time API and rezone to a given Time Zone.
+     * @param dateAndTime A date and time from a YANG object
+     * @param zoneId The time zone to rezone the time and date to
+     * @return The rezoned time and date
+     */
+    public static ZonedDateTime fromYangDateTimeZoned(DateAndTime dateAndTime, ZoneId zoneId) {
+        return OffsetDateTime.parse(dateAndTime.toString(),
+                DateTimeFormatter.ISO_OFFSET_DATE_TIME).atZoneSameInstant(zoneId);
+    }
+
+    /**
+     * Convert a from Date and Time in a ietf-yang-types format to the Java Time API rezoned to the local Time Zone.
+     * @param dateAndTime A date and time from a YANG object
+     * @return The date and time in the zone of this local machine
+     */
+    public static LocalDateTime fromYangDateTimeToLocal(DateAndTime dateAndTime) {
+        OffsetDateTime odt = OffsetDateTime.parse(dateAndTime.toString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+
+        return LocalDateTime.ofInstant(odt.toInstant(), ZoneId.systemDefault());
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java
new file mode 100644
index 0000000..0c03c46
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 for general utilities and helpers.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/resources/microsemi-drivers.xml b/drivers/microsemi/src/main/resources/microsemi-drivers.xml
new file mode 100644
index 0000000..988ac9a
--- /dev/null
+++ b/drivers/microsemi/src/main/resources/microsemi-drivers.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2017-present Open Networking Laboratory
+  ~
+  ~ 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.
+  -->
+<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>
+</drivers>
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java
new file mode 100644
index 0000000..24aad06
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.EthType.EtherType;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowEntry.FlowEntryState;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class EA1000FlowRuleProgrammableTest {
+    EA1000FlowRuleProgrammable frProgramable;
+
+    @Before
+    public void setUp() throws Exception {
+        frProgramable = new EA1000FlowRuleProgrammable();
+        frProgramable.setHandler(new MockEa1000DriverHandler());
+        assertNotNull(frProgramable.handler().data().deviceId());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testGetFlowEntries() {
+        //From MockNetconfSession sample of MseaSaFiltering
+        Collection<FlowEntry> flowEntries = frProgramable.getFlowEntries();
+
+        assertNotNull(flowEntries);
+        //There will be 12 flow entries
+        // 2 for IP Src Address filtering
+        // 2 for EVC 7 - one each port
+        // 8 for EVC 8 - one for host port, 7 on optics port because of ceVlanMap 12:14,20:22,25
+        assertEquals(12, flowEntries.size());
+
+        //Test the first Flow Entry
+        Iterator<FlowEntry> feIter = flowEntries.iterator();
+        while (feIter.hasNext()) {
+            FlowEntry fe = feIter.next();
+            assertTrue(fe.isPermanent());
+            assertEquals(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT, fe.priority());
+
+            Set<Criterion> criteria = fe.selector().criteria();
+            IPCriterion ipCr = null;
+            PortNumber port = null;
+            for (Criterion cr:criteria.toArray(new Criterion[criteria.size()])) {
+                if (cr.type() == Criterion.Type.IPV4_SRC) {
+                    ipCr = (IPCriterion) cr;
+                } else if (cr.type() == Criterion.Type.IN_PORT) {
+                    port = ((PortCriterion) cr).port();
+                } else if (cr.type() == Criterion.Type.VLAN_VID) {
+                    VlanId vid = ((VlanIdCriterion) cr).vlanId();
+                } else {
+                    fail("Unexpected Criterion type: " + cr.type().toString());
+                }
+            }
+            if (ipCr != null && (port == null || port.toLong() != 0L)) {
+                fail("Port number not equal 0 when IP Src Address filter is present");
+            }
+
+            List<Instruction> instructions = fe.treatment().allInstructions();
+
+            if (fe.tableId() == 1) {
+                //Note that in MockNetconf session 10.10.10.10/16 was entered
+                //but it has been corrected to the following by the OF implementation
+                assertEquals("10.10.0.0/16", ipCr.ip().toString());
+                assertEquals(FlowEntryState.ADDED, fe.state());
+            } else if (fe.tableId() == 2) {
+                //Likewise 20.30.40.50 has been truncated because of the 18 bit mask
+                assertEquals("20.30.0.0/18", ipCr.ip().toString());
+                assertEquals(FlowEntryState.ADDED, fe.state());
+            } else if (fe.tableId() == 7 || fe.tableId() == 8) {
+                // 7 and 8 are EVC entries - 2 elements - IN_PORT and VLAN_ID
+                assertEquals(2, fe.selector().criteria().size());
+                //In MockNetconfSession we're rigged it so that the last two chars of the
+                //flow id is the same as the VlanId
+                short vlanId = ((VlanIdCriterion) fe.selector().getCriterion(Type.VLAN_VID)).vlanId().toShort();
+                long flowId = fe.id().id();
+                String flowIdStr = String.valueOf(flowId).substring(String.valueOf(flowId).length() - 2);
+                assertEquals(flowIdStr, String.valueOf(vlanId));
+                if (((PortCriterion) fe.selector().getCriterion(Type.IN_PORT)).port().toLong() == 1L) {
+                    assertEquals(Instruction.Type.L2MODIFICATION, instructions.get(0).type());
+                }
+            } else {
+                fail("Unexpected Flow Entry Rule " + fe.tableId());
+            }
+        }
+    }
+
+    @Test
+    public void testSetFlowEntries() {
+        Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0));
+
+        TrafficTreatment treatmentDrop = DefaultTrafficTreatment.builder().drop().build();
+
+        Collection<FlowRule> frAddedList = new HashSet<FlowRule>();
+
+        FlowRule fr4 = new DefaultFlowRule.Builder()
+            .forDevice(frProgramable.handler().data().deviceId())
+            .forTable(4)
+            .withSelector(DefaultTrafficSelector.builder()
+                    .matchIPSrc(IpPrefix.valueOf("192.168.60.0/22"))
+                    .add(matchInPort).build())
+            .withTreatment(treatmentDrop)
+            .fromApp(new DefaultApplicationId(4, "Filter4"))
+            .makePermanent()
+            .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+            .build();
+        frAddedList.add(fr4);
+
+        FlowRule fr5 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(5)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchIPSrc(IpPrefix.valueOf("192.168.50.0/23"))
+                        .add(matchInPort).build())
+                .withTreatment(treatmentDrop)
+                .withCookie(Long.valueOf("5e0000abaa2772", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(fr5);
+
+        //Add in some EVCs - especially with complex ceVlanMaps
+        FlowRule frEvc1Vid19P0 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(1)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchInPort(PortNumber.portNumber(0L))
+                        .matchVlanId(VlanId.vlanId((short) 19))
+                        .build())
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .popVlan()
+                        .build())
+                .withCookie(Long.valueOf("1e0000abaa0019", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(frEvc1Vid19P0);
+
+        FlowRule frEvc1Vid20P0 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(1)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchInPort(PortNumber.portNumber(0L))
+                        .matchVlanId(VlanId.vlanId((short) 20))
+                        .build())
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .popVlan()
+                        .build())
+                .withCookie(Long.valueOf("1e0000abaa0020", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(frEvc1Vid20P0);
+
+        FlowRule frEvc1Vid21P1 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(1)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchInPort(PortNumber.portNumber(1L))
+                        .matchVlanId(VlanId.vlanId((short) 21))
+                        .build())
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .setVlanId(VlanId.vlanId((short) 250))
+                        .pushVlan(EtherType.QINQ.ethType())
+                        .build())
+                .withCookie(Long.valueOf("1e0000abaa0121", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(frEvc1Vid21P1);
+
+        FlowRule frEvc1Vid22P1 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(1)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchInPort(PortNumber.portNumber(1L))
+                        .matchVlanId(VlanId.vlanId((short) 22))
+                        .build())
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .setVlanId(VlanId.vlanId((short) 250))
+                        .pushVlan(EtherType.QINQ.ethType())
+                        .build())
+                .withCookie(Long.valueOf("1e0000abaa0122", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(frEvc1Vid22P1);
+
+        Collection<FlowRule> returnedFrList = frProgramable.applyFlowRules(frAddedList);
+
+        assertNotNull(returnedFrList);
+        assertEquals(6, returnedFrList.size());
+
+        //Test the scenario like in FlowRuleManager$InternalFlowRuleProviderService.pushFlowMetricsInternal()
+        Map<FlowEntry, FlowEntry> storedRules = Maps.newHashMap();
+        frAddedList.forEach(f -> storedRules.put(new DefaultFlowEntry(f), new DefaultFlowEntry(f)));
+        List<FlowEntry> feList = Lists.newArrayList();
+        returnedFrList.forEach(f -> feList.add(new DefaultFlowEntry(f)));
+
+        for (FlowEntry rule : feList) {
+            FlowEntry fer = storedRules.remove(rule);
+            assertNotNull(fer);
+            assertTrue(fer.exactMatch(rule));
+        }
+
+        for (FlowRule fr:returnedFrList.toArray(new FlowRule[2])) {
+            if (fr.tableId() == 4) {
+                assertEquals("IPV4_SRC:192.168.60.0/22",
+                        ((IPCriterion) fr.selector().getCriterion(Type.IPV4_SRC)).toString());
+            } else if (fr.tableId() == 5) {
+                assertEquals("IPV4_SRC:192.168.50.0/23",
+                        ((IPCriterion) fr.selector().getCriterion(Type.IPV4_SRC)).toString());
+                assertEquals(Long.valueOf("5e0000abaa2772", 16), fr.id().id());
+            } else if (fr.tableId() == 1) {
+                //TODO add in tests
+            } else {
+                fail("Unexpected flow rule " + fr.tableId() + " in test");
+            }
+        }
+    }
+
+    @Test
+    public void testRemoveFlowEntries() {
+        TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();
+        Criterion matchInPort0 = Criteria.matchInPort(PortNumber.portNumber(0));
+        Criterion matchInPort1 = Criteria.matchInPort(PortNumber.portNumber(1));
+
+        TrafficTreatment.Builder trDropBuilder = DefaultTrafficTreatment.builder();
+        TrafficTreatment treatmentDrop = trDropBuilder.drop().build();
+
+        Collection<FlowRule> frRemoveList = new HashSet<FlowRule>();
+        ApplicationId app = new DefaultApplicationId(1, "org.onosproject.rest");
+
+        Criterion matchIpSrc1 = Criteria.matchIPSrc(IpPrefix.valueOf("10.10.10.10/16"));
+        TrafficSelector selector1 = tsBuilder.add(matchIpSrc1).add(matchInPort0).build();
+        FlowRule.Builder frBuilder1 = new DefaultFlowRule.Builder();
+        frBuilder1.forDevice(frProgramable.handler().data().deviceId())
+                .withSelector(selector1)
+                .withTreatment(treatmentDrop)
+                .forTable(2)
+                .fromApp(app)
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT);
+        frRemoveList.add(frBuilder1.build());
+
+        Criterion matchIpSrc2 = Criteria.matchIPSrc(IpPrefix.valueOf("10.30.10.10/16"));
+        TrafficSelector selector2 = tsBuilder.add(matchIpSrc2).add(matchInPort0).build();
+        FlowRule.Builder frBuilder2 = new DefaultFlowRule.Builder();
+        frBuilder2.forDevice(frProgramable.handler().data().deviceId())
+                .withSelector(selector2)
+                .withTreatment(treatmentDrop)
+                .forTable(3)
+                .fromApp(app)
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frRemoveList.add(frBuilder2.build());
+
+
+        TrafficTreatment.Builder trVlanPopBuilder = DefaultTrafficTreatment.builder();
+        TrafficTreatment treatmentVlanPop = trVlanPopBuilder.popVlan().build();
+
+
+        Criterion matchVlan710 = Criteria.matchVlanId(VlanId.vlanId((short) 710));
+        TrafficSelector selector3 = DefaultTrafficSelector.builder().add(matchVlan710).add(matchInPort1).build();
+        FlowRule.Builder frBuilder3 = new DefaultFlowRule.Builder();
+        frBuilder3.forDevice(frProgramable.handler().data().deviceId())
+            .withSelector(selector3)
+            .withTreatment(treatmentVlanPop)
+            .forTable(7)
+            .fromApp(app)
+            .makePermanent()
+            .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+            .build();
+        frRemoveList.add(frBuilder3.build());
+
+
+        Criterion matchVlan101 = Criteria.matchVlanId(VlanId.vlanId((short) 101));
+        TrafficSelector selector4 = DefaultTrafficSelector.builder().add(matchVlan101).add(matchInPort1).build();
+        FlowRule.Builder frBuilder4 = new DefaultFlowRule.Builder();
+        frBuilder4.forDevice(frProgramable.handler().data().deviceId())
+            .withSelector(selector4)
+            .withTreatment(treatmentVlanPop)
+            .forTable(1)
+            .fromApp(app)
+            .makePermanent()
+            .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+            .build();
+        frRemoveList.add(frBuilder4.build());
+
+        Criterion matchVlan102 = Criteria.matchVlanId(VlanId.vlanId((short) 102));
+        TrafficSelector selector5 = DefaultTrafficSelector.builder().add(matchVlan102).add(matchInPort0).build();
+        FlowRule.Builder frBuilder5 = new DefaultFlowRule.Builder();
+        frBuilder5.forDevice(frProgramable.handler().data().deviceId())
+            .withSelector(selector5)
+            .withTreatment(treatmentVlanPop)
+            .forTable(1)
+            .fromApp(app)
+            .makePermanent()
+            .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+            .build();
+        frRemoveList.add(frBuilder5.build());
+
+        Collection<FlowRule> removedFrList = frProgramable.removeFlowRules(frRemoveList);
+        assertNotNull(removedFrList);
+        assertEquals(5, removedFrList.size());
+
+        for (FlowRule frRemoved:removedFrList) {
+            assertNotNull(frRemoved);
+        }
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java
new file mode 100644
index 0000000..b00b321
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 java.util.HashSet;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager;
+import org.onosproject.drivers.microsemi.yang.MockNetconfSessionEa1000;
+import org.onosproject.drivers.netconf.MockNetconfController;
+import org.onosproject.drivers.netconf.MockNetconfDevice;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.DefaultBand;
+import org.onosproject.net.meter.DefaultMeter;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.Meter.Unit;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.net.meter.MeterOperation;
+import org.onosproject.net.meter.MeterOperation.Type;
+import org.onosproject.netconf.NetconfController;
+
+public class EA1000MeterProviderTest {
+
+    private EA1000MeterProvider meterProvider;
+    private NetconfController controller;
+    private DeviceId mockDeviceId;
+    private MockMseaUniEvcServiceManager mseaUniEvcServiceSvc;
+
+    @Before
+    public void setUp() throws Exception {
+        mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+        controller = new MockNetconfController();
+        MockNetconfDevice device = (MockNetconfDevice) controller.connectDevice(mockDeviceId);
+        device.setNcSessionImpl(MockNetconfSessionEa1000.class);
+        mseaUniEvcServiceSvc = new MockMseaUniEvcServiceManager();
+        mseaUniEvcServiceSvc.activate();
+        meterProvider = new TestEA1000MeterProvider(controller, mseaUniEvcServiceSvc);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testPerformMeterOperationDeviceIdMeterAdd() {
+        DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+
+        Band cbsBand = DefaultBand.builder()
+                .ofType(Band.Type.REMARK) //Committed - CIR & CBS
+                .withRate(37500L)
+                .burstSize(2000)
+                .dropPrecedence((short) 0)
+                .build();
+
+        Band ebsBand = DefaultBand.builder()
+                .ofType(Band.Type.DROP) //Excess - EIR & EBS
+                .withRate(50000L) //The rate at which we drop - for EA 1000 subtract CIR to get EIR
+                .burstSize(3000) //The burst rate to drop at
+                .build();
+
+        Meter.Builder mBuilder = DefaultMeter.builder()
+                .forDevice(mockDeviceId)
+                .withId(MeterId.meterId(1))
+                .fromApp(new DefaultApplicationId(101, "unit.test"))
+                .burst()
+                .withUnit(Unit.KB_PER_SEC)
+                .withBands(new HashSet<Band>() { { add(cbsBand); add(ebsBand); } });
+
+        MeterOperation meterOp = new MeterOperation(mBuilder.build(), Type.ADD);
+
+        meterProvider.performMeterOperation(mockDeviceId, meterOp);
+        //The NETCONF XML generated by this matches the pattern
+        // sampleXmlRegexEditConfigBwpGroup1
+        // in MockNetconfSession
+    }
+
+    @Test
+    public void testPerformMeterOperationDeviceIdMeterRemove() {
+        DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+
+        Band cbsBand = DefaultBand.builder()
+                .ofType(Band.Type.REMARK) //Committed - CIR & CBS
+                .withRate(37500L)
+                .burstSize(2000)
+                .dropPrecedence((short) 0)
+                .build();
+
+        Meter.Builder mBuilder = DefaultMeter.builder()
+                .forDevice(mockDeviceId)
+                .withId(MeterId.meterId(1))
+                .fromApp(new DefaultApplicationId(101, "unit.test"))
+                .burst()
+                .withBands(new HashSet<Band>() { { add(cbsBand); } });
+
+        MeterOperation meterOp = new MeterOperation(mBuilder.build(), Type.REMOVE);
+
+        meterProvider.performMeterOperation(mockDeviceId, meterOp);
+        //The NETCONF XML generated by this matches the pattern
+        // sampleXmlRegexEditConfigBwpGroup1
+        // in MockNetconfSession
+    }
+
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java
new file mode 100644
index 0000000..a53c6e3
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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 org.junit.Before;
+import org.onosproject.net.driver.AbstractDriverLoaderTest;
+
+
+/**
+ * Microsemi drivers loader test.
+ */
+public class MicrosemiDriversLoaderTest extends AbstractDriverLoaderTest {
+
+    @Before
+    public void setUp() {
+        loader = new MicrosemiDriversLoader();
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
new file mode 100644
index 0000000..78a9d32
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 java.util.HashMap;
+import java.util.Map;
+
+import org.onosproject.core.CoreService;
+import org.onosproject.drivers.microsemi.yang.MockMseaSaFilteringManager;
+import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager;
+import org.onosproject.drivers.microsemi.yang.MockNetconfSessionEa1000;
+import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.drivers.netconf.MockCoreService;
+import org.onosproject.drivers.netconf.MockNetconfController;
+import org.onosproject.drivers.netconf.MockNetconfDevice;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.DefaultDriver;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.flow.FlowRuleProgrammable;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+
+/**
+ * A Mock implementation of the DriverHandler to facilitate unit tests.
+ *
+ * This brings in the implementations of MockMseaSaFilteringManager, MockMseaUniEvcServiceManager,
+ * MockCoreService, MockNetconfDevice and MockNetconfSessionEa1000
+ */
+public class MockEa1000DriverHandler implements DriverHandler {
+
+    private static final String MICROSEMI_DRIVERS = "com.microsemi.drivers";
+
+    private DriverData mockDriverData;
+
+    private NetconfController ncc;
+    private MockMseaSaFilteringManager mseaSaFilteringService;
+    private MockMseaUniEvcServiceManager mseaUniEvcService;
+    private CoreService coreService;
+
+    public MockEa1000DriverHandler() throws NetconfException {
+        Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours =
+                new HashMap<Class<? extends Behaviour>, Class<? extends Behaviour>>();
+        behaviours.put(FlowRuleProgrammable.class, FlowRuleProgrammable.class);
+
+        Map<String, String> properties = new HashMap<String, String>();
+
+        Driver mockDriver =
+                new DefaultDriver("mockDriver", null, "ONOSProject", "1.0.0", "1.0.0", behaviours, properties);
+        DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+        mockDriverData = new DefaultDriverData(mockDriver, mockDeviceId);
+
+
+        ncc = new MockNetconfController();
+        MockNetconfDevice device = (MockNetconfDevice) ncc.connectDevice(mockDeviceId);
+        device.setNcSessionImpl(MockNetconfSessionEa1000.class);
+
+        mseaSaFilteringService = new MockMseaSaFilteringManager();
+        mseaSaFilteringService.activate();
+
+        mseaUniEvcService = new MockMseaUniEvcServiceManager();
+        mseaUniEvcService.activate();
+
+        coreService = new MockCoreService();
+        coreService.registerApplication(MICROSEMI_DRIVERS);
+    }
+
+    @Override
+    public Driver driver() {
+        return mockDriverData.driver();
+    }
+
+    @Override
+    public DriverData data() {
+        return mockDriverData;
+    }
+
+    @Override
+    public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T> T get(Class<T> serviceClass) {
+        if (serviceClass.equals(NetconfController.class)) {
+            return (T) ncc;
+
+        } else if (serviceClass.equals(MseaSaFilteringNetconfService.class)) {
+            return (T) mseaSaFilteringService;
+
+        } else if (serviceClass.equals(MseaUniEvcServiceNetconfService.class)) {
+            return (T) mseaUniEvcService;
+
+        } else if (serviceClass.equals(CoreService.class)) {
+            return (T) coreService;
+
+        }
+
+        return null;
+    }
+
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java
new file mode 100644
index 0000000..64dd80e
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.junit.Assert.*;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.junit.Test;
+
+public class RpcResultParserTest {
+
+    private static final String SAMPLE1_XML = "/systemReply-Sample1.xml";
+    private static final String SAMPLE2_XML = "/systemReply-Sample2.xml";
+
+    @Test
+    public void testSerialNumber1() {
+        String serialNumberReply = loadXml(SAMPLE1_XML);
+        String serialNumber = RpcResultParser.parseXml(serialNumberReply, "serial-number");
+        assertEquals("Eagle Simulator.", serialNumber);
+    }
+
+    @Test
+    public void testSerialNumber2() {
+        String serialNumberReply = loadXml(SAMPLE2_XML);
+        String serialNumber = RpcResultParser.parseXml(serialNumberReply, "serial-number");
+        assertEquals(null, serialNumber);
+    }
+
+    @Test
+    public void testOsRelease1() {
+        String osReleaseReply = loadXml(SAMPLE1_XML);
+        String osRelease = RpcResultParser.parseXml(osReleaseReply, "os-release");
+        assertEquals("2.6.33-arm1-MSEA1000--00326-g643be76.x.0.0.212", osRelease);
+    }
+
+    @Test
+    public void testOsRelease2() {
+        String osReleaseReply = loadXml(SAMPLE2_XML);
+        String osRelease = RpcResultParser.parseXml(osReleaseReply, "os-release");
+        assertEquals(null, osRelease);
+    }
+
+    @Test
+    public void testLongitude() {
+        String longitudeReply = loadXml(SAMPLE1_XML);
+        String longitudeStr = RpcResultParser.parseXml(longitudeReply, "longitude");
+        assertEquals("-8.4683990", longitudeStr);
+    }
+
+    @Test
+    public void testLatitude() {
+        String latitudeReply = loadXml(SAMPLE1_XML);
+        String latitudeStr = RpcResultParser.parseXml(latitudeReply, "latitude");
+        assertEquals("51.9036140", latitudeStr);
+    }
+
+
+    private static String loadXml(final String fileName) {
+
+        InputStream inputStream = RpcResultParserTest.class.getResourceAsStream(fileName);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+        StringBuilder result = new StringBuilder();
+        try {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                result.append(line);
+            }
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return result.toString();
+    }
+}
\ No newline at end of file
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java
new file mode 100644
index 0000000..e56e121
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.netconf.NetconfController;
+
+public class TestEA1000MeterProvider extends EA1000MeterProvider {
+
+    public TestEA1000MeterProvider(NetconfController controller,
+            MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc) {
+        this.controller = controller;
+        this.mseaUniEvcServiceSvc = mseaUniEvcServiceSvc;
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java
new file mode 100644
index 0000000..c7b3e72
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils;
+
+public class CeVlanMapUtilsTest {
+
+    @Test
+    public void testGetVlanSet() {
+        Short[] vlanArray = CeVlanMapUtils.getVlanSet("101:102");
+        assertEquals(2, vlanArray.length);
+
+        vlanArray = CeVlanMapUtils.getVlanSet("101:103,107,110:115");
+        assertEquals(10, vlanArray.length);
+
+        vlanArray = CeVlanMapUtils.getVlanSet("1:4095");
+        assertEquals(4095, vlanArray.length);
+    }
+
+    @Test
+    public void testVlanListAsString() {
+        String ceVlanMap = CeVlanMapUtils.vlanListAsString(new Short[]{101, 102, 103});
+        assertEquals("101:103", ceVlanMap);
+
+        ceVlanMap = CeVlanMapUtils.vlanListAsString(new Short[]{0, 101, 104, 108});
+        assertEquals("101,104,108", ceVlanMap);
+    }
+
+    @Test
+    public void testAddtoCeVlanMap() {
+        String ceVlanMap = CeVlanMapUtils.addtoCeVlanMap("101:102", (short) 103);
+        assertEquals("101:103", ceVlanMap);
+
+        ceVlanMap = CeVlanMapUtils.addtoCeVlanMap("101:102", (short) 0);
+        assertEquals("101:102", ceVlanMap);
+
+        ceVlanMap = CeVlanMapUtils.addtoCeVlanMap("101:102", (short) 104);
+        assertEquals("101:102,104", ceVlanMap);
+    }
+
+    @Test
+    public void testRemoveZeroIfPossible() {
+        String ceVlanMap = CeVlanMapUtils.removeZeroIfPossible("101:102");
+        assertEquals("101:102", ceVlanMap);
+
+        ceVlanMap = CeVlanMapUtils.removeZeroIfPossible("0,101:102");
+        assertEquals("101:102", ceVlanMap);
+
+        ceVlanMap = CeVlanMapUtils.removeZeroIfPossible("0");
+        assertEquals("0", ceVlanMap);
+    }
+
+    @Test
+    public void testRemoveFromCeVlanMap() {
+        String ceVlanMap = CeVlanMapUtils.removeFromCeVlanMap("101:102", (short) 102);
+        assertEquals("101", ceVlanMap);
+
+        ceVlanMap = CeVlanMapUtils.removeFromCeVlanMap("101:103", (short) 102);
+        assertEquals("101,103", ceVlanMap);
+    }
+
+    @Test
+    public void testCombineVlanSets() {
+        assertEquals("101:104", CeVlanMapUtils.combineVlanSets("101:102", "103:104"));
+
+        assertEquals("101:103", CeVlanMapUtils.combineVlanSets("101:102", "103"));
+
+        assertEquals("101:102,104", CeVlanMapUtils.combineVlanSets("101:102", "104"));
+
+        assertEquals("99,101:102", CeVlanMapUtils.combineVlanSets("101:102", "99"));
+
+        assertEquals("101:102", CeVlanMapUtils.combineVlanSets("101:102", "0"));
+
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java
new file mode 100644
index 0000000..098ecdd
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.UncheckedIOException;
+import java.text.ParseException;
+import java.time.OffsetDateTime;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.drivers.microsemi.yang.impl.IetfSystemManager;
+import org.onosproject.netconf.NetconfDeviceInfo;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.AugmentedSysSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.DefaultAugmentedSysSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.AugmentedSysPlatform;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.System;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.system.DefaultClock;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.system.clock.timezone.DefaultTimezoneName;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.DefaultAugmentedSysPlatform;
+
+public class IetfSystemManagerTest {
+
+    IetfSystemManager sysSvc = null;
+    NetconfSession session;
+
+    @Before
+    public void setUp() throws Exception {
+        try {
+            sysSvc = new MockIetfSystemManager();
+            sysSvc.activate();
+        } catch (UncheckedIOException e) {
+            fail(e.getMessage());
+        }
+        NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf", Ip4Address.valueOf("1.2.3.4"), 830);
+        session = new MockNetconfSessionEa1000(deviceInfo);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        sysSvc.deactivate();
+    }
+
+    @Test
+    public void testGetIetfSystemSession() throws NetconfException {
+        System system = new DefaultSystem();
+        system.clock(new DefaultClock());
+
+        IetfSystemOpParam sampleSystem = new IetfSystemOpParam();
+        sampleSystem.system(system);
+
+        IetfSystem sys = sysSvc.getIetfSystem(sampleSystem, session);
+        assertNotNull(sys);
+
+        assertEquals(sys.system().clock().timezone().getClass(), DefaultTimezoneName.class);
+        DefaultTimezoneName tzName = (DefaultTimezoneName) sys.system().clock().timezone();
+        assertEquals("Etc/UTC", tzName.timezoneName().string());
+    }
+
+    @Test
+    public void testGetIetfSystemInit() throws NetconfException {
+
+        IetfSystem sys = sysSvc.getIetfSystemInit(session);
+        assertNotNull(sys);
+        assertNotNull(sys.system());
+
+        AugmentedSysSystem sysSystem = (AugmentedSysSystem) sys.system().augmentation(DefaultAugmentedSysSystem.class);
+
+        assertEquals("-8.4683990", sysSystem.longitude().toPlainString());
+        assertEquals("51.9036140", sysSystem.latitude().toPlainString());
+        assertEquals("4.4.0-53-generic", sys.systemState().platform().osRelease());
+
+        AugmentedSysPlatform sysSystemState =
+                (AugmentedSysPlatform) sys.systemState().platform().augmentation(DefaultAugmentedSysPlatform.class);
+
+        assertEquals("Eagle Simulator.", sysSystemState.deviceIdentification().serialNumber());
+    }
+
+    @Test
+    public void testSetCurrentDatetime() throws NetconfException, ParseException {
+        sysSvc.setCurrentDatetime(OffsetDateTime.now(), session);
+        //Look at MockNetconfSessionEa1000::sampleXmlRegexSetCurrentDatetime() for catching an error
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java
new file mode 100644
index 0000000..f035c70
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+
+import org.onosproject.drivers.microsemi.yang.impl.IetfSystemManager;
+import org.onosproject.yang.MockYangRuntimeManager;
+import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry;
+import org.onosproject.yang.serializers.xml.MockYangSerializerContext;
+import org.onosproject.yang.serializers.xml.XmlSerializer;
+
+public class MockIetfSystemManager extends IetfSystemManager {
+
+    @Override
+    public void activate() {
+        yCtx = new MockYangSerializerContext();
+        xSer = new XmlSerializer();
+        yangModelRegistry = new MockYangRuntimeManager();
+        ((MockYangRuntimeManager) yangModelRegistry).setModelRegistry(
+                (DefaultYangModelRegistry) yCtx.getContext());
+        ((MockYangRuntimeManager) yangModelRegistry).activate();
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java
new file mode 100644
index 0000000..fb20697
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.drivers.microsemi.yang.impl.MseaCfmManager;
+import org.onosproject.yang.MockYangRuntimeManager;
+import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry;
+import org.onosproject.yang.serializers.xml.MockYangSerializerContext;
+import org.onosproject.yang.serializers.xml.XmlSerializer;
+
+public class MockMseaCfmManager extends MseaCfmManager {
+
+    @Override
+    public void activate() {
+        yCtx = new MockYangSerializerContext();
+        xSer = new XmlSerializer();
+        yangModelRegistry = new MockYangRuntimeManager();
+        ((MockYangRuntimeManager) yangModelRegistry).setModelRegistry(
+                (DefaultYangModelRegistry) yCtx.getContext());
+        ((MockYangRuntimeManager) yangModelRegistry).activate();
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java
new file mode 100644
index 0000000..a2de180
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.drivers.microsemi.yang.impl.MseaSaFilteringManager;
+import org.onosproject.yang.MockYangRuntimeManager;
+import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry;
+import org.onosproject.yang.serializers.xml.MockYangSerializerContext;
+import org.onosproject.yang.serializers.xml.XmlSerializer;
+
+public class MockMseaSaFilteringManager extends MseaSaFilteringManager {
+
+    @Override
+    public void activate() {
+        yCtx = new MockYangSerializerContext();
+        xSer = new XmlSerializer();
+        yangModelRegistry = new MockYangRuntimeManager();
+        ((MockYangRuntimeManager) yangModelRegistry).setModelRegistry(
+                (DefaultYangModelRegistry) yCtx.getContext());
+        ((MockYangRuntimeManager) yangModelRegistry).activate();
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java
new file mode 100644
index 0000000..e7921c2
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.drivers.microsemi.yang.impl.MseaUniEvcServiceManager;
+import org.onosproject.yang.MockYangRuntimeManager;
+import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry;
+import org.onosproject.yang.serializers.xml.MockYangSerializerContext;
+import org.onosproject.yang.serializers.xml.XmlSerializer;
+
+public class MockMseaUniEvcServiceManager extends MseaUniEvcServiceManager {
+    @Override
+    public void activate() {
+        yCtx = new MockYangSerializerContext();
+        xSer = new XmlSerializer();
+        yangModelRegistry = new MockYangRuntimeManager();
+        ((MockYangRuntimeManager) yangModelRegistry).setModelRegistry(
+                (DefaultYangModelRegistry) yCtx.getContext());
+        ((MockYangRuntimeManager) yangModelRegistry).activate();
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java
new file mode 100644
index 0000000..fc6da58
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java
@@ -0,0 +1,1034 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfDeviceInfo;
+import org.onosproject.netconf.NetconfDeviceOutputEventListener;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.netconf.TargetConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MockNetconfSessionEa1000 implements NetconfSession {
+    private static final Logger log = LoggerFactory
+            .getLogger(MockNetconfSessionEa1000.class);
+
+    private static final String MESSAGE_ID_STRING = "message-id";
+    private static final String EQUAL = "=";
+    private static final String RPC_OPEN = "<rpc ";
+    private static final String RPC_CLOSE = "</rpc>";
+    private static final String GET_OPEN = "<get>";
+    private static final String GET_CLOSE = "</get>";
+    private static final String NEW_LINE = "\n";
+    private static final String SUBTREE_FILTER_OPEN = "<filter type=\"subtree\">";
+    private static final String SUBTREE_FILTER_CLOSE = "</filter>";
+    private static final String WITH_DEFAULT_OPEN = "<with-defaults ";
+    private static final String WITH_DEFAULT_CLOSE = "</with-defaults>";
+    private static final String EDIT_CONFIG_OPEN = "<edit-config>";
+    private static final String EDIT_CONFIG_CLOSE = "</edit-config>";
+    private static final String TARGET_OPEN = "<target>";
+    private static final String TARGET_CLOSE = "</target>";
+    private static final String DEFAULT_OPERATION_OPEN = "<default-operation>";
+    private static final String DEFAULT_OPERATION_CLOSE = "</default-operation>";
+    private static final String CONFIG_OPEN = "<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
+    private static final String CONFIG_CLOSE = "</config>";
+
+    private static final String ENDPATTERN = "]]>]]>";
+    private static final String XML_HEADER =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+    private static final String NETCONF_BASE_NAMESPACE =
+            "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"";
+    private static final String NETCONF_WITH_DEFAULTS_NAMESPACE =
+            "xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\"";
+
+
+    private Pattern sampleXmlRegex1 =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get>).*(<filter).*"
+                    + "(<system).*(<clock/>).*(</system>).*(</filter>)*.(</get>).*(</rpc).*(]]>){2}",
+                    Pattern.DOTALL);
+
+    private Pattern sampleXmlRegex2 =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get>).*(<filter).*(<system-state).*(</system-state>).*"
+                    + "(<system).*(</system>).*(</filter>).*(</get>).*(</rpc).*(]]>){2}",
+                    Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexSaFiltering =
+            Pattern.compile("(<\\?xml).*"
+                    + "(<rpc).*(<get>).*"
+                    + "(<filter type=\"subtree\">).*(<source-ipaddress-filtering).*"
+                    + "(</filter>).*(</get>).*(</rpc>).*"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexEditConfigSaFilt =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>).*"
+                    + "(<target><running/></target>).*(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">).*"
+                    + "(<source-ipaddress-filtering).*(<interface-eth0>).*"
+                    + "(<source-address-range>).*(<range-id>).*(</range-id>).*"
+                    + "(<name>).*(</name>).*(<ipv4-address-prefix>).*(</ipv4-address-prefix>).*"
+                    + "(</source-address-range>).*(</interface-eth0>)*(</source-ipaddress-filtering>).*"
+                    + "(</config>).*(</edit-config>).*(</rpc>).*(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexEditDeleteSaFilt =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target><running/></target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<source-ipaddress-filtering "
+                    + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering\">)\\R?"
+                    + "(<interface-eth0>)\\R?"
+                    + "((<source-address-range nc:operation=\"delete\">)\\R?"
+                    + "(<range-id>)[0-9]*(</range-id>)\\R?"
+                    + "((<name>)[a-zA-Z0-9]*(</name>))?\\R?"
+                    + "((<ipv4-address-prefix>)[0-9\\\\./]*(</ipv4-address-prefix>))?\\R?"
+                    + "(</source-address-range>))++\\R?"
+                    + "(</interface-eth0>)\\R?"
+                    + "(</source-ipaddress-filtering>)\\R?"
+                    + "(</config>)\\R?"
+                    + "(</edit-config>)\\R?(</rpc>).*(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexUniEvc =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get-config>)\\R?"
+                    + "(<source>)\\R?(<running/>)\\R?(</source>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<mef-services "
+                    + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\"/>)\\R?"
+                    + "(</filter>)\\R?(</get-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexUniEvcUni =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get-config>)\\R?"
+                    + "(<source>)\\R?(<running/>)\\R?(</source>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<mef-services "
+                    + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">)\\R?"
+                    + "(<uni/>)\\R?"
+                    + "(</mef-services>)\\R?"
+                    + "(</filter>)\\R?(</get-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexEditConfigUni1Evc =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target><running/></target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-services).*(<uni>)\\R?(<name>).*(</name>)\\R?"
+                    + "(<evc>)\\R?(<evc-index>).*(</evc-index>)\\R?(<name>).*(</name>)\\R?"
+                    + "(<evc-per-uni>)\\R?"
+                    + "(<evc-per-uni-c>)\\R?"
+                    + "(<ce-vlan-map>)[0-9]*(</ce-vlan-map>)\\R?"
+                    + "(<ingress-bwp-group-index>)[0-9]*(</ingress-bwp-group-index>)\\R?"
+                    + "(<tag-push>)\\R?(<push-tag-type>)pushStag(</push-tag-type>)\\R?"
+                    + "(<outer-tag-vlan>)[0-9]*(</outer-tag-vlan>)\\R?(</tag-push>)\\R?"
+                    + "((<flow-mapping>)\\R?"
+                    + "(<ce-vlan-id>)[0-9]*(</ce-vlan-id>)\\R?"
+                    + "(<flow-id>)[0-9]*(</flow-id>)\\R?"
+                    + "(</flow-mapping>)\\R?)*"
+                    + "(</evc-per-uni-c>)\\R?"
+                    + "(<evc-per-uni-n>)\\R?"
+                    + "(<ce-vlan-map>)[0-9\\:\\,]*(</ce-vlan-map>)\\R?"
+                    + "(<ingress-bwp-group-index>)[0-9]*(</ingress-bwp-group-index>)\\R?"
+                    + "(<tag-pop).*"
+                    + "((<flow-mapping>)\\R?"
+                    + "(<ce-vlan-id>)[0-9]*(</ce-vlan-id>)\\R?"
+                    + "(<flow-id>)[0-9]*(</flow-id>)\\R?"
+                    + "(</flow-mapping>)\\R?)*"
+                    + "(</evc-per-uni-n>)\\R?"
+                    + "(</evc-per-uni>)\\R?"
+                    + "(</evc>)\\R?"
+                    + "(</uni>)\\R?"
+                    + "(</mef-services>)\\R?"
+                    + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexEditConfigUni2Evc =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target><running/></target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-services).*(<uni>)\\R?(<name>)[0-9a-zA-Z\\-\\:]*(</name>)\\R?"
+                    + "(<evc>)\\R?(<evc-index>)[0-9]*(</evc-index>)\\R?(<name>)[0-9a-zA-Z\\-\\:]*(</name>)\\R?"
+                    + "(<evc-per-uni>)\\R?"
+                    + "(<evc-per-uni-c>)\\R?"
+                    + "(<ce-vlan-map>)[0-9\\:\\,]*(</ce-vlan-map>)\\R?"
+                    + "(<ingress-bwp-group-index>)[0-9]*(</ingress-bwp-group-index>)\\R?"
+                    + "(</evc-per-uni-c>)\\R?"
+                    + "(<evc-per-uni-n>)\\R?"
+                    + "(<ce-vlan-map>)[0-9\\:\\,]*(</ce-vlan-map>)\\R?"
+                    + "(<ingress-bwp-group-index>)[0-9]*(</ingress-bwp-group-index>)\\R?"
+                    + "(<evc-per-uni-service-type>).*(</evc-per-uni-service-type>)\\R?"
+                    + "(<tag-push>)\\R?(<push-tag-type>)pushStag(</push-tag-type>)\\R?(<outer-tag-vlan>).*"
+                    + "(</outer-tag-vlan>)\\R?(</tag-push>)\\R?"
+                    + "(</evc-per-uni-n>)\\R?"
+                    + "(</evc-per-uni>)\\R?"
+                    + "(</evc>)\\R?"
+                    + "(<evc>)\\R?(<evc-index>)[0-9]*(</evc-index>)\\R?(<name>)[0-9a-zA-Z\\-\\:]*(</name>)\\R?"
+                    + "(<evc-per-uni>)\\R?"
+                    + "(<evc-per-uni-c>)\\R?"
+                    + "(<ce-vlan-map>)[0-9\\:\\,]*(</ce-vlan-map>)\\R?"
+                    + "(<ingress-bwp-group-index>)[0-9]*(</ingress-bwp-group-index>)\\R?"
+                    + "(</evc-per-uni-c>)\\R?"
+                    + "(<evc-per-uni-n>)\\R?"
+                    + "(<ce-vlan-map>)[0-9\\:\\,]*(</ce-vlan-map>)\\R?"
+                    + "(<ingress-bwp-group-index>)[0-9]*(</ingress-bwp-group-index>)\\R?"
+                    + "(</evc-per-uni-n>)\\R?"
+                    + "(</evc-per-uni>)\\R?"
+                    + "(</evc>)\\R?(</uni>).*"
+                    + "(</mef-services>)\\R?"
+                    + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexEditConfigUniProfiles =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>).*"
+                    + "(<target><running/></target>).*(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">).*"
+                    + "(<mef-services).*(<profiles>).*"
+                    + "(<bwp-group>).*(<group-index>).*(</group-index>).*(</bwp-group>).*"
+                    + "(<bwp-group>).*(<group-index>).*(</group-index>).*"
+                    + "(<bwp>).*(<cos-index>).*(</cos-index>).*(<color-mode>).*(</color-mode>).*(</bwp>).*"
+                    + "(<bwp>).*(<cos-index>).*(</cos-index>).*(<color-mode>).*(</color-mode>).*(</bwp>).*"
+                    + "(</bwp-group>).*"
+                    + "(</profiles>).*(</mef-services>).*"
+                    + "(</config>).*(</edit-config>).*(</rpc>).*(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexEditConfigEvcDelete =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>).*"
+                    + "(<target><running/></target>).*(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">).*"
+                    + "(<mef-services).*"
+                    + "(<uni>).*"
+                    + "(<evc nc:operation=\"delete\">).*(<evc-index>).*(</evc-index>).*(</evc>).*"
+                    + "(</uni>).*"
+                    + "(</mef-services>).*"
+                    + "(</config>).*(</edit-config>).*(</rpc>).*(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexGetConfigCeVlanMapsEvc =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get-config>)\\R?"
+                    + "(<source>)\\R?(<running/>)\\R?(</source>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<mef-services).*"
+                    + "(<uni>)\\R?"
+                    + "(<evc>)\\R?"
+                    + "(<evc-index/>)\\R?"
+                    + "(<evc-per-uni>)\\R?"
+                    + "(<evc-per-uni-c><ce-vlan-map/><flow-mapping/><ingress-bwp-group-index/></evc-per-uni-c>)\\R?"
+                    + "(<evc-per-uni-n><ce-vlan-map/><flow-mapping/><ingress-bwp-group-index/></evc-per-uni-n>)\\R?"
+                    + "(</evc-per-uni>)\\R?"
+                    + "(</evc>)\\R?"
+                    + "(</uni>)\\R?"
+                    + "(</mef-services>)\\R?"
+                    + "(</filter>)\\R?"
+                    + "(</get-config>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    //For test testRemoveEvcUniFlowEntries()
+    private Pattern sampleXmlRegexEditConfigCeVlanMapReplace =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>).*"
+                    + "(<target><running/></target>).*"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">).*"
+                    + "(<mef-services xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">).*"
+                    + "(<uni>).*"
+                    + "(<evc nc:operation=\"delete\">).*(<evc-index>.*</evc-index>).*(</evc>).*"
+                    + "(<evc nc:operation=\"delete\">).*(<evc-index>.*</evc-index>).*(</evc>).*"
+                    + "(<evc>).*(<evc-index>).*(</evc-index>).*(<evc-per-uni>).*"
+                    + "(<evc-per-uni-c>).*"
+                    + "(<ce-vlan-map nc:operation=\"replace\">).*(</ce-vlan-map>).*"
+                    + "(<flow-mapping nc:operation=\"delete\">).*(<ce-vlan-id>).*(</ce-vlan-id>).*(</flow-mapping>).*"
+                    + "(</evc-per-uni-c>).*"
+                    + "(<evc-per-uni-n>).*"
+                    + "(<ce-vlan-map nc:operation=\"replace\">).*(</ce-vlan-map>).*"
+                    + "(<flow-mapping nc:operation=\"delete\">).*(<ce-vlan-id>).*(</ce-vlan-id>).*(</flow-mapping>).*"
+                    + "(</evc-per-uni-n>).*"
+                    + "(</evc-per-uni>).*(</evc>).*"
+                    + "(<evc>).*(<evc-index>).*(</evc-index>).*(<evc-per-uni>).*"
+                    + "(<evc-per-uni-c>).*"
+                    + "(<ce-vlan-map nc:operation=\"replace\">).*(</ce-vlan-map>).*"
+                    + "(<flow-mapping nc:operation=\"delete\">).*(<ce-vlan-id>).*(</ce-vlan-id>).*(</flow-mapping>).*"
+                    + "(</evc-per-uni-c>).*"
+                    + "(<evc-per-uni-n>).*"
+                    + "(<ce-vlan-map nc:operation=\"replace\">).*(</ce-vlan-map>).*"
+                    + "(<flow-mapping nc:operation=\"delete\">).*(<ce-vlan-id>).*(</ce-vlan-id>).*(</flow-mapping>).*"
+                    + "(</evc-per-uni-n>).*"
+                    + "(</evc-per-uni>).*(</evc>).*"
+                    + "(</uni>).*(</mef-services>).*"
+                    + "(</config>).*(</edit-config>).*(</rpc>).*(]]>){2}", Pattern.DOTALL);
+
+
+    //For testPerformMeterOperationDeviceIdMeterAdd()
+    private Pattern sampleXmlRegexEditConfigBwpGroup1 =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target>\\R?<running/>\\R?</target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-services "
+                    + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">)\\R?"
+                    + "(<profiles>)\\R?"
+                    + "(<bwp-group>)\\R?"
+                    + "(<group-index>)[0-9]*(</group-index>)\\R?"
+                    + "(<bwp>)\\R?"
+                    + "(<cos-index>)[0-9]*(</cos-index>)\\R?"
+                    + "(<name>).*(</name>)\\R?"
+                    + "(<committed-information-rate>)[0-9]*(</committed-information-rate>)\\R?"
+                    + "(<committed-burst-size>)[0-9]*(</committed-burst-size>)\\R?"
+                    + "(<excess-information-rate>)[0-9]*(</excess-information-rate>)\\R?"
+                    + "(<excess-burst-size>)[0-9]*(</excess-burst-size>)\\R?"
+                    + "(</bwp>)\\R?"
+                    + "(</bwp-group>)\\R?"
+                    + "(<cos>)\\R?"
+                    + "(<cos-index>)[0-9](</cos-index>)\\R?"
+                    + "(<name>).*(</name>)\\R?"
+                    + "(<outgoing-cos-value>)[0-9]*(</outgoing-cos-value>)\\R?"
+                    + "(<color-aware>true</color-aware>)\\R?"
+                    + "(<color-forward>true</color-forward>)\\R?"
+                    + "(<evc-cos-type-all-8-prio-to-1-evc-color>)\\R?"
+                    + "(<evc-all-8-color-to>green</evc-all-8-color-to>)\\R?"
+                    + "(</evc-cos-type-all-8-prio-to-1-evc-color>)\\R?"
+                    + "(</cos>)\\R?"
+                    + "(</profiles>)\\R?"
+                    + "(</mef-services>)\\R?"
+                    + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    //For testPerformMeterOperationDeviceIdMeterRemove()
+    private Pattern sampleXmlRegexEditConfigBwpGroup1Delete =
+    Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+            + "(<target>\\R?<running/>\\R?</target>)\\R?"
+            + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+            + "(<mef-services xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">)\\R?"
+            + "(<profiles>)\\R?"
+            + "((<bwp-group nc:operation=\"delete\">)\\R?"
+            + "(<group-index>)[0-9]*(</group-index>)\\R?"
+            + "(<bwp>.*</bwp>)?"
+            + "(</bwp-group>))++\\R?"
+            + "(</profiles>)\\R?"
+            + "(</mef-services>)\\R?"
+            + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexSetCurrentDatetime =
+    Pattern.compile("(<\\?xml).*(<rpc).*"
+            + "(<set-current-datetime xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\">)\\R?"
+            + "(<current-datetime>)"
+            + "[0-9]{4}-[0-9]{2}-[0-9]{2}(T)[0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{2}:[0-9]{2}"
+            + "(</current-datetime>)\\R?"
+            + "(</set-current-datetime>)\\R?"
+            + "(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    //For testGetConfigMseaCfmEssentials
+    private Pattern sampleXmlRegexGetMseaCfmEssentials =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "(<id/>)\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<md-level/>)\\R?"
+                    + "(<maintenance-association>)\\R?"
+                    + "(<id/>)\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<ccm-interval>)[0-9]{1,3}(ms</ccm-interval>)\\R?"
+                    + "(<remote-meps/>)\\R?"
+                    + "(<component-list/>)\\R?"
+                    + "(<maintenance-association-end-point>)\\R?"
+                    + "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
+                    + "(<interface/>)\\R?"
+                    + "(<primary-vid/>)\\R?"
+                    + "(<administrative-state/>)\\R?"
+                    + "(<ccm-ltm-priority/>)\\R?"
+                    + "(<continuity-check/>)\\R?"
+                    + "(<mac-address/>)\\R?"
+                    + "(<msea-soam-fm:port-status/>)\\R?"
+                    + "(<msea-soam-fm:interface-status/>)\\R?"
+                    + "(<msea-soam-fm:last-defect-sent/>)\\R?"
+                    + "(<msea-soam-fm:rdi-transmit-status/>)\\R?"
+                    + "(<loopback/>)\\R?"
+                    + "(<remote-mep-database/>)\\R?"
+                    + "(<linktrace/>)\\R?"
+                    + "(</maintenance-association-end-point>)\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</filter>)\\R?"
+                    + "(</get>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+
+    private static final String SAMPLE_SYSTEM_REPLY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+            + "<system xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\">\n"
+            + "<clock><timezone-name>Etc/UTC</timezone-name></clock>\n"
+            + "</system>\n"
+            + "</data>\n"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_SYSTEM_REPLY_INIT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">"
+            + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+            + "<system xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\">\n"
+            + "<longitude xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">-8.4683990</longitude>\n"
+            + "<latitude xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">51.9036140</latitude>\n"
+            + "</system>\n"
+            + "<system-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\""
+            + " xmlns:sysms=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">\n"
+            + "<platform>\n"
+            + "<os-release>4.4.0-53-generic</os-release>\n"
+            + "<sysms:device-identification>\n"
+            + "<sysms:serial-number>Eagle Simulator.</sysms:serial-number>\n"
+            + "</sysms:device-identification>\n"
+            + "</platform>\n"
+            + "</system-state>\n"
+            + "</data>"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEASAFILTERING_FE_REPLY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+            + "<source-ipaddress-filtering "
+            + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering\">\n"
+            + "<interface-eth0>\n"
+            + "<filter-admin-state>inactive</filter-admin-state>\n"
+            + "<source-address-range>\n"
+            + "<range-id>1</range-id>\n"
+            + "<ipv4-address-prefix>10.10.10.10/16</ipv4-address-prefix>\n"
+            + "<name>Filter1</name>\n"
+            + "</source-address-range>\n"
+            + "<source-address-range>\n"
+            + "<range-id>2</range-id>\n"
+            + "<ipv4-address-prefix>20.30.40.50/18</ipv4-address-prefix>\n"
+            + "<name>Flow:5e0000abaa2772</name>\n"
+            + "</source-address-range>\n"
+            + "</interface-eth0>\n"
+            + "</source-ipaddress-filtering>\n"
+            + "</data>\n"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEAEVCUNI_REPLY_INIT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+            + "<mef-services xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\"/>"
+            + "</data>\n"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEAEVCUNI_FE_REPLY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+            + "<mef-services xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">\n"
+            + "<uni>\n"
+            + "<name>Flow:7557655abfecd57865</name>\n"
+            + "<evc>\n"
+            + "<evc-index>7</evc-index\n>"
+            + "<name>evc-7</name>\n"
+            + "<evc-per-uni>\n"
+            + "<evc-per-uni-c>\n"
+            + "<ce-vlan-map>10</ce-vlan-map>\n"
+            + "<ingress-bwp-group-index>1</ingress-bwp-group-index>\n"
+            + "<tag-push>\n"
+            + "<push-tag-type>pushStag</push-tag-type>\n"
+            + "<outer-tag-vlan>3</outer-tag-vlan>\n"
+            + "</tag-push>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>10</ce-vlan-id>\n"
+            + "<flow-id>27021600672053710</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<evc-per-uni-service-type>epl</evc-per-uni-service-type>\n"
+            + "</evc-per-uni-c>\n"
+            + "<evc-per-uni-n>\n"
+            + "<ce-vlan-map>11</ce-vlan-map>\n"
+            + "<ingress-bwp-group-index>0</ingress-bwp-group-index>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>11</ce-vlan-id>\n"
+            + "<flow-id>27021600672053711</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "</evc-per-uni-n>\n"
+            + "</evc-per-uni>\n"
+            + "<uni-evc-id>EA1000-Uni-from-ONOS_5</uni-evc-id>\n"
+            + "<evc-status>\n"
+            + "<operational-state>unknown</operational-state>\n"
+            + "<max-mtu-size>9600</max-mtu-size>\n"
+            + "<max-num-uni>2</max-num-uni>\n"
+            + "</evc-status>\n"
+            + "</evc>\n"
+            + "<evc>\n"
+            + "<evc-index>8</evc-index>\n"
+            + "<name>evc-8</name>\n"
+            + "<evc-per-uni>\n"
+            + "<evc-per-uni-c>\n"
+            + "<ce-vlan-map>12:14,20:22,25</ce-vlan-map>\n"
+            + "<ingress-bwp-group-index>0</ingress-bwp-group-index>\n"
+            + "<tag-pop />\n"
+            + "<evc-per-uni-service-type>epl</evc-per-uni-service-type>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>12</ce-vlan-id>\n"
+            + "<flow-id>27021600672053712</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>13</ce-vlan-id>\n"
+            + "<flow-id>27021600672053713</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>14</ce-vlan-id>\n"
+            + "<flow-id>27021600672053714</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>20</ce-vlan-id>\n"
+            + "<flow-id>27021600672053720</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>21</ce-vlan-id>\n"
+            + "<flow-id>27021600672053721</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>22</ce-vlan-id>\n"
+            + "<flow-id>27021600672053722</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>25</ce-vlan-id>\n"
+            + "<flow-id>27021600672053725</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "</evc-per-uni-c>\n"
+            + "<evc-per-uni-n>\n"
+            + "<ce-vlan-map>13</ce-vlan-map>\n"
+            + "<ingress-bwp-group-index>0</ingress-bwp-group-index>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>13</ce-vlan-id>\n"
+            + "<flow-id>27021600672053713</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "</evc-per-uni-n>\n"
+            + "</evc-per-uni>\n"
+            + "<uni-evc-id>EA1000-Uni-from-ONOS_5</uni-evc-id>\n"
+            + "<evc-status>\n"
+            + "<operational-state>unknown</operational-state>\n"
+            + "<max-mtu-size>9600</max-mtu-size>\n"
+            + "<max-num-uni>2</max-num-uni>\n"
+            + "</evc-status>\n"
+            + "</evc>\n"
+            + "</uni>\n"
+            + "<profiles>\n"
+            + "<bwp-group>\n"
+            + "<group-index>0</group-index>\n"
+            + "</bwp-group>\n"
+            + "</profiles>\n"
+            + "</mef-services>\n"
+            + "</data>\n"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEAEVCUNI_CEVLANMAP_EVC_REPLY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+            + "<mef-services xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">\n"
+            + "<uni>\n"
+
+            + "<evc><evc-index>1</evc-index>\n"
+            + "<evc-per-uni>\n"
+            + "<evc-per-uni-c>\n"
+            + "<ce-vlan-map>101</ce-vlan-map>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>101</ce-vlan-id>\n"
+            + "<flow-id>27021598629213101</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "</evc-per-uni-c>\n"
+            + "<evc-per-uni-n>\n"
+            + "<ce-vlan-map>102</ce-vlan-map>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>102</ce-vlan-id>\n"
+            + "<flow-id>27021598629213102</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "</evc-per-uni-n>\n"
+            + "</evc-per-uni>\n"
+            + "</evc>\n"
+
+            + "<evc><evc-index>7</evc-index>\n"
+            + "<evc-per-uni>\n"
+            + "<evc-per-uni-c>\n"
+            + "<ce-vlan-map>700,710,720</ce-vlan-map>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>700</ce-vlan-id>\n"
+            + "<flow-id>27021598629213700</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>710</ce-vlan-id>\n"
+            + "<flow-id>27021598629213710</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>720</ce-vlan-id>\n"
+            + "<flow-id>27021598629213720</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "</evc-per-uni-c>\n"
+            + "<evc-per-uni-n>\n"
+            + "<ce-vlan-map>701:703</ce-vlan-map>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>701</ce-vlan-id>\n"
+            + "<flow-id>27021598629213701</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>702</ce-vlan-id>\n"
+            + "<flow-id>27021598629213702</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "<flow-mapping>\n"
+            + "<ce-vlan-id>703</ce-vlan-id>\n"
+            + "<flow-id>27021598629213703</flow-id>\n"
+            + "</flow-mapping>\n"
+            + "</evc-per-uni-n>\n"
+            + "</evc-per-uni>\n"
+            + "</evc>\n"
+
+            + "<evc><evc-index>8</evc-index>\n"
+            + "<evc-per-uni>\n"
+            + "<evc-per-uni-c>\n<ce-vlan-map>800,810,820</ce-vlan-map>\n</evc-per-uni-c>\n"
+            + "<evc-per-uni-n>\n<ce-vlan-map>801:803</ce-vlan-map>\n</evc-per-uni-n>\n"
+            + "</evc-per-uni>\n"
+            + "</evc>\n"
+
+            + "</uni>\n"
+            + "</mef-services>\n"
+            + "</data>\n"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEACFM_MD_MA_MEP_REPLY =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"47\">"
+            + "<data>"
+            + "<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" "
+            + "xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" "
+            + "xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">"
+            + "<maintenance-domain>"
+            + "<id>1</id>"
+            + "<name>md-1</name>"
+            + "<md-level>3</md-level>"
+            + "<maintenance-association>"
+            + "<id>1</id>"
+            + "<name>ma-1-1</name>"
+            + "<ccm-interval>10ms</ccm-interval>" //Causing problems on create of MA
+            + "<remote-meps>1</remote-meps>"
+            + "<remote-meps>2</remote-meps>"
+            + "<component-list>"
+            + "<vid>100</vid>"
+            + "<tag-type>vlan-stag</tag-type>"
+            + "</component-list>"
+            + "<maintenance-association-end-point>"
+            + "<mep-identifier>1</mep-identifier>"
+            + "<interface>eth1</interface>"
+            + "<primary-vid>100</primary-vid>"
+            + "<administrative-state>true</administrative-state>"
+            + "<ccm-ltm-priority>4</ccm-ltm-priority>"
+            + "<continuity-check>"
+            + "<cci-enabled>true</cci-enabled>"
+            + "<fng-state>report-defect</fng-state>"
+            + "<highest-priority-defect-found>remote-mac-error</highest-priority-defect-found>"
+            + "<active-defects> remote-mac-error invalid-ccm</active-defects>"
+            + "<last-error-ccm>U2FtcGxlIGxhc3QgZXJyb3IgY2NtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAA==</last-error-ccm>"
+            + "<ccm-sequence-error-count>10</ccm-sequence-error-count>"
+            + "<sent-ccms>15</sent-ccms>"
+            + "</continuity-check>"
+            + "<mac-address>53:65:61:6e:20:43</mac-address>"
+            + "<msea-soam-fm:port-status>no-status-tlv</msea-soam-fm:port-status>"
+            + "<msea-soam-fm:interface-status>no-status-tlv</msea-soam-fm:interface-status>"
+//            + "<msea-soam-fm:last-defect-sent/>" --Can't handle this at the moment
+            + "<msea-soam-fm:rdi-transmit-status>false</msea-soam-fm:rdi-transmit-status>"
+            + "<loopback>"
+            + "<replies-received>123</replies-received>"
+            + "<replies-transmitted>456</replies-transmitted>"
+            + "</loopback>"
+            + "<remote-mep-database>"
+            + "<remote-mep>"
+            + "<remote-mep-id>2</remote-mep-id>"
+            + "<remote-mep-state>ok</remote-mep-state>"
+            + "<failed-ok-time>1490692834</failed-ok-time>"
+            + "<mac-address>53:65:61:6e:20:43</mac-address>"
+            + "<rdi>true</rdi>"
+            + "<port-status-tlv>up</port-status-tlv>"
+            + "<interface-status-tlv>dormant</interface-status-tlv>"
+            + "</remote-mep>"
+            + "</remote-mep-database>"
+            + "<linktrace>"
+            + "<unexpected-replies-received>0</unexpected-replies-received>"
+            + "<msea-soam-fm:ltm-msgs-transmitted>2</msea-soam-fm:ltm-msgs-transmitted>"
+            + "<msea-soam-fm:ltm-msgs-received>2</msea-soam-fm:ltm-msgs-received>"
+            + "<msea-soam-fm:ltr-msgs-transmitted>2</msea-soam-fm:ltr-msgs-transmitted>"
+            + "<msea-soam-fm:ltr-msgs-received>2</msea-soam-fm:ltr-msgs-received>"
+            + "<linktrace-database/>"
+            + "</linktrace>"
+            + "</maintenance-association-end-point>"
+            + "<remote-meps>4</remote-meps>"
+            + "</maintenance-association>"
+            + "</maintenance-domain>"
+            + "</mef-cfm>"
+            + "</data>"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEACFM_MD_MA_MEP_REPLY2 =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"47\">"
+            + "<data>"
+            + "<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" "
+            + "xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" "
+            + "xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">"
+            + "<maintenance-domain>"
+            + "<id>1</id>"
+            + "<name>Microsemi</name>"
+            + "<md-level>2</md-level>"
+            + "<maintenance-association>"
+            + "<id>1</id>"
+            + "<name>example-ma</name>"
+            + "<remote-meps>1</remote-meps>"
+            + "<remote-meps>2</remote-meps>"
+            + "<component-list>"
+            + "<vid>100</vid>"
+            + "<tag-type>vlan-stag</tag-type>"
+            + "</component-list>"
+            + "<maintenance-association-end-point>"
+            + "<mep-identifier>4</mep-identifier>"
+            + "<interface>eth1</interface>"
+            + "<primary-vid>100</primary-vid>"
+            + "<administrative-state>true</administrative-state>"
+            + "<ccm-ltm-priority>4</ccm-ltm-priority>"
+            + "<continuity-check>"
+            + "<cci-enabled>true</cci-enabled>"
+            + "<fng-state>defect-reported</fng-state>"
+            + "<highest-priority-defect-found>remote-invalid-ccm</highest-priority-defect-found>"
+//            + "<active-defects> remote-invalid-ccm</active-defects>"
+            + "<active-defects/>"
+            + "<ccm-sequence-error-count>0</ccm-sequence-error-count>"
+            + "<sent-ccms>41013</sent-ccms>"
+            + "</continuity-check>"
+            + "<mac-address>00:b0:ae:03:ff:31</mac-address>"
+            + "<msea-soam-fm:port-status>up</msea-soam-fm:port-status>"
+            + "<msea-soam-fm:interface-status>up</msea-soam-fm:interface-status>"
+            + "<msea-soam-fm:rdi-transmit-status>true</msea-soam-fm:rdi-transmit-status>"
+            + "<loopback>"
+            + "<replies-received>0</replies-received>"
+            + "<replies-transmitted>0</replies-transmitted>"
+            + "</loopback>"
+            + "<remote-mep-database>"
+            + "<remote-mep>"
+            + "<remote-mep-id>1</remote-mep-id>"
+            + "<remote-mep-state>failed</remote-mep-state>"
+            + "<failed-ok-time>26315533</failed-ok-time>"
+            + "<mac-address>00:00:00:00:00:00</mac-address>"
+            + "<rdi>false</rdi>"
+            + "<port-status-tlv>no-status-tlv</port-status-tlv>"
+            + "<interface-status-tlv>no-status-tlv</interface-status-tlv>"
+            + "</remote-mep>"
+            + "<remote-mep>"
+            + "<remote-mep-id>2</remote-mep-id>"
+            + "<remote-mep-state>failed</remote-mep-state>"
+            + "<failed-ok-time>26315541</failed-ok-time>"
+            + "<mac-address>00:00:00:00:00:00</mac-address>"
+            + "<rdi>false</rdi>"
+            + "<port-status-tlv>no-status-tlv</port-status-tlv>"
+            + "<interface-status-tlv>no-status-tlv</interface-status-tlv>"
+            + "</remote-mep>"
+            + "</remote-mep-database>"
+            + "<linktrace />"
+            + "</maintenance-association-end-point>"
+            + "<remote-meps>4</remote-meps>"
+            + "</maintenance-association>"
+            + "</maintenance-domain>"
+            + "</mef-cfm>"
+            + "</data>"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_REPLY_OK = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"2\">"
+            + "<ok/>"
+            + "</rpc-reply>";
+
+    private NetconfDeviceInfo deviceInfo;
+
+    private final AtomicInteger messageIdInteger = new AtomicInteger(0);
+
+    public MockNetconfSessionEa1000(NetconfDeviceInfo deviceInfo) throws NetconfException {
+        this.deviceInfo = deviceInfo;
+    }
+
+    @Override
+    public CompletableFuture<String> request(String request) throws NetconfException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String get(String request) throws NetconfException {
+
+        return sendRequest(request);
+    }
+
+    @Override
+    public String get(String filterSchema, String withDefaultsMode) throws NetconfException {
+        StringBuilder rpc = new StringBuilder(XML_HEADER);
+        rpc.append(RPC_OPEN);
+        rpc.append(MESSAGE_ID_STRING);
+        rpc.append(EQUAL);
+        rpc.append("\"");
+        rpc.append(messageIdInteger.get());
+        rpc.append("\"  ");
+        rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
+        rpc.append(GET_OPEN).append(NEW_LINE);
+        if (filterSchema != null) {
+            rpc.append(SUBTREE_FILTER_OPEN).append(NEW_LINE);
+            rpc.append(filterSchema).append(NEW_LINE);
+            rpc.append(SUBTREE_FILTER_CLOSE).append(NEW_LINE);
+        }
+        if (withDefaultsMode != null) {
+            rpc.append(WITH_DEFAULT_OPEN).append(NETCONF_WITH_DEFAULTS_NAMESPACE).append(">");
+            rpc.append(withDefaultsMode).append(WITH_DEFAULT_CLOSE).append(NEW_LINE);
+        }
+        rpc.append(GET_CLOSE).append(NEW_LINE);
+        rpc.append(RPC_CLOSE).append(NEW_LINE);
+        rpc.append(ENDPATTERN);
+        String reply = sendRequest(rpc.toString());
+        checkReply(reply);
+        return reply;
+    }
+
+    @Override
+    public String doWrappedRpc(String request) throws NetconfException {
+        StringBuilder rpc = new StringBuilder(XML_HEADER);
+        rpc.append(RPC_OPEN);
+        rpc.append(MESSAGE_ID_STRING);
+        rpc.append(EQUAL);
+        rpc.append("\"");
+        rpc.append(messageIdInteger.get());
+        rpc.append("\"  ");
+        rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
+        rpc.append(request);
+        rpc.append(RPC_CLOSE).append(NEW_LINE);
+        rpc.append(ENDPATTERN);
+        String reply = sendRequest(rpc.toString());
+        checkReply(reply);
+        return reply;
+    }
+
+    @Override
+    public String requestSync(String request) throws NetconfException {
+        if (!request.contains(ENDPATTERN)) {
+            request = request + NEW_LINE + ENDPATTERN;
+        }
+        String reply = sendRequest(request);
+        checkReply(reply);
+        return reply;
+    }
+
+
+    @Override
+    public String getConfig(DatastoreId targetConfiguration, String configurationSchema) throws NetconfException {
+        StringBuilder rpc = new StringBuilder(XML_HEADER);
+        rpc.append("<rpc ");
+        rpc.append(MESSAGE_ID_STRING);
+        rpc.append(EQUAL);
+        rpc.append("\"");
+        rpc.append(messageIdInteger.get());
+        rpc.append("\"  ");
+        rpc.append("xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n");
+        rpc.append("<get-config>\n");
+        rpc.append("<source>\n");
+        rpc.append("<").append(targetConfiguration).append("/>");
+        rpc.append("</source>");
+        if (configurationSchema != null) {
+            rpc.append("<filter type=\"subtree\">\n");
+            rpc.append(configurationSchema).append("\n");
+            rpc.append("</filter>\n");
+        }
+        rpc.append("</get-config>\n");
+        rpc.append("</rpc>\n");
+        rpc.append(ENDPATTERN);
+        String reply = sendRequest(rpc.toString());
+        return checkReply(reply) ? reply : "ERROR " + reply;
+    }
+
+    @Override
+    public boolean editConfig(String newConfiguration) throws NetconfException {
+        return editConfig(DatastoreId.RUNNING, null, newConfiguration);
+    }
+
+    @Override
+    public boolean editConfig(DatastoreId targetConfiguration, String mode, String newConfiguration)
+            throws NetconfException {
+        newConfiguration = newConfiguration.trim();
+        StringBuilder rpc = new StringBuilder(XML_HEADER);
+        rpc.append(RPC_OPEN);
+        rpc.append(MESSAGE_ID_STRING);
+        rpc.append(EQUAL);
+        rpc.append("\"");
+        rpc.append(messageIdInteger.get());
+        rpc.append("\"  ");
+        rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
+        rpc.append(EDIT_CONFIG_OPEN).append("\n");
+        rpc.append(TARGET_OPEN);
+        rpc.append("<").append(targetConfiguration).append("/>");
+        rpc.append(TARGET_CLOSE).append("\n");
+        if (mode != null) {
+            rpc.append(DEFAULT_OPERATION_OPEN);
+            rpc.append(mode);
+            rpc.append(DEFAULT_OPERATION_CLOSE).append("\n");
+        }
+        rpc.append(CONFIG_OPEN).append("\n");
+        rpc.append(newConfiguration);
+        rpc.append(CONFIG_CLOSE).append("\n");
+        rpc.append(EDIT_CONFIG_CLOSE).append("\n");
+        rpc.append(RPC_CLOSE);
+        rpc.append(ENDPATTERN);
+        log.debug(rpc.toString());
+        String reply = sendRequest(rpc.toString());
+        return checkReply(reply);
+    }
+
+    @Override
+    public boolean copyConfig(String targetConfiguration, String newConfiguration) throws NetconfException {
+        return copyConfig(TargetConfig.valueOf(targetConfiguration), newConfiguration);
+    }
+
+    @Override
+    public void startSubscription() throws NetconfException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void startSubscription(String filterSchema) throws NetconfException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void endSubscription() throws NetconfException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean lock() throws NetconfException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean unlock() throws NetconfException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean close() throws NetconfException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public String getSessionId() {
+        return "mockSessionId";
+    }
+
+    @Override
+    public String getServerCapabilities() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setDeviceCapabilities(List<String> capabilities) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void addDeviceOutputListener(NetconfDeviceOutputEventListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeDeviceOutputListener(NetconfDeviceOutputEventListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    private boolean checkReply(String reply) throws NetconfException {
+        if (reply != null) {
+            if (!reply.contains("<rpc-error>")) {
+                log.debug("Device {} sent reply {}", deviceInfo, reply);
+                return true;
+            } else if (reply.contains("<ok/>")
+                    || (reply.contains("<rpc-error>")
+                    && reply.contains("warning"))) {
+                log.debug("Device {} sent reply {}", deviceInfo, reply);
+                return true;
+            }
+        }
+        log.warn("Device {} has error in reply {}", deviceInfo, reply);
+        return false;
+    }
+
+    private String sendRequest(String request) throws NetconfException {
+        log.info("Mocking NETCONF Session send request: \n" + request);
+
+        if (sampleXmlRegex1.matcher(request).matches()) {
+            return SAMPLE_SYSTEM_REPLY;
+
+        } else if (sampleXmlRegex2.matcher(request).matches()) {
+            return SAMPLE_SYSTEM_REPLY_INIT;
+
+        } else if (sampleXmlRegexSaFiltering.matcher(request).matches()) {
+            return SAMPLE_MSEASAFILTERING_FE_REPLY;
+
+        } else if (sampleXmlRegexEditConfigSaFilt.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexEditDeleteSaFilt.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexUniEvc.matcher(request).matches()) {
+            return SAMPLE_MSEAEVCUNI_REPLY_INIT;
+
+        } else if (sampleXmlRegexUniEvcUni.matcher(request).matches()) {
+            return SAMPLE_MSEAEVCUNI_FE_REPLY;
+
+        } else if (sampleXmlRegexEditConfigUni1Evc.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexEditConfigUni2Evc.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexEditConfigUniProfiles.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexEditConfigEvcDelete.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexGetConfigCeVlanMapsEvc.matcher(request).matches()) {
+            return SAMPLE_MSEAEVCUNI_CEVLANMAP_EVC_REPLY;
+
+        } else if (sampleXmlRegexEditConfigCeVlanMapReplace.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexEditConfigBwpGroup1.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexEditConfigBwpGroup1Delete.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexSetCurrentDatetime.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexGetMseaCfmEssentials.matcher(request).matches()) {
+            return SAMPLE_MSEACFM_MD_MA_MEP_REPLY2;
+
+        } else {
+            throw new NetconfException("MocknetconfSession. No sendRequest() case for query: " +
+                    request);
+        }
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java
new file mode 100644
index 0000000..e3a81bc
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.UncheckedIOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.drivers.microsemi.yang.impl.MseaCfmManager;
+import org.onosproject.netconf.NetconfDeviceInfo;
+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.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;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameCharacterString;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+
+public class MseaCfmManagerTest {
+
+    MseaCfmManager mseaCfmService;
+    NetconfSession session;
+
+    @Before
+    public void setUp() throws Exception {
+        try {
+            mseaCfmService = new MockMseaCfmManager();
+            mseaCfmService.activate();
+        } catch (UncheckedIOException e) {
+            fail(e.getMessage());
+        }
+        NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf", Ip4Address.valueOf("1.2.3.4"), 830);
+        session = new MockNetconfSessionEa1000(deviceInfo);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testGetConfigMseaCfmEssentials() throws NetconfException {
+        MseaCfm mseaCfm = mseaCfmService.getMepEssentials("md-1", "ma-1-1", 1, session);
+        assertNotNull(mseaCfm);
+
+        //See SAMPLE_MSEACFM_MD_MA_MEP_REPLY in MockNetconfSessionEa1000
+        assertEquals(1, mseaCfm.mefCfm().maintenanceDomain().size());
+        assertEquals(2, mseaCfm.mefCfm().maintenanceDomain().get(0).mdLevel().uint8());
+    }
+
+    /**
+     * Create the Maintenance Domain "md-1".
+     * @throws NetconfException
+     */
+    @Test
+    public void testSetMseaCfm() throws NetconfException {
+        NameCharacterString mdName = new DefaultNameCharacterString();
+        mdName.name(Identifier45.fromString("md-1"));
+
+        MaintenanceDomain yangMd = new DefaultMaintenanceDomain();
+        yangMd.id((short) 1);
+        yangMd.mdNameAndTypeCombo(mdName);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+      //FIXME implement this
+//        MseaCfmOpParam mseaCfmOpParam = (MseaCfmOpParam) MseaCfmOpParam.builder().mefCfm(mefCfm).build();
+//        mseaCfmService.setMseaCfm(mseaCfmOpParam, session, NcDsType.running);
+    }
+
+    @Test
+    public void testTransmitLoopback() throws NetconfException {
+        try {
+            mseaCfmService.transmitLoopback(null, session);
+        } catch (UnsupportedOperationException e) {
+            assertTrue(e.getMessage().contains("Not yet implemented"));
+        }
+    }
+
+    @Test
+    public void testAbortLoopback() throws NetconfException {
+        try {
+            mseaCfmService.abortLoopback(null, session);
+        } catch (UnsupportedOperationException e) {
+            assertTrue(e.getMessage().contains("Not yet implemented"));
+        }
+    }
+
+    @Test
+    public void testTransmitLinktrace() throws NetconfException {
+        try {
+            mseaCfmService.transmitLinktrace(null, session);
+        } catch (UnsupportedOperationException e) {
+            assertTrue(e.getMessage().contains("Not yet implemented"));
+        }
+    }
+
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java
new file mode 100644
index 0000000..acb6ae6
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.UncheckedIOException;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.drivers.microsemi.yang.impl.MseaSaFilteringManager;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfDeviceInfo;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.DefaultSourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.DefaultInterfaceEth0;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.InterfaceEth0;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.DefaultSourceAddressRange;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
+
+public class MseaSaFilteringManagerTest {
+
+    MseaSaFilteringManager mseaSaSvc;
+    NetconfSession session;
+
+    @Before
+    public void setUp() throws Exception {
+        try {
+            mseaSaSvc = new MockMseaSaFilteringManager();
+            mseaSaSvc.activate();
+        } catch (UncheckedIOException e) {
+            fail(e.getMessage());
+        }
+        NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf", Ip4Address.valueOf("1.2.3.4"), 830);
+        session = new MockNetconfSessionEa1000(deviceInfo);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testGetMseaSaFilteringMseaSaFilteringOpParamNetconfSession() throws NetconfException {
+        SourceIpaddressFiltering sip = new DefaultSourceIpaddressFiltering();
+
+        MseaSaFilteringOpParam op = new MseaSaFilteringOpParam();
+        op.sourceIpaddressFiltering(sip);
+
+        MseaSaFiltering result = mseaSaSvc.getMseaSaFiltering(op, session);
+
+        //Results come from MockNetconfSession SAMPLE_MSEASAFILTERING_REPLY_INIT
+        assertNotNull(result.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange());
+        List<SourceAddressRange> ranges = result.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
+        assertEquals(2, ranges.size());
+
+        for (SourceAddressRange sa:ranges) {
+            if (sa.rangeId() == 1) {
+                assertEquals("10.10.10.10/16", sa.ipv4AddressPrefix());
+
+            } else if (sa.rangeId() == 2) {
+                assertEquals("20.30.40.50/18", sa.ipv4AddressPrefix());
+            }
+        }
+    }
+
+    @Test
+    public void testSetMseaSaFilteringMseaSaFilteringOpParamNetconfSessionNcDsType() {
+
+        MseaSaFilteringOpParam mseaSaFilteringConfig =
+                createConfigForEdit("192.168.60.10/27", (short) 3, "Filter3");
+
+        //Calling on the edit-config just makes the change and hopefully does not throw a Netconf Exception
+        try {
+            mseaSaSvc.setMseaSaFiltering(mseaSaFilteringConfig, session, DatastoreId.RUNNING);
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF Exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void testDeleteMseaSaFilteringMseaSaFilteringOpParamNetconfSessionNcDsType() {
+
+        MseaSaFilteringOpParam mseaSaFilteringConfig =
+                createConfigForEdit("192.168.60.10/27", (short) 3, "Filter3");
+
+        SourceAddressRange sar2 = new DefaultSourceAddressRange();
+        sar2.ipv4AddressPrefix("10.205.86.10/27");
+        sar2.rangeId((short) 4);
+        sar2.name("Filter4");
+
+        mseaSaFilteringConfig.sourceIpaddressFiltering().interfaceEth0()
+                .addToSourceAddressRange(sar2);
+
+        //Calling on the edit-config just makes the change and hopefully does not throw a Netconf Exception
+        try {
+            mseaSaSvc.deleteMseaSaFilteringRange(mseaSaFilteringConfig, session, DatastoreId.RUNNING);
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF Exception: " + e.getMessage());
+        }
+    }
+
+    /**
+     * This is also called from the test case EA1000FlowRuleProgrammableTest().
+     * In the ea1000driver project
+     * @return
+     */
+    public static MseaSaFilteringOpParam createConfigForEdit(String ipAddrPrefix, short rangeId, String rangeName) {
+        SourceAddressRange sar = new DefaultSourceAddressRange();
+        sar.ipv4AddressPrefix(ipAddrPrefix);
+        sar.rangeId(rangeId);
+        sar.name(rangeName);
+
+        InterfaceEth0 eth0 = new DefaultInterfaceEth0();
+        eth0.addToSourceAddressRange(sar);
+
+        SourceIpaddressFiltering sip = new DefaultSourceIpaddressFiltering();
+        sip.interfaceEth0(eth0);
+
+        MseaSaFilteringOpParam op = new MseaSaFilteringOpParam();
+        op.sourceIpaddressFiltering(sip);
+
+        return op;
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java
new file mode 100644
index 0000000..8d8b2bd
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java
@@ -0,0 +1,496 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.drivers.microsemi.yang.impl.MseaUniEvcServiceManager;
+import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfDeviceInfo;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.VlanIdType;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.EvcPerUniServiceTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPush;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.tagpush.tagpush.PushTagTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPush;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultUni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Uni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.Cos;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultCos;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.Bwp;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.DefaultBwp;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.bwp.ColorModeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.DefaultEvc;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.Evc;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.DefaultEvcPerUni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.EvcPerUni;
+import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnic;
+import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnin;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin;
+
+public class MseaUniEvcServiceManagerTest {
+
+    MseaUniEvcServiceManager mseaUniEvcServiceSvc;
+    NetconfSession session;
+
+    @Before
+    public void setUp() throws Exception {
+        try {
+            mseaUniEvcServiceSvc = new MockMseaUniEvcServiceManager();
+            mseaUniEvcServiceSvc.activate();
+        } catch (UncheckedIOException e) {
+            fail(e.getMessage());
+        }
+        NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf", Ip4Address.valueOf("1.2.3.4"), 830);
+        session = new MockNetconfSessionEa1000(deviceInfo);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testGetMseaUniEvcServiceMseaUniEvcServiceOpParamNetconfSession() {
+        MefServices mefServices = new DefaultMefServices();
+        mefServices.uni(new DefaultUni());
+
+        MseaUniEvcServiceOpParam evcUni = new MseaUniEvcServiceOpParam();
+        evcUni.mefServices(mefServices);
+
+        MseaUniEvcService result = null;
+        try {
+            result =
+                    mseaUniEvcServiceSvc.getConfigMseaUniEvcService(
+                            evcUni, session, DatastoreId.RUNNING);
+        } catch (NetconfException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            fail("Error: " + e.getMessage());
+        }
+
+        assertNotNull(result);
+    }
+
+    @Test
+    public void testSetMseaUniEvcServiceMseaUniEvcServiceOpParamEvcs() {
+      TagPush tp1 = new DefaultTagPush();
+      org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
+              .evcperuniextensionattributes.tagmanipulation
+          .tagpush.TagPush tpInner1 =
+              new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
+                      .mseaunievcservice.evcperuniextensionattributes
+                  .tagmanipulation.tagpush.DefaultTagPush();
+      tpInner1.outerTagVlan(new VlanIdType(3));
+      tpInner1.pushTagType(PushTagTypeEnum.PUSHSTAG);
+      tp1.tagPush(tpInner1);
+
+      EvcPerUnin epun1 = new CustomEvcPerUnin();
+      epun1.evcPerUniServiceType(EvcPerUniServiceTypeEnum.EVPL);
+      epun1.ceVlanMap(ServiceListType.fromString("10"));
+      epun1.ingressBwpGroupIndex("0");
+      epun1.tagManipulation(tp1);
+
+      EvcPerUnic epuc1 = new CustomEvcPerUnic();
+      epuc1.ceVlanMap(new ServiceListType("11"));
+      epuc1.ingressBwpGroupIndex("0");
+
+      EvcPerUni epu1 = new DefaultEvcPerUni();
+      epu1.evcPerUnic(epuc1);
+      epu1.evcPerUnin(epun1);
+
+      List<Evc> evcList = new ArrayList<Evc>();
+      Evc evc1 = new DefaultEvc();
+      evc1.evcIndex(1);
+      evc1.name(new Identifier45("evc-1"));
+      evc1.evcPerUni(epu1);
+
+      evcList.add(evc1);
+
+
+      EvcPerUnin epun2 = new CustomEvcPerUnin();
+      epun2.ceVlanMap(ServiceListType.fromString("13"));
+      epun2.ingressBwpGroupIndex("0");
+
+      EvcPerUnic epuc2 = new CustomEvcPerUnic();
+      epuc2.ceVlanMap(new ServiceListType("12"));
+      epuc2.ingressBwpGroupIndex("0");
+
+      EvcPerUni epu2 = new DefaultEvcPerUni();
+      epu2.evcPerUnic(epuc2);
+      epu2.evcPerUnin(epun2);
+
+      Evc evc2 = new DefaultEvc();
+      evc2.evcIndex(2);
+      evc2.name(new Identifier45("evc-2"));
+      evc2.evcPerUni(epu2);
+
+      evcList.add(evc2);
+
+      Uni uni = new DefaultUni();
+      uni.name(new Identifier45("testUni"));
+      uni.evc(evcList);
+
+      MefServices mefServices = new DefaultMefServices();
+      mefServices.uni(uni);
+
+      MseaUniEvcServiceOpParam evcUni = new MseaUniEvcServiceOpParam();
+      evcUni.mefServices(mefServices);
+      try {
+          mseaUniEvcServiceSvc.setMseaUniEvcService(evcUni, session, DatastoreId.RUNNING);
+      } catch (NetconfException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+          fail("Error: " + e.getMessage());
+      }
+    }
+
+    @Test
+    public void testSetMseaUniEvcServiceMseaUniEvcServiceOpParamProfiles() {
+      List<Cos> cosList = new ArrayList<Cos>();
+      Cos cos0 = new DefaultCos();
+      cos0.cosIndex(0);
+      cos0.name("cos0");
+      cosList.add(cos0);
+
+      Cos cos1 = new DefaultCos();
+      cos1.cosIndex(1);
+      cos1.name("cos1");
+      cosList.add(cos1);
+
+      List<BwpGroup> bwpGroupList = new ArrayList<BwpGroup>();
+      BwpGroup bwpGrp = new DefaultBwpGroup();
+      bwpGrp.groupIndex((short) 0);
+      bwpGroupList.add(bwpGrp);
+
+      List<Bwp> bwpList = new ArrayList<Bwp>();
+      Bwp bwp1 = new DefaultBwp();
+      bwp1.cosIndex(0);
+      bwp1.colorMode(ColorModeEnum.COLORAWARE);
+      bwpList.add(bwp1);
+
+      Bwp bwp2 = new DefaultBwp();
+      bwp2.cosIndex(1);
+      bwp2.colorMode(ColorModeEnum.COLORBLIND);
+      bwpList.add(bwp2);
+
+      BwpGroup bwpGrp1 = new DefaultBwpGroup();
+      bwpGrp1.groupIndex((short) 1);
+      bwpGrp1.bwp(bwpList);
+      bwpGroupList.add(bwpGrp1);
+
+      Profiles profiles = new DefaultProfiles();
+      profiles.bwpGroup(bwpGroupList);
+
+      MefServices mefServices = new DefaultMefServices();
+      mefServices.profiles(profiles);
+
+      MseaUniEvcServiceOpParam evcUni = new MseaUniEvcServiceOpParam();
+      evcUni.mefServices(mefServices);
+      try {
+          mseaUniEvcServiceSvc.setMseaUniEvcService(evcUni, session, DatastoreId.RUNNING);
+      } catch (NetconfException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+          fail("Error: " + e.getMessage());
+      }
+    }
+
+    @Test
+    public void testDeleteMseaUniEvcServiceMseaUniEvcServiceOpParamProfiles() {
+        List<Cos> cosList = new ArrayList<Cos>();
+        Cos cos0 = new DefaultCos();
+        cos0.cosIndex(0);
+        cos0.name("cos0");
+        cosList.add(cos0);
+
+        Cos cos1 = new DefaultCos();
+        cos1.cosIndex(1);
+        cos1.name("cos1");
+        cosList.add(cos1);
+
+        List<BwpGroup> bwpGroupList = new ArrayList<BwpGroup>();
+        BwpGroup bwpGrp = new DefaultBwpGroup();
+        bwpGrp.groupIndex((short) 0);
+        bwpGroupList.add(bwpGrp);
+
+        List<Bwp> bwpList = new ArrayList<Bwp>();
+        Bwp bwp1 = new DefaultBwp();
+        bwp1.cosIndex(0);
+        bwp1.colorMode(ColorModeEnum.COLORAWARE);
+        bwpList.add(bwp1);
+
+        Bwp bwp2 = new DefaultBwp();
+        bwp2.cosIndex(1);
+        bwp2.colorMode(ColorModeEnum.COLORBLIND);
+        bwpList.add(bwp2);
+
+        BwpGroup bwpGrp1 = new DefaultBwpGroup();
+        bwpGrp1.groupIndex((short) 1);
+        bwpGrp1.bwp(bwpList);
+        bwpGroupList.add(bwpGrp1);
+
+        Profiles profiles = new DefaultProfiles();
+        profiles.bwpGroup(bwpGroupList);
+
+        MefServices mefServices = new DefaultMefServices();
+        mefServices.profiles(profiles);
+
+        MseaUniEvcServiceOpParam evcUni = new MseaUniEvcServiceOpParam();
+        evcUni.mefServices(mefServices);
+        try {
+            mseaUniEvcServiceSvc.deleteMseaUniEvcService(evcUni, session, DatastoreId.RUNNING);
+        } catch (NetconfException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            fail("Error: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void testGetMseaUniEvcCeVlanMaps() {
+
+        try {
+            MseaUniEvcService ceVlanMapsResult7 =
+                    mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING);
+
+            assertNotNull(ceVlanMapsResult7.mefServices().uni().evc());
+
+            List<Evc> evcList = ceVlanMapsResult7.mefServices().uni().evc();
+            assertEquals(3, evcList.size());
+            for (Evc evc : evcList) {
+               assertNotNull(evc.evcPerUni().evcPerUnic().ceVlanMap());
+               assertNotNull(evc.evcPerUni().evcPerUnin().ceVlanMap());
+
+               if (evc.evcIndex() == 7) {
+                   assertEquals("700,710,720", evc.evcPerUni().evcPerUnic().ceVlanMap().string());
+                   assertEquals("701:703", evc.evcPerUni().evcPerUnin().ceVlanMap().string());
+               }
+            }
+
+        } catch (NetconfException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            fail("Error: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void testChangeEvcCeVlanMap() {
+        EvcPerUnin epun1 = new CustomEvcPerUnin();
+        epun1.evcPerUniServiceType(EvcPerUniServiceTypeEnum.EVPL);
+        epun1.ceVlanMap(ServiceListType.fromString("10"));
+        epun1.ingressBwpGroupIndex("0");
+
+        EvcPerUnic epuc1 = new CustomEvcPerUnic();
+        epuc1.ceVlanMap(new ServiceListType("11"));
+        epuc1.ingressBwpGroupIndex("0");
+
+        EvcPerUni epu = new DefaultEvcPerUni();
+        epu.evcPerUnic(epuc1);
+        epu.evcPerUnin(epun1);
+
+        Evc evc = new DefaultEvc();
+        evc.evcPerUni(epu);
+
+        assertEquals("10", evc.evcPerUni().evcPerUnin().ceVlanMap().string());
+        assertEquals("11", evc.evcPerUni().evcPerUnic().ceVlanMap().string());
+
+        assertEquals("11", evc.evcPerUni().evcPerUnic().ceVlanMap().string());
+    }
+
+    @Test
+    public void testChangeEvcCeVlanMapNoValues() {
+        EvcPerUnin epun1 = new CustomEvcPerUnin();
+        epun1.evcPerUniServiceType(EvcPerUniServiceTypeEnum.EVPL);
+        epun1.ingressBwpGroupIndex("0");
+
+        EvcPerUnic epuc1 = new CustomEvcPerUnic();
+        epuc1.ingressBwpGroupIndex("0");
+
+        EvcPerUni epu = new DefaultEvcPerUni();
+        epu.evcPerUnic(epuc1);
+        epu.evcPerUnin(epun1);
+
+        Evc evc = new DefaultEvc();
+        evc.evcIndex(1);
+        evc.evcPerUni(epu);
+
+        assertEquals("0", evc.evcPerUni().evcPerUnin().ceVlanMap().string());
+        assertEquals("0", evc.evcPerUni().evcPerUnic().ceVlanMap().string());
+    }
+
+    @Test
+    public void testRemoveEvcUniFlowEntries() {
+
+        Map<Integer, String> ceVlanUpdates = new TreeMap<>();
+        ceVlanUpdates.put((1 << 2), "");
+        ceVlanUpdates.put((1 << 2) + 1, "");
+        ceVlanUpdates.put((2 << 2), "");
+        ceVlanUpdates.put((2 << 2) + 1, "");
+
+        ceVlanUpdates.put((7 << 2), "700,710,720");
+        ceVlanUpdates.put((7 << 2) + 1, "701:703");
+        ceVlanUpdates.put((8 << 2), "800,810,820");
+        ceVlanUpdates.put((8 << 2) + 1, "801,802,803");
+
+        Map<Integer, List<Short>> flowVlanIdMap = new HashMap<>();
+        //These should get ignored because whole EVC is being deleted
+        flowVlanIdMap.put(1 << 2, new ArrayList<Short>());
+        flowVlanIdMap.get(1 << 2).add((short) 11);
+
+        flowVlanIdMap.put((1 << 2) + 1, new ArrayList<Short>());
+        flowVlanIdMap.get((1 << 2) + 1).add((short) 12L);
+
+        //These are the EVCs being removed
+        flowVlanIdMap.put(7 << 2, new ArrayList<Short>());
+        flowVlanIdMap.get(7 << 2).add((short) 730L);
+        flowVlanIdMap.get(7 << 2).add((short) 740L);
+
+        flowVlanIdMap.put((7 << 2) + 1, new ArrayList<Short>());
+        flowVlanIdMap.get((7 << 2) + 1).add((short) 705L);
+        flowVlanIdMap.get((7 << 2) + 1).add((short) 706L);
+
+        flowVlanIdMap.put(8 << 2, new ArrayList<Short>());
+        flowVlanIdMap.get(8 << 2).add((short) 830L);
+        flowVlanIdMap.get(8 << 2).add((short) 840L);
+
+        flowVlanIdMap.put((8 << 2) + 1, new ArrayList<Short>());
+        flowVlanIdMap.get((8 << 2) + 1).add((short) 805L);
+        flowVlanIdMap.get((8 << 2) + 1).add((short) 806L);
+
+        try {
+            mseaUniEvcServiceSvc.removeEvcUniFlowEntries(
+                    ceVlanUpdates, flowVlanIdMap, session, DatastoreId.RUNNING,
+                    UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS);
+        } catch (NetconfException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            fail("Error: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void testGetVlanSet1() {
+        Short[] vlanIds = CeVlanMapUtils.getVlanSet("10");
+        assertEquals(1, vlanIds.length);
+    }
+
+    @Test
+    public void testGetVlanSet2() {
+        Short[] vlanIds = CeVlanMapUtils.getVlanSet("10:20");
+        assertEquals(11, vlanIds.length);
+        assertEquals(10, vlanIds[0].shortValue());
+        assertEquals(20, vlanIds[10].shortValue());
+    }
+
+    @Test
+    public void testGetVlanSet3() {
+        Short[] vlanIds = CeVlanMapUtils.getVlanSet("10:20,30:40");
+        assertEquals(22, vlanIds.length);
+        assertEquals(10, vlanIds[0].shortValue());
+        assertEquals(40, vlanIds[21].shortValue());
+    }
+
+    @Test
+    public void testGetVlanSet4() {
+        Short[] vlanIds = CeVlanMapUtils.getVlanSet("10,20,30");
+        assertEquals(3, vlanIds.length);
+        assertEquals(10, vlanIds[0].shortValue());
+        assertEquals(30, vlanIds[2].shortValue());
+    }
+
+    @Test
+    public void testVlanListAsString() {
+        assertEquals("20:22", CeVlanMapUtils.vlanListAsString(new Short[]{20, 21, 22}));
+
+        assertEquals("20:22,24:25",
+                CeVlanMapUtils.vlanListAsString(new Short[]{20, 21, 22, 24, 25}));
+
+        assertEquals("30,33,36:40",
+                CeVlanMapUtils.vlanListAsString(new Short[]{30, 33, 36, 37, 38, 39, 40}));
+
+        assertEquals("20", CeVlanMapUtils.vlanListAsString(new Short[]{20}));
+
+        assertEquals("20,22,24,26,28",
+                CeVlanMapUtils.vlanListAsString(new Short[]{20, 22, 24, 26, 28}));
+    }
+
+    @Test
+    public void testAddtoCeVlanMap() {
+        assertEquals("20,22:24,26,28",
+                CeVlanMapUtils.addtoCeVlanMap("20,22,24,26,28", (short) 23));
+
+        assertEquals("20:26,28",
+                CeVlanMapUtils.addtoCeVlanMap("20,21,22,24,25,26,28", (short) 23));
+
+        assertEquals("20,23",
+                CeVlanMapUtils.addtoCeVlanMap("20", (short) 23));
+
+        assertEquals("20,22:23",
+                CeVlanMapUtils.addtoCeVlanMap("20,22", (short) 23));
+    }
+
+    @Test
+    public void testCombineVlanSets() {
+        assertEquals("10:11,13:14", CeVlanMapUtils.combineVlanSets("10:11", "13:14"));
+
+        assertEquals("10:14", CeVlanMapUtils.combineVlanSets("10:11", "12:14"));
+
+        assertEquals("10:11,14", CeVlanMapUtils.combineVlanSets("10:11", "14"));
+
+        assertEquals("10:12", CeVlanMapUtils.combineVlanSets("10:11", "11:12"));
+    }
+
+    @Test
+    public void testRemoveZeroIfPossible() {
+        assertEquals("0", CeVlanMapUtils.removeZeroIfPossible(""));
+
+        assertEquals("0", CeVlanMapUtils.removeZeroIfPossible("0"));
+
+        assertEquals("1,3", CeVlanMapUtils.removeZeroIfPossible("0:1,3"));
+
+        assertEquals("1:2", CeVlanMapUtils.removeZeroIfPossible("0:2"));
+
+        assertEquals("10:12", CeVlanMapUtils.removeZeroIfPossible("0,10:12"));
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/package-info.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/package-info.java
new file mode 100644
index 0000000..4173ece
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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 for Microsemi device drivers support for NETCONF for EA1000.
+ */
+package org.onosproject.drivers.microsemi.yang;
\ No newline at end of file
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java
new file mode 100644
index 0000000..da0954f
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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 static org.junit.Assert.assertEquals;
+
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.DateAndTime;
+
+public class IetfYangTypesUtilsTest {
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testFromYangDateTime() {
+        OffsetDateTime odt = IetfYangTypesUtils.fromYangDateTime(DateAndTime.fromString("2015-07-08T12:49:20.9Z"));
+        assertEquals(OffsetDateTime.of(2015, 7, 8, 12, 49, 20, 900000000, ZoneOffset.UTC), odt);
+    }
+
+    @Test
+    public void testFromYangDateTimeZoned() {
+        ZonedDateTime zdt = IetfYangTypesUtils.fromYangDateTimeZoned(DateAndTime.fromString("2015-07-08T12:49:20.9Z"),
+                ZoneId.systemDefault());
+
+        assertEquals(OffsetDateTime.of(2015, 7, 8, 12, 49, 20, 900000000, ZoneOffset.UTC).toInstant(),
+                zdt.toOffsetDateTime().toInstant());
+    }
+
+    @Test
+    public void testFromYangDateTimeToLocal() {
+        LocalDateTime ldt = IetfYangTypesUtils
+                .fromYangDateTimeToLocal(DateAndTime.fromString("2015-07-08T12:49:20.9Z"));
+
+        OffsetDateTime odtExpected = OffsetDateTime.of(2015, 7, 8, 12, 49, 20, 900000000, ZoneOffset.UTC);
+        ZoneOffset offsetForcurrentZone = ZoneId.systemDefault().getRules().getOffset(ldt);
+        assertEquals(odtExpected.toInstant(), ldt.toInstant(offsetForcurrentZone));
+    }
+
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java b/drivers/microsemi/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java
new file mode 100644
index 0000000..e2f4389
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.yang;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.CoreService;
+import org.onosproject.drivers.netconf.MockCoreService;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaContext;
+import org.onosproject.yang.model.SchemaContextProvider;
+import org.onosproject.yang.model.YangModel;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.CompositeStream;
+import org.onosproject.yang.runtime.ModelRegistrationParam;
+import org.onosproject.yang.runtime.RuntimeContext;
+import org.onosproject.yang.runtime.YangModelRegistry;
+import org.onosproject.yang.runtime.YangRuntimeService;
+import org.onosproject.yang.runtime.YangSerializer;
+import org.onosproject.yang.runtime.YangSerializerRegistry;
+import org.onosproject.yang.runtime.impl.DefaultModelConverter;
+import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry;
+import org.onosproject.yang.runtime.impl.DefaultYangRuntimeHandler;
+import org.onosproject.yang.runtime.impl.DefaultYangSerializerRegistry;
+import org.onosproject.yang.serializers.json.JsonSerializer;
+import org.onosproject.yang.serializers.xml.XmlSerializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class MockYangRuntimeManager implements YangModelRegistry,
+            YangSerializerRegistry, YangRuntimeService, ModelConverter,
+            SchemaContextProvider {
+
+        private static final String APP_ID = "org.onosproject.yang";
+        private final Logger log = LoggerFactory.getLogger(getClass());
+
+        @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+        protected CoreService coreService;
+
+        private DefaultYangModelRegistry modelRegistry;
+        private DefaultYangSerializerRegistry serializerRegistry;
+        private DefaultYangRuntimeHandler runtimeService;
+        private DefaultModelConverter modelConverter;
+
+        public void setModelRegistry(DefaultYangModelRegistry yReg) {
+            this.modelRegistry = yReg;
+        }
+
+        @Activate
+        public void activate() {
+            coreService = new MockCoreService();
+            coreService.registerApplication(APP_ID);
+            serializerRegistry = new DefaultYangSerializerRegistry();
+            runtimeService =
+                    new DefaultYangRuntimeHandler(serializerRegistry, modelRegistry);
+            serializerRegistry.registerSerializer(new JsonSerializer());
+            serializerRegistry.registerSerializer(new XmlSerializer());
+            modelConverter = new DefaultModelConverter(modelRegistry);
+            log.info("Started");
+        }
+
+        @Deactivate
+        public void deactivate() {
+            log.info("Stopped");
+        }
+
+
+        @Override
+        public void registerModel(ModelRegistrationParam p) {
+            modelRegistry.registerModel(p);
+        }
+
+        @Override
+        public void unregisterModel(ModelRegistrationParam p) {
+            modelRegistry.unregisterModel(p);
+        }
+
+        @Override
+        public Set<YangModel> getModels() {
+            return modelRegistry.getModels();
+        }
+
+        @Override
+        public void registerSerializer(YangSerializer ys) {
+            serializerRegistry.registerSerializer(ys);
+        }
+
+        @Override
+        public void unregisterSerializer(YangSerializer ys) {
+            serializerRegistry.unregisterSerializer(ys);
+        }
+
+        @Override
+        public Set<YangSerializer> getSerializers() {
+            return serializerRegistry.getSerializers();
+        }
+
+        @Override
+        public CompositeData decode(CompositeStream cs, RuntimeContext rc) {
+            return runtimeService.decode(cs, rc);
+        }
+
+        @Override
+        public CompositeStream encode(CompositeData cd, RuntimeContext rc) {
+            return runtimeService.encode(cd, rc);
+        }
+
+        @Override
+        public ModelObjectData createModel(ResourceData resourceData) {
+            return modelConverter.createModel(resourceData);
+        }
+
+        @Override
+        public ResourceData createDataNode(ModelObjectData modelObjectData) {
+            return modelConverter.createDataNode(modelObjectData);
+        }
+
+        @Override
+        public SchemaContext getSchemaContext(ResourceId resourceId) {
+            checkNotNull(resourceId, " resource id can't be null.");
+            NodeKey key = resourceId.nodeKeys().get(0);
+            if (resourceId.nodeKeys().size() == 1 &&
+                    "/".equals(key.schemaId().name())) {
+                return modelRegistry;
+            }
+            log.info("To be implemented.");
+            return null;
+        }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java b/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
new file mode 100644
index 0000000..dab269d
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.yang.serializers.xml;
+
+
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.model.YangModel;
+import org.onosproject.yang.runtime.AppModuleInfo;
+import org.onosproject.yang.runtime.DefaultAppModuleInfo;
+import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
+import org.onosproject.yang.runtime.ModelRegistrationParam;
+import org.onosproject.yang.runtime.YangModelRegistry;
+import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.onosproject.yang.compiler.datamodel.utils.DataModelUtils;
+import org.onosproject.yang.compiler.utils.UtilConstants;
+import org.onosproject.yang.compiler.utils.io.impl.YangIoUtils;
+import org.onosproject.yang.runtime.helperutils.YangApacheUtils;
+import org.onosproject.yang.runtime.RuntimeHelper;
+
+public class MockYangSchemaNodeProvider {
+
+    private static final String FS = File.separator;
+    private static final String PATH = System.getProperty("user.dir") +
+            FS + "buck-out" + FS + "gen" +
+            FS + "models" + FS + "microsemi" + FS + "onos-models-microsemi-schema" + FS;
+    private static final String SER_FILE_PATH = "yang" + FS + "resources" +
+            FS + "YangMetaData.ser";
+    private static final String META_PATH =
+            PATH.replace("drivers/microsemi", "")
+            + SER_FILE_PATH;
+    private static final String TEMP_FOLDER_PATH = PATH + UtilConstants.TEMP;
+    private YangModelRegistry reg = new DefaultYangModelRegistry();
+    private List<YangNode> nodes = new ArrayList<>();
+
+    /**
+     * Creates an instance of mock bundle context.
+     */
+    public MockYangSchemaNodeProvider() {
+    }
+
+    /**
+     * Process YANG schema node for a application.
+     */
+    public void processSchemaRegistry() {
+        try {
+            //Need to deserialize generated meta data file for unit tests.
+            Set<YangNode> appNode = DataModelUtils.deSerializeDataModel(META_PATH);
+            RuntimeHelper.addLinkerAndJavaInfo(appNode);
+            nodes.addAll(appNode);
+            reg.registerModel(prepareParam(nodes));
+            YangIoUtils.deleteDirectory(TEMP_FOLDER_PATH);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("YangMetaData.ser could not " +
+                    "be loaded from " + META_PATH, e);
+        }
+    }
+
+    /**
+     * Unregister given nodes from runtime service.
+     *
+     * @param nodes list of nodes
+     */
+    public void unRegister(List<YangNode> nodes) {
+        reg.unregisterModel(prepareParam(nodes));
+    }
+
+    /**
+     * Prepares model registration parameter.
+     *
+     * @param nodes list of nodes
+     * @return model registration parameter
+     */
+    private ModelRegistrationParam prepareParam(List<YangNode> nodes) {
+        //Process loading class file.
+        String appName;
+        ClassLoader classLoader = getClass().getClassLoader();
+
+        //Create model registration param.
+        ModelRegistrationParam.Builder b =
+                DefaultModelRegistrationParam.builder();
+
+        //create a new YANG model
+        YangModel model = YangApacheUtils.processYangModel(META_PATH, nodes);
+        //set YANG model
+        b.setYangModel(model);
+
+        Iterator<YangNode> it = nodes.iterator();
+        while (it.hasNext()) {
+            YangSchemaNode node = it.next();
+
+            //If service class is not generated then use
+            // interface file to load this class.
+            appName = RuntimeHelper.getInterfaceClassName(node);
+            Class<?> cls;
+            try {
+                cls = classLoader.loadClass(appName);
+            } catch (ClassNotFoundException e) {
+                continue;
+            }
+
+            //generate app info.
+            AppModuleInfo info = new DefaultAppModuleInfo(cls, null);
+            b.addAppModuleInfo(YangApacheUtils.processModuleId((YangNode) node), info);
+        }
+        return b.build();
+    }
+
+    /**
+     * Returns schema registry.
+     *
+     * @return schema registry
+     */
+    public DefaultYangModelRegistry registry() {
+        return (DefaultYangModelRegistry) reg;
+    }
+}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java b/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java
new file mode 100644
index 0000000..cfe7b9b
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.yang.serializers.xml;
+
+import org.onosproject.yang.model.SchemaContext;
+import org.onosproject.yang.runtime.Annotation;
+import org.onosproject.yang.runtime.DefaultAnnotation;
+import org.onosproject.yang.runtime.YangSerializerContext;
+import org.onosproject.yang.runtime.impl.DefaultYangModelRegistry;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class MockYangSerializerContext implements YangSerializerContext {
+
+    private static MockYangSchemaNodeProvider schemaProvider =
+            new MockYangSchemaNodeProvider();
+    private static final String NETCONF_NS =
+            "urn:ietf:params:xml:ns:netconf:base:1.0";
+    private static final String XMNLS_NC = "xmlns:xc";
+
+
+    @Override
+    public SchemaContext getContext() {
+        schemaProvider.processSchemaRegistry();
+        DefaultYangModelRegistry registry = schemaProvider.registry();
+        return registry;
+    }
+
+    @Override
+    public List<Annotation> getProtocolAnnotations() {
+        Annotation annotation = new DefaultAnnotation(XMNLS_NC, NETCONF_NS);
+        List<Annotation> protocolAnnotation = new LinkedList<>();
+        protocolAnnotation.add(annotation);
+        return protocolAnnotation;
+    }
+}
diff --git a/drivers/microsemi/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt b/drivers/microsemi/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt
new file mode 100644
index 0000000..04db8030
--- /dev/null
+++ b/drivers/microsemi/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt
@@ -0,0 +1,85 @@
+onos> ce-evc-list
+CarrierEthernetVirtualConnection{
+    id=EP-Line-1, cfgId=evpl1, type=POINT_TO_POINT, state=ACTIVE,
+    UNIs=[
+        CarrierEthernetUni{
+            id=netconf:192.168.56.10:830/0,
+            cfgId=netconf:192.168.56.10:830/0,
+            role=Root,
+            refCount=0,
+            ceVlanIds=[100],
+            capacity=1000000000,
+            usedCapacity=3.0E8,
+            bandwidthProfiles=[
+                CarrierEthernetBandwidthProfile{
+                    id=FC-1,
+                    type=EVC,
+                    cir=3.0E8,
+                    cbs=2000,
+                    eir=0.0,
+                    ebs=0}]},
+        CarrierEthernetUni{
+            id=netconf:192.168.56.20:830/0,
+            cfgId=netconf:192.168.56.20:830/0,
+            role=Root,
+            refCount=0,
+            ceVlanIds=[100],
+            capacity=1000000000,
+            usedCapacity=3.0E8,
+            bandwidthProfiles=[
+                CarrierEthernetBandwidthProfile{
+                    id=FC-1,
+                    type=EVC,
+                    cir=3.0E8,
+                    cbs=2000,
+                    eir=0.0,
+                    ebs=0}]}],
+    FCs=[
+        CarrierEthernetForwardingConstruct{
+            id=FC-1,
+            cfgId=null,
+            type=POINT_TO_POINT,
+            vlanId=1,
+            metroConnectId=null,
+            refCount=1,
+            LTPs=[
+                CarrierEthernetLogicalTerminationPoint{
+                    id=netconf:192.168.56.10:830/0,
+                    cfgId=netconf:192.168.56.10:830/0,
+                    role=Root,
+                    ni=CarrierEthernetUni{
+                        id=netconf:192.168.56.10:830/0,
+                        cfgId=netconf:192.168.56.10:830/0,
+                        role=Root,
+                        refCount=0,
+                        ceVlanIds=[100],
+                        capacity=1000000000,
+                        usedCapacity=3.0E8,
+                        bandwidthProfiles=[
+                            CarrierEthernetBandwidthProfile{
+                                id=FC-1,
+                                type=EVC,
+                                cir=3.0E8,
+                                cbs=2000,
+                                eir=0.0,
+                                ebs=0}]}},
+                CarrierEthernetLogicalTerminationPoint{
+                    id=netconf:192.168.56.20:830/0,
+                    cfgId=netconf:192.168.56.20:830/0,
+                    role=Root,
+                    ni=CarrierEthernetUni{
+                        id=netconf:192.168.56.20:830/0,
+                        cfgId=netconf:192.168.56.20:830/0,
+                        role=Root,
+                        refCount=0,
+                        ceVlanIds=[100],
+                        capacity=1000000000,
+                        usedCapacity=3.0E8,
+                        bandwidthProfiles=[
+                            CarrierEthernetBandwidthProfile{
+                                id=FC-1,
+                                type=EVC,
+                                cir=3.0E8,
+                                cbs=2000,
+                                eir=0.0,
+                                ebs=0}]}}]}]}
diff --git a/drivers/microsemi/src/test/resources/getConfigSaFiltering.xml b/drivers/microsemi/src/test/resources/getConfigSaFiltering.xml
new file mode 100644
index 0000000..53bfe46
--- /dev/null
+++ b/drivers/microsemi/src/test/resources/getConfigSaFiltering.xml
@@ -0,0 +1,11 @@
+<rpc message-id="101"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <get-config>
+        <source>
+            <running/>
+        </source>
+        <filter type="subtree">
+            <source-ipaddress-filtering xmlns="http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering"/>
+        </filter>
+    </get-config>
+</rpc>
\ No newline at end of file
diff --git a/drivers/microsemi/src/test/resources/getConfigSaFilteringReply.xml b/drivers/microsemi/src/test/resources/getConfigSaFilteringReply.xml
new file mode 100644
index 0000000..6e1e040
--- /dev/null
+++ b/drivers/microsemi/src/test/resources/getConfigSaFilteringReply.xml
@@ -0,0 +1,14 @@
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="7">
+    <data>
+        <source-ipaddress-filtering xmlns="http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering">
+            <interface-eth0>
+                <source-address-range>
+                    <range-id>1</range-id>
+                    <ipv4-address-prefix>10.10.10.10/16</ipv4-address-prefix>
+                    <name>Filter1</name>
+                </source-address-range>
+                <filter-admin-state>inactive</filter-admin-state>
+            </interface-eth0>
+        </source-ipaddress-filtering>
+    </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/drivers/microsemi/src/test/resources/systemReply-Sample1.xml b/drivers/microsemi/src/test/resources/systemReply-Sample1.xml
new file mode 100644
index 0000000..206bf45
--- /dev/null
+++ b/drivers/microsemi/src/test/resources/systemReply-Sample1.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2">
+    <data>
+        <system xmlns="urn:ietf:params:xml:ns:yang:ietf-system">
+            <longitude xmlns="http://www.microsemi.com/microsemi-edge-assure/msea-system">-8.4683990</longitude>
+            <latitude xmlns="http://www.microsemi.com/microsemi-edge-assure/msea-system">51.9036140</latitude>
+        </system>
+        <system-state xmlns="urn:ietf:params:xml:ns:yang:ietf-system" xmlns:sysms="http://www.microsemi.com/microsemi-edge-assure/msea-system">
+            <platform>
+                <os-release>2.6.33-arm1-MSEA1000--00326-g643be76.x.0.0.212</os-release>
+                <sysms:device-identification>
+                    <sysms:serial-number>Eagle Simulator.</sysms:serial-number>
+                </sysms:device-identification>
+            </platform>
+        </system-state>
+    </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/drivers/microsemi/src/test/resources/systemReply-Sample2.xml b/drivers/microsemi/src/test/resources/systemReply-Sample2.xml
new file mode 100644
index 0000000..9592538
--- /dev/null
+++ b/drivers/microsemi/src/test/resources/systemReply-Sample2.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2">
+  <data>
+    <system-state xmlns="urn:ietf:params:xml:ns:yang:ietf-system">
+      <platform/>
+    </system-state>
+  </data>
+</rpc-reply>
\ No newline at end of file