Refactor of CFM code part3 - Microsemi driver

Change-Id: Ibfee64f626c41e82b26d61f5ec160e2921e9fc1f
diff --git a/drivers/microsemi/ea1000/BUCK b/drivers/microsemi/ea1000/BUCK
new file mode 100644
index 0000000..940903e
--- /dev/null
+++ b/drivers/microsemi/ea1000/BUCK
@@ -0,0 +1,48 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:ONOS_YANG',
+    '//drivers/utilities:onos-drivers-utilities',
+    '//protocols/netconf/api:onos-protocols-netconf-api',
+    '//protocols/netconf/ctl:onos-protocols-netconf-ctl',
+    '//models/common:onos-models-common',
+    '//models/microsemi:onos-models-microsemi',
+    '//lib:org.apache.karaf.shell.console',
+    '//apps/cfm/api:onos-apps-cfm-api',
+] + YANG_TOOLS
+
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+    '//core/api:onos-api-tests',
+    '//drivers/netconf:onos-drivers-netconf-tests',
+    '//utils/osgi:onlab-osgi-tests',
+    '//apps/cfm/app:onos-apps-cfm-app',
+    '//apps/cfm/app:onos-apps-cfm-app-tests',
+]
+
+APPS = [
+    'org.onosproject.yang',
+#     'org.onosproject.yang-gui',
+    'org.onosproject.config',
+    'org.onosproject.netconf',
+    'org.onosproject.netconfsb',
+    'org.onosproject.drivers.netconf',
+    'org.onosproject.models.common',
+    'org.onosproject.models.microsemi',
+    'org.onosproject.cfm',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+    resources_root = 'src/main/resources',
+    resources = glob(['src/main/resources/**']),
+)
+
+onos_app (
+    app_name = 'org.onosproject.drivers.microsemi.ea1000',
+    title = 'Microsemi Drivers EA1000',
+    category = 'Drivers',
+    url = 'http://onosproject.org',
+    description = 'Adds support for Microsemi EA1000 devices.',
+    required_apps = APPS,
+)
diff --git a/drivers/microsemi/ea1000/README.md b/drivers/microsemi/ea1000/README.md
new file mode 100644
index 0000000..e821fcd
--- /dev/null
+++ b/drivers/microsemi/ea1000/README.md
@@ -0,0 +1,495 @@
+# Microsemi Edge Assure 1000 SFP-NID
+This driver allows connection to the Microsemi Edge Assure 1000 SFP-NID
+[EdgeAssure 1000 Product Page](https://www.microsemi.com/existing-parts/parts/137346)
+
+The User Guide for this product is available on request from Microsemi, and gives a full explanation of the theory of operation, functionality and how all functions can be accessed through the NETCONF interface only.<br/>
+
+Currently only a subset of it's functionality is supported through ONOS, but this will expand to full functionality in future releases.
+
+# Compile and Installation
+Currently this driver is built using BUCK and uses version 2.1 of onos-yang-tools<br/>
+
+All that is required to activate the driver is to run the following at the ONOS CLI<br/>
+**`onos:app activate org.onosproject.drivers.microsemi`**<br/>
+This will load any dependent apps also. To verify the driver has been loaded run the command<br/>
+**onos:apps -a -s**
+
+# Change NETCONF default connection timeout
+Connection timeouts need to be increased from default values when using EA1000. At ONOS command line run
+
+```
+onos:cfg set org.onosproject.netconf.ctl.impl.NetconfControllerImpl netconfConnectTimeout 50
+onos:cfg set org.onosproject.netconf.ctl.impl.NetconfControllerImpl netconfReplyTimeout 50
+```
+
+# Creating Devices
+EA1000 Devices will not be automatically discovered at present in ONOS. They have to be created through the network/configuration REST interface in ONOS.
+
+* The name must follow the format **netconf:ipaddr:port**
+* The **ip** and **port** must correspond to the ip and port in the name (above).
+
+```js
+{
+  "devices": {
+    "netconf:192.168.56.10:830": {
+      "netconf": {
+        "username": "admin",
+        "password": "admin",
+        "ip": "192.168.56.10",
+        "port": 830,
+        "connect-timeout": 50,
+        "reply-timeout": 50,
+        "idle-timeout": 40 
+      },
+      "basic": {
+        "driver": "microsemi-netconf",
+        "type": "SWITCH",
+        "manufacturer": "Microsemi",
+        "hwVersion": "EA1000"
+      }
+    }
+  }
+}
+```
+
+
+# Connected Device
+When the EA1000 is configured and connected is should be visible in ONOS through the **devices** command.
+
+```
+onos> devices
+id=netconf:192.168.56.10:830, available=true, local-status=connected 33s ago, role=MASTER, type=SWITCH, mfr=Microsemi, hw=EA1000, sw=4.4.0-53-generic, serial=Eagle Simulator., driver=microsemi-netconf, ipaddress=192.168.56.10, latitude=51.8865467, locType=geo, longitude=-8.4040440, name=netconf:192.168.56.10:830, port=830, protocol=NETCONF 
+```
+
+Note how the
+* software version (sw=**4.4.0-53-generic**)
+* serial number (serial=**Eagle Simulator.**)
+* latitude (latitude=**51.8865467**) and
+* longitude (longitude=**-8.4040440**)
+are all retrieved from the device on initial handshake.
+
+In addition the time on the device is checked at this stage, and if it wrong by more than 1 day (it defaults to 1-1-1970 on startup if no NTP server is configured), then the current time is written to it at this stage. This will persist on the device until next reboot.
+
+Also the ports of the device will be visible after connection. There are 2 ports
+* Port 0 - The **Optics** port - this is a single mode 1000LX 1310nm optical connection
+* Port 1 - The **Host** port - this is a 1GB Ethernet Copper connection in to an SFP Port
+
+```
+onos> ports
+id=netconf:192.168.56.10:830, available=true, local-status=connected 15s ago, role=MASTER, type=SWITCH, mfr=Microsemi, hw=EA1000, sw=4.4.0-53-generic, serial=Eagle Simulator., driver=microsemi-netconf, ipaddress=192.168.56.10, latitude=51.8865467, locType=geo, longitude=-8.4040440, name=netconf:192.168.56.10:830, port=830, protocol=NETCONF
+    port=0, state=enabled, type=fiber, speed=1000, portName=Optics
+    port=1, state=enabled, type=copper, speed=1000, portName=Host
+```
+
+# OpenFlow Emulation
+Currently the EA1000 supports only a limited set of OpenFlow rules through the Flows REST API and the Flow Objective API.
+
+## IP Source Address filtering
+A feature of the EA1000 that may be configured through Flow Rules is IP Source Address Filtering. This can only be activated on Port 0 (the optics Port). An example of this kind of flow is
+
+`POST /onos/v1/flows/ HTTP/1.1`<br/>
+```js
+{
+  "flows": [
+    {
+      "priority": 50000,
+      "timeout": 0,
+      "isPermanent": true,
+      "deviceId": "netconf:192.168.56.10:830",
+      "tableId": 8,
+      "treatment": {
+        "instructions": [ {"type": "NOACTION"} ],
+        "deferred": []
+      },
+      "selector": {
+        "criteria": [
+          {"type": "IPV4_SRC", "ip": "192.168.8.0/24"},
+          {"type": "IN_PORT", "port": "0"}
+        ]
+      }
+    }
+  ]
+}
+```
+
+## Vlan Tag Manipulation
+**Note: Before Vlan Tag manipulation can be done the mode of the interface on the EA1000 has to be changed to be compatible with the type of tags that are being received. If this is not done, once an EVC is created the packets that have the Vlan tagged on will be treated as untagged by EA1000, and dropped if there is no EVC present corresponding to the interface PVID. See the section below on the "Setting EA1000 Interface Tagging Mode"**
+
+Flows that Push, Pop or Overwrite VLAN tags are implemented in EA1000 and are treated as MEF Carrier Ethernet EVCs. Both CTags and STags can be pushed on to matching Ethernet packets at network Layer 2.
+
+`POST /onos/v1/flows/ HTTP/1.1`<br/>
+```js
+{
+  "flows": [
+    {
+      "priority": 50000,
+      "timeout": 0,
+      "isPermanent": true,
+      "tableId": 6, // This sets the EVC id - this first flow is configuring the customer side - UNI-C
+      "deviceId": "netconf:192.168.56.10:830",
+      "treatment": {
+        "instructions": [
+          {
+            "type": "L2MODIFICATION",
+            "subtype": "VLAN_PUSH", // This pushes a VLAN on
+            "ethernetType": "0x88a8" // The pushed VLAN type is QinQ
+          },
+          {
+            "type": "L2MODIFICATION",
+            "subtype": "VLAN_ID",
+            "vlanId": "200" // The pushed VLAN id is 200
+          }],
+        "deferred": []
+      },
+      "selector": {
+        "criteria": [
+        {
+          "type": "VLAN_VID",
+          "vlanId": "100" // Applies only to packets already tagged with VLAN 100..
+        },
+        {
+          "type": "IN_PORT",
+          "port": "1" // ...that are coming in on the Host port
+        }]
+        }
+    },
+    {
+      "priority": 50000,
+      "timeout": 0,
+      "isPermanent": true,
+      "tableId": 6, // The same EVC, but now we are configuring another VLAN
+      "deviceId": "netconf:192.168.56.10:830",
+      "treatment": {
+        "instructions": [
+          {
+            "type": "L2MODIFICATION",
+            "subtype": "VLAN_PUSH", // Push again
+            "ethernetType": "0x88a8" // QinQ again
+          },
+          {
+            "type": "L2MODIFICATION",
+            "subtype": "VLAN_ID",
+            "vlanId": "200" // VLAN 200 again
+          }],
+        "deferred": []
+      },
+      "selector": {
+        "criteria": [
+          {
+            "type": "VLAN_VID",
+            "vlanId": "101" // Applies only to packets already tagged with VLAN 101..
+          },
+          {
+            "type": "IN_PORT",
+            "port": "1" // ... that are coming in on the Host port
+          }]
+      }
+    },
+    {
+      "priority": 50000,
+      "timeout": 0,
+      "isPermanent": true,
+      "tableId": 6, // The same EVC, but now we are configuring the opposite side
+      "deviceId": "netconf:192.168.56.10:830",
+      "treatment": {
+        "instructions": [
+        {
+          "type": "L2MODIFICATION",
+          "subtype": "VLAN_POP" // Here we are popping the top level tag
+        }],
+        "deferred": []
+      },
+      "selector": {
+        "criteria": [
+          {
+            "type": "VLAN_VID", // Applies only to packets tagged with VLAN 200
+            "vlanId": "200"
+          },
+          {
+            "type": "IN_PORT",
+            "port": "0" // That are coming in on the Optics Port
+          }]
+      }
+    }
+  ]
+}
+```
+
+## Setting EA1000 Interface Tagging Mode
+The Interface of the EA1000 has an attribute **frame_format** that must be set to either:
+* none (default)
+* ctag
+* stag
+to correspond to the type of tagging that will be applied to packets received at that port.
+
+For instance if Port 0 of an EA1000 is to receive and process S-Tags, the the frame-format of the interface *eth0* should be set to **stag** in advance.
+
+This should be made a permanent setting in the NETCONF *startup* datastore, so that it will be active if the device reboots.
+
+Likewise the opposite port should be set to *ctag*.<br/>
+
+This changes are not made done through the ONOS Driver, and currently only possible to make this change through a NETCONF CLI client such as *yangcli-pro* or *netopeer-cli*;
+
+See the EA1000 User Guide for details on how to use *yangcli-pro* to access the EA1000.
+
+On an EA1000 accessed through *yangcli-pro* the following commands can be used to make these changes:
+
+```
+admin@192.168.2.234> discard-changes
+admin@192.168.2.234> copy-config source=startup target=candidate
+admin@192.168.2.234> merge /interfaces/interface[name='eth0']/frame-format --value='stag'
+admin@192.168.2.234> merge /interfaces/interface[name='eth1']/frame-format --value='ctag'
+admin@192.168.2.234> commit
+admin@192.168.2.234> copy-config source=running target=startup
+```
+
+# ONOS Carrier Ethernet Application
+The ONOS [Carrier Ethernet](https://wiki.onosproject.org/display/ONOS/Carrier+Ethernet+Application) application allows EVCs to be created between UNIs that are linked together in ONOS. This is translated down to OpenFlow switches by converting the **ce-evc-create** commands in to Flow Rules similar to those shown above.
+
+While EA1000 is not an OpenFlow switch, it's driver can convert these flows in to NETCONF which can be used to configure EVCs on the EA1000. Because EA1000 is just a 2 port device it represents only 1 UNI (conventionally on switches each port represnts a UNI).
+
+When an EA1000 device is configured in ONOS the Carrier Ethernet Application considers both of its ports to be UNIs, as can be seen in the listing below:
+
+```
+onos> ce-uni-list
+CarrierEthernetUni{id=netconf:192.168.56.10:830/0, cfgId=netconf:192.168.56.10:830/0, role=null, refCount=0, ceVlanIds=[], capacity=1000000000, usedCapacity=0.0, bandwidthProfiles=[]}
+CarrierEthernetUni{id=netconf:192.168.56.10:830/1, cfgId=netconf:192.168.56.10:830/1, role=null, refCount=0, ceVlanIds=[], capacity=1000000000, usedCapacity=0.0, bandwidthProfiles=[]}
+```
+
+This mismatch is handled in the driver - both side appear to be separate here but they will apply to the same single UNI on the EA1000 in opposite directions.
+
+For an EVC to be created there has to an ONOS 'link' between 2 UNIs for a POINT-TO-POINT connection - an Ethernet Virtual Private Line (**EVPL**). There has to be more than 2 UNIs to create a MULTIPOINT-TO-MULTIPOINT link - an E-Lan.
+
+## Links
+In a simple scenario that has 2 EA1000s (netconf:192.168.56.10:830 and netconf:192.168.56.20:830) configured in ONOS, the two might be linked together through their optics ports (port 0). The following result is expected for a bi-directional link:
+
+```
+onos> links
+src=netconf:192.168.56.10:830/0, dst=netconf:192.168.56.20:830/0, type=DIRECT, state=ACTIVE, expected=false
+src=netconf:192.168.56.20:830/0, dst=netconf:192.168.56.10:830/0, type=DIRECT, state=ACTIVE, expected=false
+```
+This will not exist by default since Link Discovery is not yet a feature of the EA1000 driver. These have to be created manually - through the network/configuration REST API.
+
+`POST /onos/v1/network/configuration/ HTTP/1.1`<br/>
+```js
+{
+  "links": {
+    "netconf:192.168.56.10:830/0-netconf:192.168.56.20:830/0": { // 10 to 20
+      "basic" : {
+        "type" : "DIRECT"
+      }
+    },
+    "netconf:192.168.56.20:830/0-netconf:192.168.56.10:830/0" : { // and reverse
+      "basic" : {
+        "type" : "DIRECT"
+      }
+    }
+  }
+}
+```
+
+## EVPL Creation
+To create a simple EVPL the following command can be used at the ONOS CLI:<br/>
+
+```
+onos>ce-evc-create --cevlan 101 evpl1 POINT_TO_POINT netconf:192.168.57.10:830/0 netconf:192.168.57.20:830/0
+```
+
+This returns without any message. Tailing through the ONOS logs will reveal any error that might have occurred.<br/>
+
+This EVC can be viewed only through the command line:
+```
+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=[101], capacity=1000000000, usedCapacity=0.0, bandwidthProfiles=[CarrierEthernetBandwidthProfile{id=FC-1, type=EVC, cir=0.0, cbs=0, 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=[101], capacity=1000000000, usedCapacity=0.0, bandwidthProfiles=[CarrierEthernetBandwidthProfile{id=FC-1, type=EVC, cir=0.0, cbs=0, 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=[101], capacity=1000000000, usedCapacity=0.0, bandwidthProfiles=[CarrierEthernetBandwidthProfile{id=FC-1, type=EVC, cir=0.0, cbs=0, 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=[101], capacity=1000000000, usedCapacity=0.0, bandwidthProfiles=[CarrierEthernetBandwidthProfile{id=FC-1, type=EVC, cir=0.0, cbs=0, eir=0.0, ebs=0}]}}]}]}
+```
+
+## EVPL flows
+This creates a set of flows in ONOS that are pushed down to the two EA1000s through NETCONF to configure the EVCs
+
+```
+onos> flows
+deviceId=netconf:192.168.56.10:830, flowRuleCount=2
+id=71000050d21dd5, state=ADDED, bytes=0, packets=0, duration=0, liveType=UNKNOWN, priority=50000, tableId=1, appId=org.onosproject.ecord.carrierethernet, payLoad=null, selector=[IN_PORT:0, VLAN_VID:1], treatment=DefaultTrafficTreatment{immediate=[VLAN_POP], deferred=[], transition=None, meter=None, cleared=false, metadata=null} # This represents ingress on the Optics port 0 on device A and POPs off the S-Tag
+id=710000b5c1f057, state=ADDED, bytes=0, packets=0, duration=0, liveType=UNKNOWN, priority=50000, tableId=1, appId=org.onosproject.ecord.carrierethernet, payLoad=null, selector=[IN_PORT:1, VLAN_VID:101], treatment=DefaultTrafficTreatment{immediate=[VLAN_PUSH:qinq, VLAN_ID:1], deferred=[], transition=TABLE:0, meter=None, cleared=false, metadata=null} # This represents ingress on the Host port 1 on device A and pushes on the S-Tag 1
+
+deviceId=netconf:192.168.56.20:830, flowRuleCount=2
+id=710000613c8252, state=ADDED, bytes=0, packets=0, duration=0, liveType=UNKNOWN, priority=50000, tableId=1, appId=org.onosproject.ecord.carrierethernet, payLoad=null, selector=[IN_PORT:0, VLAN_VID:1], treatment=DefaultTrafficTreatment{immediate=[VLAN_POP], deferred=[], transition=None, meter=None, cleared=false, metadata=null} # This represents ingress on the Optics port 0 on device B and POPs off the S-Tag 1
+id=7100006ca2573f, state=ADDED, bytes=0, packets=0, duration=0, liveType=UNKNOWN, priority=50000, tableId=1, appId=org.onosproject.ecord.carrierethernet, payLoad=null, selector=[IN_PORT:1, VLAN_VID:101], treatment=DefaultTrafficTreatment{immediate=[VLAN_PUSH:qinq, VLAN_ID:1], deferred=[], transition=TABLE:0, meter=None, cleared=false, metadata=null} # This represents ingress on the Host port 1 on device B and pushes on the S-Tag 1
+```
+
+Through these flows it's clear that the CE-VLAN on the UNI-C side is 101 and that the S-Tag that is being pushed on is VLAN 1. Packets coming back in on the UNI-N on port 0 have their S-Tag popped off. In this scenario this will create evc-1 on both of the EA1000s.<br/>
+
+On the actual EA1000 itself using a NETCONF CLI Client like yangcli-pro, the result is:
+```
+admin@192.168.56.10> sget-config /mef-services/uni source=running
+rpc-reply {
+  data {
+    mef-services {
+      uni { # There is only one UNI on the EA1000
+        name Uni-on-192.168.56.10:830 # Automatically assigned
+        evc 1 { # From the VLAN 1 from CE app
+          evc-index 1
+          name EVC-1 # Automatically assigned
+          evc-per-uni {
+            evc-per-uni-c { # The UNI-C side
+            ce-vlan-map 101 # Could be a range of values
+            flow-mapping {
+              ce-vlan-id 101
+              flow-id 31243725464268887 # For tracking with ONOS
+            }
+            ingress-bwp-group-index 0 # No meters
+            tag-push { # Push on an a VLAN
+              push-tag-type pushStag # Push type is S-TAG
+              outer-tag-vlan 1 # Push value is 1
+              }
+            }
+            evc-per-uni-n { # For the UNI-N side
+              ce-vlan-map 1 # The VLAN to match for egress on this side
+              flow-mapping {
+                ce-vlan-id 1
+                flow-id 31243723770830293
+              }
+              ingress-bwp-group-index 0
+              tag-pop { # Pop off the S-TAG
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+admin@192.168.56.10>
+```
+
+## CIR and EIR as OpenFlow Meters
+** Note: The meters created by Carrier Ethernet are not compatible with Open vSwitch at present.They will disrupt the configuration of the EA1000 if there are Open VSwitch based OpenFlow switches between the UNIs **<br/>
+
+To create limits on how the EVPL can transport data the CIR, EIR and CBS and EBS values can be specified:
+
+```
+onos> ce-evc-create --cevlan 102 -c 400 -e 200 -cbs 3000 -ebs 2000 evpl2 POINT_TO_POINT netconf:192.168.56.10:830/0 netconf:192.168.56.20:830/0
+```
+
+* -c 400 means Commit Information Rate is 400 MB/s
+* -e 200 means Excess information Rate is 200 MB/s
+* -cbs 3000 is Committed Burst Size of 3000 **Bytes**
+* -ebs 2000 is Excess Burst Rate of 2000 **Bytes**
+
+These will be created as meters in Open Flow.
+
+```
+onos> meters
+DefaultMeter{device=netconf:192.168.56.20:830, id=1, appId=org.onosproject.ecord.carrierethernet, unit=KB_PER_SEC, isBurst=true, state=PENDING_ADD, bands=[DefaultBand{rate=50000, burst-size=3000, type=REMARK, drop-precedence=0}, DefaultBand{rate=75000, burst-size=5000, type=DROP, drop-precedence=null}]}
+DefaultMeter{device=netconf:192.168.56.10:830, id=1, appId=org.onosproject.ecord.carrierethernet, unit=KB_PER_SEC, isBurst=true, state=PENDING_ADD, bands=[DefaultBand{rate=75000, burst-size=5000, type=DROP, drop-precedence=null}, DefaultBand{rate=50000, burst-size=3000, type=REMARK, drop-precedence=0}]}
+```
+
+## EVC Deletion
+EVCs can be deleted individually with **ce-evc-remove <evc-id>** or all together with **ce-evc-remove-all**.
+
+# Support for Layer 2 Monitoring
+EA1000 supports both Connectivity Fault Management (CFM) and MEF Services OAM. This is achieved through the EA1000 driver supporting the ONOS behaviors CfmMepProgrammable and SoamDmProgrammable described in [Layer 2 Monitoring with CFM and Services OAM](https://wiki.onosproject.org/display/ONOS/Layer+2+Monitoring+with+CFM+and+Services+OAM).
+
+With EA1000 the CFM entities (Maintenance Association Endpoints or MEPs) are created in parallel with the EVC services that they are designed to test, and related loosely to each other only through VLAN ID.
+For instance an EVC might be created with a VLAN of 101, and separately a Maintenance Association would be created with the same VLAN ID, and MEPs created under this for monitoring that VLAN (and by inference that EVC).
+
+The CFM interface to ONOS is exposed through a REST API at /onos/cfm
+In ONOS Maintenance Domains and Maintenance Associations beneath them are created and persisted in a distributed datastore. These are logical entities that can span across an ONOS cluster and are not directly related to devices.
+
+The Maintenance Association Endpoint - MEP (the child of the Maintenance Association, and grandchild of the Maintenance Domain) is also a logical entity but has a hard many:1 association to a device that supports the CfmMepProgrammable behaviour. EA1000 is one such device, and so one to many MEPs can be associated with an EA1000 device.
+
+For example to create an Maintenance Domain in ONOS the following might be POSTed to 
+`POST http://localhost:8181/onos/cfm/md HTTP/1.1`</br>
+```js
+{"md": {
+    "mdName": "Microsemi",
+    "mdNameType": "CHARACTERSTRING",
+    "mdLevel": "LEVEL3",
+    "mdNumericId": 1
+   }
+}
+```
+
+To create a Maintenance Association under this
+`POST http://localhost:8181/onos/cfm/md/Microsemi/ma HTTP/1.1`</br>
+```js
+{
+  "ma": {
+    "maName": "ma-vlan-1",
+    "maNameType": "CHARACTERSTRING",
+    "maNumericId": 1,
+    "ccm-interval": "INTERVAL_1S",
+    "component-list": [
+      { "component": {
+        "component-id":"1",
+        "tag-type": "VLAN_STAG",
+        "vid-list": [
+          {"vid":1}
+        ]
+        }
+      }
+    ],
+    "rmep-list": [
+      { "rmep":10 },
+      { "rmep":20 },
+      { "rmep":30 }
+    ]
+  }
+}
+```
+
+To create a MEP under this:
+`POST http://localhost:8181/onos/cfm/md/Microsemi/ma/ma-vlan-1/mep HTTP/1.1`</br>
+```js
+{
+  "mep": {
+    "mepId": 10,
+    "deviceId": "netconf:10.205.86.26:830",
+    "port": 0,
+    "direction": "DOWN_MEP",
+    "primary-vid": 1,
+    "administrative-state": true,
+    "ccm-ltm-priority": 4,
+    "cci-enabled" :true
+  }
+}
+```
+
+When the MEP is created a configuration is written down to the EA1000 device at 10.205.86.26 through NETCONF roughly in the format:
+```xml
+<maintenance-domain>
+ <id>1</id>
+ <name>Microsemi</name>
+ <name-type>CHARACTER_STRING</name-type>
+ <md-level>3</md-level>
+ <maintenance-association>
+   <id>1</id>
+   <name>ma-vlan-1</name>
+   <name-type>CHARACTER_STRING</name-type>
+   <component-list>
+     <tag-type>vlan-stag</tag-type>
+     <vid>1</vid> 
+   </component-list>
+   <remote-mep>10</remote-mep>
+   <remote-mep>20</remote-mep>
+   <remote-mep>30</remote-mep>
+   <maintenance-association-endpoint>
+     <mep-identifier>10</mep-identifier>
+     ...
+   </maintenance-association-endpoint>
+ </maintenance-association>
+</maintenance-domain>
+```
+
+There are a few things to note here:
+* On EA1000 the MD and MA are indexed by their _id_ and not by name. This means that it is essential when working with EA1000 that all MD's and MA's have a numeric ID specified, and that the numeric IDs of Maintenance Domains should be unique. The numeric IDs of Maintenance Associations should be unique _within_ Maintenance Domains.
+* The component list is flattened down to a singleton object. While in the CFM model many Components are possible, EA1000 supports only 1
+* With Remote Meps - the local and all remote meps must be specified by their ID. In this instance 10 is the local on device 10.205.86.26 and 20 and 30 are remote meps that we expect will be local to some other devices
+* Even though the write to the EA1000 only happens when the MEP is created it brings down the MD and MA to the device with it.
+* When the MEP is deleted the MD and MA are left behind on the device. If the MD and MA were then to be changed in ONOS and a new MEP pushed down to the device, there would be an error, as the MD and MA would remain on the device since the earlier time. To remedy this, the MD and MA would need to be deleted manually through yangcli-pro.
diff --git a/drivers/microsemi/ea1000/pom.xml b/drivers/microsemi/ea1000/pom.xml
new file mode 100644
index 0000000..d34a507
--- /dev/null
+++ b/drivers/microsemi/ea1000/pom.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2017 Open Networking Foundation
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>onos-drivers-general</artifactId>
+        <groupId>org.onosproject</groupId>
+        <version>1.13.0-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+
+    <artifactId>onos-drivers-microsemi-ea1000</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>Microsemi Drivers EA1000</description>
+    <url>http://onosproject.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <onos.version>${project.version}</onos.version>
+        <onos.app.requires>
+          org.onosproject.yang,
+          org.onosproject.netconf,
+          org.onosproject.models.microsemi,
+          org.onosproject.cfm
+        </onos.app.requires>
+        <onos.app.category>Drivers</onos.app.category>
+        <onos.app.title>Microsemi Drivers</onos.app.title>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-apps-cfm-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-model</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-runtime</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-drivers-utilities</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-protocols-netconf-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-drivers-netconf</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <classifier>tests</classifier>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-models-microsemi</artifactId>
+            <version>${project.version}</version>
+            <type>bundle</type>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-cli</artifactId>
+            <version>${onos.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.console</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-osgi</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-apps-cfm-app</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-apps-cfm-app</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+            <scope>test</scope>
+            <classifier>tests</classifier>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-core-common</artifactId>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
+
+    </dependencies>
+
+    <build>
+
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>generate-scr-srcdescriptor</id>
+                        <goals>
+                            <goal>scr</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <supportedProjectTypes>
+                        <supportedProjectType>bundle</supportedProjectType>
+                        <supportedProjectType>war</supportedProjectType>
+                    </supportedProjectTypes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.onosproject</groupId>
+                <artifactId>onos-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>cfg</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>cfg</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>swagger</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>swagger</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>app</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>app</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+    </build>
+
+</project>
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java
new file mode 100755
index 0000000..a5ff236
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java
@@ -0,0 +1,866 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.drivers.microsemi.yang.utils.MaNameUtil.getApiMaIdFromYangMaName;
+import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getApiMdIdFromYangMdName;
+import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getYangMdNameFromApiMdId;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onlab.util.HexString;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.drivers.microsemi.yang.utils.MaNameUtil;
+import org.onosproject.incubator.net.l2monitoring.cfm.Component;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultRemoteMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.MepDirection;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry.MepLbEntryBuilder;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.InterfaceStatusTlvType;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.PortStatusTlvType;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepEntryBuilder;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.DefaultAbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.faultalarmdefectbitstype.Bits;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.CcmIntervalEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.ComponentList;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultComponentList;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.componentlist.TagTypeEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.ContinuityCheck;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultContinuityCheck;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.InterfaceEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.remotemepstatetype.RemoteMepStateTypeEnum;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMacAddress;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMepId;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.DefaultTransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.DefaultTargetAddress;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.TargetAddress;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MdLevelType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.VlanIdType;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of CfmMepProgrammable for Microsemi EA1000.
+ */
+public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
+    implements CfmMepProgrammable {
+
+    private static final int NUMERIC_ID_MAX = 64;
+    private static final int REMOTEMEPLIST_MIN_COUNT = 2;
+    private static final int REMOTEMEPLIST_MAX_COUNT = 9;
+    private static final int COMPONENT_LIST_SIZE = 1;
+    private static final int VIDLIST_SIZE_MIN = 1;
+    private static final int MEP_PORT_MIN = 0;
+    private static final int MEP_PORT_MAX = 1;
+    private final Logger log = getLogger(getClass());
+
+    public EA1000CfmMepProgrammable() {
+        log.debug("Loaded handler behaviour EA1000CfmMepProgrammable");
+    }
+
+    @Override
+    public boolean createMep(MdId mdName, MaIdShort maName, Mep mep)
+            throws CfmConfigException {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = checkNotNull(controller.getDevicesMap()
+                                .get(handler().data().deviceId()).getSession());
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+        CfmMepService cfmMepService =
+                checkNotNull(handler().get(CfmMepService.class));
+
+        MaintenanceAssociationEndPoint yangMep = buildYangMepFromApiMep(mep);
+
+        CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class));
+        MseaCfmOpParam mseaCfmOpParam = getMaYangObject(cfmMdService, mdName, maName);
+
+        mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
+                .maintenanceAssociation().get(0).addToMaintenanceAssociationEndPoint(yangMep);
+        //Add this mepId to the list of remoteMeps on the device
+        mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
+                .maintenanceAssociation().get(0).addToRemoteMeps(MepIdType.of(mep.mepId().value()));
+
+        //Add all of the existing meps on this MD/MA to the remote meps list
+        cfmMepService.getAllMeps(mdName, maName).forEach(m -> {
+            mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
+                    .maintenanceAssociation().get(0).addToRemoteMeps(MepIdType.of(m.mepId().value()));
+        });
+        try {
+            mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            log.info("Created MEP {} on device {}", mdName + "/" + maName +
+                    "/" + mep.mepId(), handler().data().deviceId());
+
+            return true;
+        } catch (NetconfException e) {
+            log.error("Unable to create MEP {}/{}/{} on device {}",
+                    mdName, maName, mep.mepId(), handler().data().deviceId());
+            throw new CfmConfigException("Unable to create MEP :" + e.getMessage());
+        }
+    }
+
+    @Override
+    public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        if (handler().data().deviceId() == null) {
+            throw new CfmConfigException("Device is not ready - connecting or "
+                    + "disconnected for MEP " + mdName + "/" + maName + "/" + mepId);
+        }
+        NetconfSession session = checkNotNull(controller.getDevicesMap()
+                                .get(handler().data().deviceId()).getSession());
+        MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        try {
+            MseaCfm mseacfm =
+                    mseaCfmService.getMepFull(mdName, maName, mepId, session);
+            Collection<MepEntry> mepEntries = getMepEntriesFromYangResponse(mseacfm);
+            if (mepEntries == null || mepEntries.size() != 1) {
+                log.warn("Mep " + mepId + " not found on device " + handler().data().deviceId());
+                return null;
+            } else {
+                return mepEntries.stream().findFirst().get();
+            }
+        } catch (NetconfException e) {
+            log.error("Unable to get MEP {}/{}/{} on device {}",
+                    mdName, maName, mepId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to get MEP :" + e.getMessage());
+        }
+    }
+
+    private Collection<MepEntry> getMepEntriesFromYangResponse(MseaCfm mseacfm)
+            throws CfmConfigException {
+
+        Collection<MepEntry> mepEntries = new ArrayList<>();
+        if (mseacfm == null || mseacfm.mefCfm() == null || mseacfm.mefCfm().maintenanceDomain() == null) {
+            return mepEntries;
+        }
+
+        for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.
+                mseacfm.mefcfm.MaintenanceDomain replyMd:mseacfm.mefCfm().maintenanceDomain()) {
+            for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.
+                    mseacfm.mefcfm.maintenancedomain.
+                    MaintenanceAssociation replyMa:replyMd.maintenanceAssociation()) {
+                for (MaintenanceAssociationEndPoint replyMep:replyMa.maintenanceAssociationEndPoint()) {
+                    mepEntries.add(buildApiMepEntryFromYangMep(
+                        replyMep, handler().data().deviceId(), replyMd, replyMa));
+                }
+            }
+        }
+        return mepEntries;
+    }
+
+    @Override
+    public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId,
+                    Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
+
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = checkNotNull(controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession());
+        MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+        MaintenanceAssociationEndPoint mep =
+                new DefaultMaintenanceAssociationEndPoint();
+        mep.mepIdentifier(MepIdType.of(mepId.id()));
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+            .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+        Short maNumericId = null;
+        try {
+            maNumericId =
+                    mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId();
+            yangMa.id(maNumericId);
+        } catch (NoSuchElementException | IllegalArgumentException e) {
+            //The MA and/or MD have probably been deleted
+            // try to get numeric id values from oldMd
+            log.debug("Could not get MD/MA details from MD service during deletion of MEP {}." +
+                    "Continuing with values from event", new MepKeyId(mdName, maName, mepId));
+            yangMa.id(getMaNumericId(oldMd.get(), maName));
+        }
+
+        yangMa.addToMaintenanceAssociationEndPoint(mep);
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
+            new DefaultMaintenanceDomain();
+        Short mdNumericId = null;
+        try {
+            mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId();
+            yangMd.id(mdNumericId);
+        } catch (NoSuchElementException | IllegalArgumentException e) {
+            //The MD has probably been deleted
+            // try to get numeric id values from oldMd
+            log.debug("Could not get MD details from MD service during deletion of MEP {}." +
+                    "Continuing with values from event", new MepKeyId(mdName, maName, mepId));
+            yangMd.id(oldMd.get().mdNumericId());
+        }
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            mseaCfmService.deleteMseaMep(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            log.info("Deleted MEP {} on device {}", mdName + "/" + maName +
+                    "/" + mepId, handler().data().deviceId());
+            return true;
+        } catch (NetconfException e) {
+            log.error("Unable to delete MEP {} ({}) on device {}",
+                    mdName + "/" + maName + "/" + mepId,
+                    mdNumericId + "/" + maNumericId, handler().data().deviceId(), e);
+            throw new CfmConfigException("Unable to delete MEP :" + e.getMessage());
+        }
+
+    }
+
+    @Override
+    public boolean createMdOnDevice(MdId mdId) throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = checkNotNull(controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession());
+
+        CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class));
+        MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdId).get();
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
+                .mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md);
+
+        if (md.mdNumericId() <= 0 || md.mdNumericId() > NUMERIC_ID_MAX) {
+            throw new CfmConfigException("Numeric id of MD " + mdId + " must"
+                    + " be between 1 and 64 inclusive for EA1000");
+        }
+
+        for (MaintenanceAssociation ma:md.maintenanceAssociationList()) {
+            if (ma.maNumericId() <= 0 || ma.maNumericId() > NUMERIC_ID_MAX) {
+                throw new CfmConfigException("Numeric id of MA " + mdId + " must"
+                        + " be between 1 and 64 inclusive for EA1000");
+            }
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+                    .MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma);
+            yangMd.addToMaintenanceAssociation(yangMa);
+        }
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        try {
+            boolean created = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            log.info("Created MD {} on device {}", mdId.mdName(),
+                    handler().data().deviceId());
+            return created;
+        } catch (NetconfException e) {
+            log.error("Unable to create MD {} on device {}",
+                    mdId.mdName(), handler().data().deviceId());
+            throw new CfmConfigException("Unable to create MD :" + e.getMessage());
+        }
+    }
+
+    @Override
+    public boolean createMaOnDevice(MdId mdId, MaIdShort maId) throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = checkNotNull(controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession());
+
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+        MseaCfmOpParam mseaCfmOpParam = getMaYangObject(mdService, mdId, maId);
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        try {
+            boolean created = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            log.info("Created MA {} on device {}", mdId.mdName() + "/" + maId.maName(),
+                    handler().data().deviceId());
+            return created;
+        } catch (NetconfException e) {
+            log.error("Unable to create MA {} on device {}",
+                    mdId.mdName() + "/" + maId.maName(), handler().data().deviceId());
+            throw new CfmConfigException("Unable to create MA :" + e.getMessage());
+        }
+    }
+
+    private static MseaCfmOpParam getMaYangObject(CfmMdService cfmMdService,
+                        MdId mdName, MaIdShort maName) throws CfmConfigException {
+        MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdName).get();
+        MaintenanceAssociation ma = cfmMdService.getMaintenanceAssociation(mdName, maName).get();
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+                .MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma);
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
+                .mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md);
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        if (md.mdNumericId() <= 0 || md.mdNumericId() > NUMERIC_ID_MAX) {
+            throw new CfmConfigException("Numeric id of MD " + mdName + " must"
+                    + " be between 1 and 64 inclusive for EA1000");
+        } else if (ma.maNumericId() <= 0 || ma.maNumericId() > NUMERIC_ID_MAX) {
+            throw new CfmConfigException("Numeric id of MA " + maName + " must"
+                    + " be between 1 and 64 inclusive for EA1000");
+        }
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        return mseaCfmOpParam;
+    }
+
+    @Override
+    public boolean deleteMdOnDevice(MdId mdId, Optional<MaintenanceDomain> oldMd)
+            throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession();
+
+        //First check if this MD is known to ONOS if it is does it have MAs and
+        // do they have any Meps known to ONOS. If there are Meps throw an exception -
+        // the Meps should have been deleted first
+        //If there are none known to ONOS we do not check for Meps on the actual device
+        // - there might might be some orphaned ones down there - we want to delete these
+        //FIXME: When CfmMepService is extended to be persistent come back and enable check
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        MdNameAndTypeCombo mdName = getYangMdNameFromApiMdId(mdId);
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
+                new DefaultMaintenanceDomain();
+        Short mdNumericId = null;
+        try {
+            mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
+            yangMd.id(mdNumericId);
+        } catch (NoSuchElementException e) {
+            yangMd.id(oldMd.get().mdNumericId());
+        }
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            boolean deleted = mseaCfmService.deleteMseaMd(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            log.info("Deleted MD {} on device {}", mdName,
+                    handler().data().deviceId());
+            return deleted;
+        } catch (NetconfException e) {
+            log.error("Unable to delete MD {} ({}) on device {}",
+                    mdName, mdNumericId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to delete MD :" + e.getMessage());
+        }
+
+    }
+
+    @Override
+    public boolean deleteMaOnDevice(MdId mdId, MaIdShort maId, Optional<MaintenanceDomain> oldMd)
+            throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession();
+
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+                .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+        Short maNumericId = null;
+        try {
+            maNumericId =
+                    mdService.getMaintenanceAssociation(mdId, maId).get().maNumericId();
+            yangMa.id(maNumericId);
+        } catch (NoSuchElementException e) {
+            yangMa.id(getMaNumericId(oldMd.get(), maId));
+        }
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
+                new DefaultMaintenanceDomain();
+        Short mdNumericId = null;
+        try {
+            mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
+            yangMd.id(mdNumericId);
+        } catch (NoSuchElementException e) {
+            yangMd.id(oldMd.get().mdNumericId());
+        }
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            boolean deleted = mseaCfmService.deleteMseaMa(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            log.info("Deleted MA {} ({})on device {}", mdId.mdName() + "/" + maId.maName(),
+                    mdNumericId + "/" + maNumericId, handler().data().deviceId());
+            return deleted;
+        } catch (NetconfException e) {
+            log.error("Unable to delete MA {} ({}) on device {}",
+                    mdId.mdName() + "/" + maId.maName(),
+                    mdNumericId + "/" + maNumericId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to delete MA :" + e.getMessage());
+        }
+    }
+
+    @Override
+    public boolean createMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
+        return crDelMaRemoteMep(mdId, maId, remoteMep, true);
+    }
+
+    @Override
+    public boolean deleteMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
+        return crDelMaRemoteMep(mdId, maId, remoteMep, false);
+    }
+
+    private boolean crDelMaRemoteMep(MdId mdId, MaIdShort maId, MepId remoteMep,
+                                     boolean isCreate) throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession();
+
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+        Short mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
+        Short maNumericId =
+                mdService.getMaintenanceAssociation(mdId, maId).get().maNumericId();
+
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+                .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+        yangMa.id(maNumericId);
+        yangMa.addToRemoteMeps(MepIdType.of(remoteMep.value()));
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
+                new DefaultMaintenanceDomain();
+        yangMd.id(mdNumericId);
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            boolean result = false;
+            if (isCreate) {
+                result = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            } else {
+                result = mseaCfmService.deleteMseaMaRMep(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            }
+            log.info("{} Remote MEP {} in MA {} on device {}", isCreate ? "Created" : "Deleted",
+                    remoteMep, mdId.mdName() + "/" + maId.maName(), handler().data().deviceId());
+            return result;
+        } catch (NetconfException e) {
+            log.error("Unable to {} RemoteMep {} in MA {} on device {}",
+                    isCreate ? "create" : "delete", remoteMep, mdId.mdName() + "/" + maId.maName(),
+                    handler().data().deviceId());
+            throw new CfmConfigException("Unable to " + (isCreate ? "create" : "delete")
+                    + " Remote Mep:" + e.getMessage());
+        }
+    }
+
+
+    @Override
+    public void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId,
+            MepLbCreate lbCreate) throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+        Short mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId();
+        Short maNumericId =
+                mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId();
+
+        TransmitLoopbackInput lb = new DefaultTransmitLoopbackInput();
+        lb.maintenanceDomain(mdNumericId);
+        lb.maintenanceAssociation(maNumericId);
+        lb.maintenanceAssociationEndPoint(mepId.id());
+        if (lbCreate.numberMessages() != null) {
+            lb.numberOfMessages(lbCreate.numberMessages());
+        }
+        if (lbCreate.vlanDropEligible() != null) {
+            lb.vlanDropEligible(lbCreate.vlanDropEligible());
+        }
+
+        if (lbCreate.remoteMepId() != null) {
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype
+            .MepId yangMepId = new DefaultMepId();
+            yangMepId.mepId(MepIdType.of(lbCreate.remoteMepId().id()));
+            TargetAddress ta = new DefaultTargetAddress();
+            ta.addressType(yangMepId);
+            lb.targetAddress(ta);
+        } else if (lbCreate.remoteMepAddress() != null) {
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype
+            .MacAddress yangMacAddress = new DefaultMacAddress();
+            yangMacAddress.macAddress(
+                    org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes
+                    .MacAddress.of(lbCreate.remoteMepAddress().toString()));
+            TargetAddress ta = new DefaultTargetAddress();
+            ta.addressType(yangMacAddress);
+            lb.targetAddress(ta);
+        } else {
+            throw new CfmConfigException("Either a remote MEP ID or Remote MEP "
+                    + "MacAddress must be specified when calling Transmit Loopback");
+        }
+
+        if (lbCreate.dataTlvHex() != null && !lbCreate.dataTlvHex().isEmpty()) {
+            lb.dataTlv(HexString.fromHexString(lbCreate.dataTlvHex()));
+        }
+        if (lbCreate.vlanPriority() != null) {
+            lb.vlanPriority(PriorityType.of((short) lbCreate.vlanPriority().ordinal()));
+        }
+
+        try {
+            mseaCfmService.transmitLoopback(lb, session);
+            log.info("Transmit Loopback called on MEP {} on device {}",
+                    mdName + "/" + maName + "/" + mepId,
+                    handler().data().deviceId());
+        } catch (NetconfException e) {
+            throw new CfmConfigException(e);
+        }
+    }
+
+    @Override
+    public void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap()
+                .get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+        CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+        Short mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId();
+        Short maNumericId =
+                mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId();
+
+        AbortLoopbackInput lbAbort = new DefaultAbortLoopbackInput();
+        lbAbort.maintenanceDomain(mdNumericId);
+        lbAbort.maintenanceAssociation(maNumericId);
+        lbAbort.maintenanceAssociationEndPoint(mepId.id());
+
+        try {
+            mseaCfmService.abortLoopback(lbAbort, session);
+            log.info("Loopback on MEP {} on device {} aborted",
+                    mdName + "/" + maName + "/" + mepId,
+                    handler().data().deviceId());
+        } catch (NetconfException e) {
+            throw new CfmConfigException(e);
+        }
+    }
+
+    @Override
+    public void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
+            MepLtCreate ltCreate) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    private static org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+            .MaintenanceDomain buildYangMdFromApiMd(MaintenanceDomain md)
+            throws CfmConfigException {
+        MdNameAndTypeCombo mdName = getYangMdNameFromApiMdId(md.mdId());
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                .MaintenanceDomain mdYang = new DefaultMaintenanceDomain();
+        mdYang.id(md.mdNumericId());
+        mdYang.mdNameAndTypeCombo(mdName);
+        mdYang.mdLevel(MdLevelType.of((short) md.mdLevel().ordinal()));
+
+        return mdYang;
+    }
+
+    private static org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+            .maintenancedomain.MaintenanceAssociation buildYangMaFromApiMa(
+                        MaintenanceAssociation apiMa) throws CfmConfigException {
+
+        MaNameAndTypeCombo maName = MaNameUtil.getYangMaNameFromApiMaId(apiMa.maId());
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+                .MaintenanceAssociation yamgMa = new DefaultMaintenanceAssociation();
+        yamgMa.maNameAndTypeCombo(maName);
+
+        for (MepId rmep:apiMa.remoteMepIdList()) {
+            yamgMa.addToRemoteMeps(MepIdType.of(rmep.id()));
+        }
+
+        if (apiMa.ccmInterval() != null) {
+            switch (apiMa.ccmInterval()) {
+            case INTERVAL_3MS:
+                yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX3_3MS);
+                break;
+            case INTERVAL_10MS:
+                yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX10MS);
+                break;
+            case INTERVAL_100MS:
+                yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX100MS);
+                break;
+            case INTERVAL_1S:
+                yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX1S);
+                break;
+            default:
+                throw new CfmConfigException("EA1000 only supports "
+                        + "3ms, 10ms, 100ms and 1s for CCM Interval. Rejecting: "
+                        + apiMa.ccmInterval().name());
+            }
+        }
+        if (apiMa.componentList() == null || apiMa.componentList().size() != COMPONENT_LIST_SIZE) {
+            throw new CfmConfigException("EA1000 supports only 1 Component in an MA");
+        }
+
+        Component maComponent = apiMa.componentList().iterator().next();
+        if (maComponent.vidList() == null || maComponent.vidList().size() < VIDLIST_SIZE_MIN) {
+            throw new CfmConfigException("EA1000 requires at least 1 VID in "
+                    + "the Component of an MA");
+        }
+        ComponentList compList = new DefaultComponentList();
+        for (VlanId vid:maComponent.vidList()) {
+            compList.addToVid(VlanIdType.of(vid.toShort()));
+        }
+
+        if (maComponent.tagType() != null) {
+            switch (maComponent.tagType()) {
+            case VLAN_STAG:
+                compList.tagType(TagTypeEnum.VLAN_STAG);
+                break;
+            case VLAN_CTAG:
+                compList.tagType(TagTypeEnum.VLAN_CTAG);
+                break;
+            case VLAN_NONE:
+            default:
+                compList.tagType(TagTypeEnum.VLAN_NONE);
+                break;
+            }
+        }
+
+        yamgMa.componentList(compList);
+        yamgMa.id(apiMa.maNumericId());
+        return yamgMa;
+    }
+
+    private static MaintenanceAssociationEndPoint buildYangMepFromApiMep(Mep mep)
+            throws CfmConfigException {
+        MaintenanceAssociationEndPoint mepBuilder =
+                                    new DefaultMaintenanceAssociationEndPoint();
+        mepBuilder.mepIdentifier(MepIdType.of(mep.mepId().id()));
+        ContinuityCheck cc = new DefaultContinuityCheck();
+        cc.cciEnabled(mep.cciEnabled());
+        mepBuilder.continuityCheck(cc);
+        mepBuilder.ccmLtmPriority(
+                        PriorityType.of((short) mep.ccmLtmPriority().ordinal()));
+        mepBuilder.administrativeState(mep.administrativeState());
+
+        if (mep.direction() == MepDirection.UP_MEP) {
+            throw new CfmConfigException("EA1000 only supports DOWN Meps");
+        }
+
+        if (mep.port() == null || mep.port().toLong() < MEP_PORT_MIN
+                                    || mep.port().toLong() > MEP_PORT_MAX) {
+            throw new CfmConfigException("EA1000 has only ports 0 and 1. "
+                    + "Rejecting Port: " + mep.port());
+        }
+        mepBuilder.yangAutoPrefixInterface(
+                (mep.port().toLong() == 0) ? InterfaceEnum.ETH0 : InterfaceEnum.ETH1);
+
+        return mepBuilder;
+    }
+
+    private MepEntry buildApiMepEntryFromYangMep(
+            MaintenanceAssociationEndPoint yangMep, DeviceId deviceId,
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.
+                    mseacfm.mefcfm.MaintenanceDomain replyMd,
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.
+                    mseacfm.mefcfm.maintenancedomain.MaintenanceAssociation replyMa)
+            throws CfmConfigException {
+        MepId mepId = MepId.valueOf((short) yangMep.mepIdentifier().uint16());
+        MepEntry.MepEntryBuilder builder = DefaultMepEntry.builder(mepId,
+                deviceId,
+                (yangMep.yangAutoPrefixInterface() == InterfaceEnum.ETH0) ?
+                        PortNumber.portNumber(0) : PortNumber.portNumber(1),
+                MepDirection.DOWN_MEP, //Always down for EA1000
+                getApiMdIdFromYangMdName(replyMd.mdNameAndTypeCombo()),
+                getApiMaIdFromYangMaName(replyMa.maNameAndTypeCombo()));
+
+        if (yangMep.loopback() != null) {
+            MepLbEntryBuilder lbEntryBuilder = DefaultMepLbEntry.builder();
+            if (yangMep.loopback().repliesReceived() != null) {
+                lbEntryBuilder = lbEntryBuilder.countLbrReceived(
+                        yangMep.loopback().repliesReceived().uint32());
+            }
+            if (yangMep.loopback().repliesTransmitted() != null) {
+                lbEntryBuilder = lbEntryBuilder.countLbrTransmitted(
+                        yangMep.loopback().repliesTransmitted().uint32());
+            }
+            builder.loopbackAttributes(lbEntryBuilder.build());
+        }
+
+        if (yangMep.remoteMepDatabase() != null &&
+                yangMep.remoteMepDatabase().remoteMep() != null) {
+            for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                    .maintenancedomain.maintenanceassociation
+                    .maintenanceassociationendpoint.remotemepdatabase.RemoteMep
+                    rmep:yangMep.remoteMepDatabase().remoteMep()) {
+                builder = (MepEntry.MepEntryBuilder) builder.addToActiveRemoteMepList(
+                        getApiRemoteMepFromYangRemoteMep(rmep));
+            }
+        }
+
+        if (yangMep.ccmLtmPriority() != null) {
+            builder = (MepEntry.MepEntryBuilder) builder.ccmLtmPriority(
+                    Priority.values()[yangMep.ccmLtmPriority().uint8()]);
+        }
+
+        //And the the state attributes
+        builder = (MepEntry.MepEntryBuilder) builder
+                .macAddress(MacAddress.valueOf(yangMep.macAddress().toString()))
+                .administrativeState(yangMep.administrativeState())
+                .cciEnabled(yangMep.continuityCheck().cciEnabled());
+
+        AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedyangMep = yangMep
+                .augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+
+        if (augmentedyangMep != null) {
+            if (augmentedyangMep.lastDefectSent() != null) {
+                builder = (MepEntry.MepEntryBuilder) builder
+                .activeXconCcmDefect(augmentedyangMep.lastDefectSent().bits()
+                            .get(Bits.CROSS_CONNECT_CCM.bits()))
+                .activeErrorCcmDefect(augmentedyangMep.lastDefectSent().bits()
+                        .get(Bits.INVALID_CCM.bits()))
+                .activeMacStatusDefect(augmentedyangMep.lastDefectSent().bits()
+                        .get(Bits.REMOTE_MAC_ERROR.bits()))
+                .activeRdiCcmDefect(augmentedyangMep.lastDefectSent().bits()
+                        .get(Bits.REMOTE_RDI.bits()))
+                .activeRemoteCcmDefect(augmentedyangMep.lastDefectSent().bits()
+                        .get(Bits.REMOTE_INVALID_CCM.bits()));
+            }
+        }
+
+        return builder.buildEntry();
+    }
+
+    private RemoteMepEntry getApiRemoteMepFromYangRemoteMep(
+            org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.
+            maintenanceassociation.maintenanceassociationendpoint.remotemepdatabase.
+            RemoteMep yangRemoteMep) throws CfmConfigException {
+
+        MepId remoteMepId = MepId.valueOf((short) yangRemoteMep.remoteMepId().uint16());
+        RemoteMepStateTypeEnum state = RemoteMepStateTypeEnum.FAILED;
+        if (yangRemoteMep.remoteMepState() != null) {
+            state = yangRemoteMep.remoteMepState().enumeration();
+        }
+        RemoteMepEntryBuilder rmepBuilder = DefaultRemoteMepEntry.builder(
+                    remoteMepId, RemoteMepState.valueOf("RMEP_" + state.name()))
+                .rdi(yangRemoteMep.rdi());
+        if (yangRemoteMep.macAddress() != null) {
+            rmepBuilder = rmepBuilder.macAddress(
+                    MacAddress.valueOf(yangRemoteMep.macAddress().toString()));
+        }
+        if (yangRemoteMep.failedOkTime() != null) {
+            //Currently EA1000 is reporting this as 1/1000s even though yang type
+            // is time ticks 1/100s - to be fixed
+            rmepBuilder = rmepBuilder.failedOrOkTime(Duration.ofMillis(
+                    yangRemoteMep.failedOkTime().uint32()));
+        }
+        if (yangRemoteMep.portStatusTlv() != null) {
+            rmepBuilder = rmepBuilder.portStatusTlvType(PortStatusTlvType.valueOf(
+                    "PS_" + yangRemoteMep.portStatusTlv().enumeration().name()));
+        }
+        if (yangRemoteMep.interfaceStatusTlv() != null) {
+            rmepBuilder = rmepBuilder.interfaceStatusTlvType(InterfaceStatusTlvType.valueOf(
+                    "IS_" + yangRemoteMep.interfaceStatusTlv().enumeration().name()));
+        }
+        return rmepBuilder.build();
+    }
+
+    private static short getMaNumericId(MaintenanceDomain md, MaIdShort maId) {
+        return md.maintenanceAssociationList().stream()
+                .filter(ma -> maId.equals(ma.maId()))
+                .findFirst().get().maNumericId();
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java
new file mode 100644
index 0000000..b8258df
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java
@@ -0,0 +1,975 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.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);
+                return flowEntryCollection;
+            }
+        }
+
+
+        //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/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java
new file mode 100644
index 0000000..03405d7
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi;
+
+
+import static org.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) {
+                        Thread.currentThread().interrupt();
+                        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/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java
new file mode 100644
index 0000000..3631f2e
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.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/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java
new file mode 100755
index 0000000..5a8fddb
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java
@@ -0,0 +1,740 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Optional;
+
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService.DmEntryParts;
+import org.onosproject.drivers.microsemi.yang.utils.IetfYangTypesUtils;
+import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepTsCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.incubator.net.l2monitoring.soam.StartTime.StartTimeOption;
+import org.onosproject.incubator.net.l2monitoring.soam.StopTime.StopTimeOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatCurrent;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatHistory;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.DmEntryBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent.DmStatCurrentBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory.DmStatHistoryBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.delaymeasurementbinsgroup.bins.FrameDelay;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.delaymeasurementbinsgroup.bins.InterFrameDelayVariation;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.DefaultDelayMeasurements;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.DelayMeasurements;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DefaultDelayMeasurement;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.HistoryStats;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.MeasurementEnable;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.MessagePeriodEnum;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep.DefaultMepId;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of SoamDmProgrammable for Microsemi EA1000.
+ */
+public class EA1000SoamDmProgrammable extends AbstractHandlerBehaviour
+        implements SoamDmProgrammable {
+    private static final Logger log = getLogger(EA1000SoamDmProgrammable.class);
+    private static final int MAX_DMS = 2;
+
+    public EA1000SoamDmProgrammable() {
+        log.debug("Loaded handler behaviour EA1000SoamDmProgrammable");
+    }
+
+    @Override
+    public Collection<DelayMeasurementEntry> getAllDms(
+            MdId mdName, MaIdShort maName, MepId mepId)
+                    throws CfmConfigException, SoamConfigException {
+        return getAllDmsOrOneDm(mdName, maName, mepId, null, DmEntryParts.ALL_PARTS);
+    }
+
+    @Override
+    public DelayMeasurementEntry getDm(MdId mdName, MaIdShort maName,
+            MepId mepId, SoamId dmId) throws CfmConfigException, SoamConfigException {
+        Collection<DelayMeasurementEntry> allDms =
+                getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.ALL_PARTS);
+
+        if (allDms != null && allDms.size() >= 1) {
+            return allDms.toArray(new DelayMeasurementEntry[1])[0];
+        }
+        return null;
+    }
+
+    @Override
+    public DelayMeasurementStatCurrent getDmCurrentStat(
+            MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId)
+                    throws CfmConfigException, SoamConfigException {
+        Collection<DelayMeasurementEntry> dms =
+                getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.CURRENT_ONLY);
+
+        //There should be only one
+        if (dms != null && dms.size() == 1) {
+            return dms.toArray((new DelayMeasurementEntry[1]))[0].currentResult();
+        }
+        return null;
+    }
+
+    @Override
+    public Collection<DelayMeasurementStatHistory> getDmHistoricalStats(
+            MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId)
+                    throws CfmConfigException, SoamConfigException {
+        Collection<DelayMeasurementEntry> dms =
+                getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.HISTORY_ONLY);
+
+        //There should only be one in the result
+        if (dms != null && dms.size() == 1) {
+            return dms.toArray(new DelayMeasurementEntry[1])[0].historicalResults();
+        }
+        return new ArrayList<>();
+    }
+
+    @Override
+    public Optional<SoamId> createDm(
+            MdId mdName, MaIdShort maName, MepId mepId, DelayMeasurementCreate dm)
+            throws CfmConfigException, SoamConfigException {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        MseaCfm mepEssentials;
+        try {
+            mepEssentials = mseaCfmService.getMepEssentials(
+                                        mdName, maName, mepId, session);
+        } catch (NetconfException e) {
+            throw new CfmConfigException(e);
+        }
+        short mdNumber = mepEssentials.mefCfm().maintenanceDomain().get(0).id();
+        short maNumber = mepEssentials.mefCfm().maintenanceDomain().get(0)
+                .maintenanceAssociation().get(0).id();
+        MaintenanceAssociationEndPoint currentMep =
+                mepEssentials.mefCfm().maintenanceDomain().get(0)
+                .maintenanceAssociation().get(0)
+                .maintenanceAssociationEndPoint().get(0);
+        AugmentedMseaCfmMaintenanceAssociationEndPoint currAugMep =
+                currentMep.augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+
+        if (dm.startTime() != null && !dm.startTime().option().equals(StartTimeOption.IMMEDIATE)) {
+            throw new SoamConfigException(
+                    "Only start time: IMMEDIATE is supported on EA1000");
+        } else if (dm.stopTime() != null && !dm.stopTime().option().equals(StopTimeOption.NONE)) {
+            throw new SoamConfigException(
+                    "Only stop time: NONE is supported on EA1000");
+        }
+
+        MessagePeriodEnum mpEnum = MessagePeriodEnum.YANGAUTOPREFIX1000MS;
+        if (dm.messagePeriod() != null) {
+            if (dm.messagePeriod().toMillis() == 1000) {
+                mpEnum = MessagePeriodEnum.YANGAUTOPREFIX1000MS;
+            } else if (dm.messagePeriod().toMillis() == 100) {
+                mpEnum = MessagePeriodEnum.YANGAUTOPREFIX100MS;
+            } else if (dm.messagePeriod().toMillis() == 10) {
+                mpEnum = MessagePeriodEnum.YANGAUTOPREFIX10MS;
+            } else if (dm.messagePeriod().toMillis() == 3) {
+                mpEnum = MessagePeriodEnum.YANGAUTOPREFIX3MS;
+            } else {
+                throw new SoamConfigException("EA1000 supports only Message "
+                    + "Periods 1000ms,100ms, 10ms and 3ms for Delay Measurements");
+            }
+        }
+
+        short lastDmId = 0;
+        short newDmId = 1;
+        if (currAugMep != null && currAugMep.delayMeasurements() != null) {
+            Iterator<DelayMeasurement> dmIterator =
+                    currAugMep.delayMeasurements().delayMeasurement().iterator();
+            while (dmIterator.hasNext()) {
+                lastDmId = dmIterator.next().dmId();
+            }
+
+            if (lastDmId == 0) {
+                //Indicates that no DM was found under this MEP.
+                //We will just create the next one as 1
+                log.info("Creating DM 1");
+                newDmId = 1;
+            } else if (lastDmId == 1) {
+                log.info("Creating DM 2");
+                newDmId = 2;
+            } else if (lastDmId == MAX_DMS) {
+                log.warn("Maximum number of DMs (2) have been created on MEP {}/{}/{}"
+                        + "on device {} - delete DMs before creating more",
+                        mdName.mdName(), maName.maName(), mepId.id(),
+                        handler().data().deviceId());
+                throw new CfmConfigException("Maximum number of DMs (2) exist on MEP. "
+                        + "Please call abort on a DM before creating more");
+            }
+        }
+
+
+        DelayMeasurement dmBuilder = new DefaultDelayMeasurement();
+        dmBuilder.dmId((short) newDmId);
+        DefaultMepId dMepId = new DefaultMepId();
+        dMepId.mepId(MepIdType.of(dm.remoteMepId().id()));
+        dmBuilder.remoteMep(dMepId);
+
+        BitSet measurementEnable = getMeasurementEnabledSet(dm.measurementsEnabled());
+        if (measurementEnable != null && !measurementEnable.isEmpty()) {
+            dmBuilder.measurementEnable(measurementEnable);
+        }
+        dmBuilder.administrativeState(true);
+        dmBuilder.priority(PriorityType.of((short) dm.priority().ordinal()));
+        dmBuilder.messagePeriod(mpEnum);
+
+        if (dm.numberIntervalsStored() != null) {
+            //Here we pass in num intervals stored - for EA1000 32 are always
+            //stored so it's not controllable - instead we set number returned
+            dmBuilder.numberIntervalsReturned(dm.numberIntervalsStored());
+        }
+
+        if (dm.measurementInterval() != null) {
+            dmBuilder.measurementInterval(dm.measurementInterval().toMinutes());
+        }
+        if (dm.frameSize() != null) {
+            dmBuilder.frameSize(dm.frameSize());
+        }
+        DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+                new DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint();
+        DelayMeasurements dms = new DefaultDelayMeasurements();
+        dms.addToDelayMeasurement(dmBuilder);
+        augmentedMep.delayMeasurements(dms);
+
+        MaintenanceAssociationEndPoint mep =
+                new DefaultMaintenanceAssociationEndPoint();
+        mep.mepIdentifier(MepIdType.of(mepId.id()));
+        mep.addAugmentation(augmentedMep);
+
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+            .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+        yangMa.id(maNumber);
+        yangMa.addToMaintenanceAssociationEndPoint(mep);
+
+        org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                .MaintenanceDomain yangMd = new DefaultMaintenanceDomain();
+        yangMd.id(mdNumber);
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+            return Optional.empty();
+        } catch (NetconfException e) {
+            log.error("Unable to create DM {}/{}/{} on device {}",
+                    mdName, maName, mepId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to create DM :" + e.getMessage());
+        }
+
+    }
+
+    @Override
+    public void abortDm(MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId)
+            throws CfmConfigException {
+        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session = controller.getDevicesMap().get(handler().data()
+                .deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService = checkNotNull(handler()
+                .get(MseaCfmNetconfService.class));
+        CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class));
+
+
+        org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain
+        .maintenanceassociation.maintenanceassociationendpoint
+        .augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements
+        .DelayMeasurement dm = new DefaultDelayMeasurement();
+         dm.dmId(dmId.id().shortValue());
+
+        DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+                new DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint();
+        DelayMeasurements ddms = new DefaultDelayMeasurements();
+        ddms.addToDelayMeasurement(dm);
+        augmentedMep.delayMeasurements(ddms);
+
+        MaintenanceAssociationEndPoint mep =
+                new DefaultMaintenanceAssociationEndPoint();
+        mep.mepIdentifier(MepIdType.of(mepId.id()));
+        mep.addAugmentation(augmentedMep);
+
+
+        short mdNumericId = cfmMdService.getMaintenanceDomain(mdName).get().mdNumericId();
+        short maNumericId = cfmMdService
+                .getMaintenanceAssociation(mdName, maName).get().maNumericId();
+
+        DefaultMaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+        yangMa.id(maNumericId);
+        yangMa.addToMaintenanceAssociationEndPoint(mep);
+
+        DefaultMaintenanceDomain yangMd = new DefaultMaintenanceDomain();
+        yangMd.id(mdNumericId);
+        yangMd.addToMaintenanceAssociation(yangMa);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(yangMd);
+
+        MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+        mseaCfmOpParam.mefCfm(mefCfm);
+
+        try {
+            mseaCfmService.deleteMseaCfmDm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+        } catch (NetconfException e) {
+            log.error("Unable to delete DM {}/{}/{}/{} on device {}",
+                    mdName, maName, mepId, dm.dmId(), handler().data().deviceId());
+            throw new CfmConfigException("Unable to delete DM :" + e.getMessage());
+        }
+    }
+
+    @Override
+    public void abortDm(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void clearDelayHistoryStats(MdId mdName, MaIdShort maName,
+            MepId mepId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void clearDelayHistoryStats(MdId mdName, MaIdShort maName,
+            MepId mepId, SoamId dmId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public Collection<LossMeasurementEntry> getAllLms(MdId mdName,
+            MaIdShort maName, MepId mepId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public LossMeasurementEntry getLm(MdId mdName, MaIdShort maName,
+            MepId mepId, SoamId lmId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public LossMeasurementStatCurrent getLmCurrentStat(MdId mdName,
+            MaIdShort maName, MepId mepId, SoamId lmId) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public Collection<LossMeasurementStatCurrent> getLmHistoricalStats(
+            MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public Optional<SoamId> createLm(MdId mdName, MaIdShort maName, MepId mepId,
+                             LossMeasurementCreate lm) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void abortLm(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void abortLm(MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId)
+            throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void clearLossHistoryStats(MdId mdName, MaIdShort maName,
+            MepId mepId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void clearLossHistoryStats(MdId mdName, MaIdShort maName,
+            MepId mepId, SoamId lmId) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void createTestSignal(MdId mdName, MaIdShort maName, MepId mepId,
+            MepTsCreate tsCreate) throws CfmConfigException {
+        throw new UnsupportedOperationException("Not supported by EA1000");
+    }
+
+    @Override
+    public void abortTestSignal(MdId mdName, MaIdShort maName, MepId mepId)
+            throws CfmConfigException {
+        throw new UnsupportedOperationException("Not supported by EA1000");
+    }
+
+    private static DelayMeasurementEntry buildApiDmFromYangDm(DelayMeasurement dm,
+            MdId mdName, MaIdShort maName, MepId mepId)
+                    throws SoamConfigException, CfmConfigException {
+
+        org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep
+        .MepId rmep = MepIdUtil.convertRemoteMepId(dm.remoteMep());
+
+        DmEntryBuilder dmBuilder = (DmEntryBuilder) DefaultDelayMeasurementEntry.builder(
+                SoamId.valueOf(dm.dmId()), DmType.DMDMM, Version.Y17312011,
+                MepId.valueOf((short) ((MepIdType) rmep.mepId()).uint16()),
+                Priority.values()[dm.priority().uint8()]);
+        if (dm.sessionStatus() != null) {
+            dmBuilder = dmBuilder.sessionStatus(SessionStatus.valueOf(
+                    dm.sessionStatus().enumeration().name()));
+        }
+
+        if (dm.frameDelayTwoWay() != null) {
+            dmBuilder = dmBuilder.frameDelayTwoWay(Duration.ofNanos(
+                    dm.frameDelayTwoWay().uint32() * 1000));
+        }
+        if (dm.interFrameDelayVariationTwoWay() != null) {
+            dmBuilder = dmBuilder.interFrameDelayVariationTwoWay(Duration.ofNanos(
+                    dm.interFrameDelayVariationTwoWay().uint32() * 1000));
+        }
+
+        if (dm.frameSize() != 0) {
+            dmBuilder = (DmEntryBuilder) dmBuilder.frameSize((short) dm.frameSize());
+        }
+
+        if (dm.messagePeriod() != null) {
+            switch (dm.messagePeriod()) {
+                case YANGAUTOPREFIX1000MS:
+                    dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(1000));
+                    break;
+                case YANGAUTOPREFIX100MS:
+                    dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(100));
+                    break;
+                case YANGAUTOPREFIX10MS:
+                    dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(10));
+                    break;
+                case YANGAUTOPREFIX3MS:
+                    dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(3));
+                    break;
+                default:
+                    throw new SoamConfigException("EA1000 supports only 1000,"
+                            + "100, 10 and 3ms for Message Period on DM");
+            }
+        }
+
+        Collection<MeasurementOption> moSet =
+            EA1000SoamDmProgrammable.getMeasurementOptions(dm.measurementEnable());
+        moSet.forEach(dmBuilder::addToMeasurementsEnabled);
+
+        dmBuilder = dmBuilder
+                .currentResult(buildApiDmCurrFromYangDmCurr(dm, mdName, maName, mepId));
+
+        for (DelayMeasurementStatHistory historyStat:
+                            buildApiDmHistFromYangDm(dm, mdName, maName, mepId)) {
+            dmBuilder = dmBuilder.addToHistoricalResults(historyStat);
+        }
+
+        return dmBuilder.build();
+    }
+
+    private static Collection<DelayMeasurementStatHistory> buildApiDmHistFromYangDm(
+            DelayMeasurement dm, MdId mdName, MaIdShort maName, MepId mepId)
+                    throws SoamConfigException, CfmConfigException {
+
+        Collection<DelayMeasurementStatHistory> historyStatsCollection = new ArrayList<>();
+        if (dm.historyStats() != null) {
+            for (HistoryStats dmHistory:dm.historyStats()) {
+                DmStatHistoryBuilder historyBuilder =
+                        DefaultDelayMeasurementStatHistory.builder(
+                                SoamId.valueOf((int) dmHistory.id()),
+                                Duration.ofMillis(dmHistory.elapsedTime() * 10), //Values are in 1/100th sec
+                                dmHistory.suspectStatus() != null ?
+                                        dmHistory.suspectStatus().yangAutoPrefixBoolean() : false);
+                historyBuilder = historyBuilder.endTime(
+                        IetfYangTypesUtils.fromYangDateTimeToInstant(dmHistory.endTime()));
+
+                if (dmHistory.frameDelayTwoWayMin() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .frameDelayTwoWayMin(Duration.ofNanos(dmHistory.frameDelayTwoWayMin().uint32() * 1000));
+                }
+
+                if (dmHistory.frameDelayTwoWayMax() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .frameDelayTwoWayMax(Duration.ofNanos(dmHistory.frameDelayTwoWayMax().uint32() * 1000));
+                }
+
+                if (dmHistory.frameDelayTwoWayAverage() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                           .frameDelayTwoWayAvg(Duration.ofNanos(dmHistory.frameDelayTwoWayAverage().uint32() * 1000));
+                }
+
+                if (dmHistory.interFrameDelayVariationTwoWayMin() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .interFrameDelayVariationTwoWayMin(Duration.ofNanos(
+                                    dmHistory.interFrameDelayVariationTwoWayMin().uint32() * 1000));
+                }
+
+                if (dmHistory.interFrameDelayVariationTwoWayMax() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .interFrameDelayVariationTwoWayMax(Duration.ofNanos(
+                                    dmHistory.interFrameDelayVariationTwoWayMax().uint32() * 1000));
+                }
+
+                if (dmHistory.interFrameDelayVariationTwoWayAverage() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .interFrameDelayVariationTwoWayAvg(Duration.ofNanos(
+                                    dmHistory.interFrameDelayVariationTwoWayAverage().uint32() * 1000));
+                }
+
+                if (dmHistory.soamPdusReceived() != null) {
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .soamPdusReceived(Integer.valueOf((int) dmHistory.soamPdusReceived().uint32()));
+                }
+
+                if (dmHistory.bins() != null && dmHistory.bins().frameDelay() != null) {
+                    Map<Duration, Integer> frameDelayTwoWayBins = new HashMap<>();
+                    for (FrameDelay fdBin:dmHistory.bins().frameDelay()) {
+                        frameDelayTwoWayBins.put(
+                                Duration.ofNanos(fdBin.lowerBound().uint32() * 1000),
+                                Integer.valueOf((int) fdBin.counter().uint32()));
+                    }
+                    historyBuilder = (DmStatHistoryBuilder) historyBuilder
+                            .frameDelayTwoWayBins(frameDelayTwoWayBins);
+                }
+
+                if (dmHistory.bins() != null && dmHistory.bins().interFrameDelayVariation() != null) {
+                    Map<Duration, Integer> ifdvTwoWayBins = new HashMap<>();
+                    for (InterFrameDelayVariation ifdvBin:dmHistory.bins().interFrameDelayVariation()) {
+                        ifdvTwoWayBins.put(
+                                Duration.ofNanos(ifdvBin.lowerBound().uint32() * 1000),
+                                Integer.valueOf((int) ifdvBin.counter().uint32()));
+                    }
+                    historyBuilder =
+                            (DmStatHistoryBuilder) historyBuilder.interFrameDelayVariationTwoWayBins(ifdvTwoWayBins);
+                }
+
+                historyStatsCollection.add((DelayMeasurementStatHistory) historyBuilder.build());
+            }
+        }
+        return historyStatsCollection;
+    }
+
+    private static DelayMeasurementStatCurrent buildApiDmCurrFromYangDmCurr(
+            DelayMeasurement dm, MdId mdName, MaIdShort maName, MepId mepId)
+                    throws SoamConfigException, CfmConfigException {
+        if (dm == null || dm.currentStats() == null || mdName == null ||
+                maName == null || mepId == null) {
+            return null;
+        }
+
+        DmStatCurrentBuilder statCurrBuilder =
+           DefaultDelayMeasurementStatCurrent.builder(
+                Duration.ofMillis(dm.currentStats().elapsedTime() * 10), //Values are in 1/100th sec
+                dm.currentStats().suspectStatus() != null ?
+                    dm.currentStats().suspectStatus().yangAutoPrefixBoolean() : false);
+        statCurrBuilder = statCurrBuilder.startTime(
+                IetfYangTypesUtils.fromYangDateTimeToInstant(dm.currentStats().startTime()));
+
+        if (dm.currentStats().frameDelayTwoWayMin() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .frameDelayTwoWayMin(Duration.ofNanos(
+                            dm.currentStats().frameDelayTwoWayMin().uint32() * 1000));
+        }
+
+        if (dm.currentStats().frameDelayTwoWayMax() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .frameDelayTwoWayMax(Duration.ofNanos(
+                            dm.currentStats().frameDelayTwoWayMax().uint32() * 1000));
+        }
+
+        if (dm.currentStats().frameDelayTwoWayAverage() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                   .frameDelayTwoWayAvg(Duration.ofNanos(
+                           dm.currentStats().frameDelayTwoWayAverage().uint32() * 1000));
+        }
+
+        if (dm.currentStats().interFrameDelayVariationTwoWayMin() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .interFrameDelayVariationTwoWayMin(Duration.ofNanos(
+                            dm.currentStats().interFrameDelayVariationTwoWayMin().uint32() * 1000));
+        }
+
+        if (dm.currentStats().interFrameDelayVariationTwoWayMax() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .interFrameDelayVariationTwoWayMax(Duration.ofNanos(
+                            dm.currentStats().interFrameDelayVariationTwoWayMax().uint32() * 1000));
+        }
+
+        if (dm.currentStats().interFrameDelayVariationTwoWayAverage() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .interFrameDelayVariationTwoWayAvg(Duration.ofNanos(
+                            dm.currentStats().interFrameDelayVariationTwoWayAverage().uint32() * 1000));
+        }
+
+        if (dm.currentStats().soamPdusReceived() != null) {
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder
+                    .soamPdusReceived(Integer.valueOf((int) dm.currentStats().soamPdusReceived().uint32()));
+        }
+
+        if (dm.currentStats().bins() != null && dm.currentStats().bins().frameDelay() != null) {
+            Map<Duration, Integer> frameDelayTwoWayBins = new HashMap<>();
+            for (FrameDelay fdBin:dm.currentStats().bins().frameDelay()) {
+                frameDelayTwoWayBins.put(
+                        Duration.ofNanos(fdBin.lowerBound().uint32() * 1000),
+                        Integer.valueOf((int) fdBin.counter().uint32()));
+            }
+            statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder.frameDelayTwoWayBins(frameDelayTwoWayBins);
+        }
+
+        if (dm.currentStats().bins() != null && dm.currentStats().bins().interFrameDelayVariation() != null) {
+            Map<Duration, Integer> ifdvTwoWayBins = new HashMap<>();
+            for (InterFrameDelayVariation ifdvBin:dm.currentStats().bins().interFrameDelayVariation()) {
+                ifdvTwoWayBins.put(
+                        Duration.ofNanos(ifdvBin.lowerBound().uint32() * 1000),
+                        Integer.valueOf((int) ifdvBin.counter().uint32()));
+            }
+            statCurrBuilder =
+                    (DmStatCurrentBuilder) statCurrBuilder.interFrameDelayVariationTwoWayBins(ifdvTwoWayBins);
+        }
+
+        return (DelayMeasurementStatCurrent) statCurrBuilder.build();
+    }
+
+    private Collection<DelayMeasurementEntry> getAllDmsOrOneDm(
+            MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId, DmEntryParts parts)
+                    throws CfmConfigException, SoamConfigException {
+        NetconfController controller =
+                checkNotNull(handler().get(NetconfController.class));
+        NetconfSession session =
+                controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+        MseaCfmNetconfService mseaCfmService =
+                checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+        Collection<DelayMeasurementEntry> dmResults = new ArrayList<>();
+        try {
+            MseaCfm mseacfm =
+                    mseaCfmService.getSoamDm(mdName, maName, mepId, dmId, parts, session);
+            for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                    .MaintenanceDomain replyMd:mseacfm.mefCfm().maintenanceDomain()) {
+                for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
+                        .mefcfm.maintenancedomain.MaintenanceAssociation replyMa:
+                            replyMd.maintenanceAssociation()) {
+                    for (MaintenanceAssociationEndPoint replyMep:
+                            replyMa.maintenanceAssociationEndPoint()) {
+                        AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+                                replyMep.augmentation(
+                                        DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+                        if (augmentedMep == null ||
+                                augmentedMep.delayMeasurements() == null ||
+                                augmentedMep.delayMeasurements()
+                                        .delayMeasurement().isEmpty()) {
+                            log.info("No Delay Measurements retrieved from MEP " +
+                                        mdName + "/" + maName + "/" + mepId);
+                        } else {
+                            for (org.onosproject.yang.gen.v1.mseasoampm.rev20160229
+                                    .mseasoampm.mefcfm.maintenancedomain.maintenanceassociation
+                                    .maintenanceassociationendpoint
+                                    .augmentedmseacfmmaintenanceassociationendpoint
+                                    .delaymeasurements.DelayMeasurement dm
+                                        :augmentedMep.delayMeasurements().delayMeasurement()) {
+                                dmResults.add(buildApiDmFromYangDm(dm, mdName, maName, mepId));
+                            }
+                        }
+                    }
+                }
+            }
+            return dmResults;
+        } catch (NetconfException e) {
+            log.error("Unable to get MEP {}/{}/{} on device {}",
+                    mdName, maName, mepId, handler().data().deviceId());
+            throw new CfmConfigException("Unable to create MEP :" + e.getMessage());
+        }
+    }
+
+
+    protected static BitSet getMeasurementEnabledSet(
+            Collection<MeasurementOption> measEnabled) throws SoamConfigException {
+        BitSet measurementEnable = new BitSet();
+        try {
+            measEnabled.forEach(mo -> {
+                    MeasurementEnable me = MeasurementEnable.valueOf(mo.name());
+                    measurementEnable.set(me.measurementEnable());
+            });
+        } catch (IllegalArgumentException e) {
+            throw new SoamConfigException(
+                    "Measurement Option is not supported on EA1000: ", e);
+        }
+
+        return measurementEnable;
+    }
+
+    protected static Collection<MeasurementOption> getMeasurementOptions(BitSet meBs) {
+        Collection<MeasurementOption> meList = new ArrayList<>();
+        if (meBs != null && !meBs.isEmpty()) {
+            for (int i = 0; i < meBs.size(); i++) {
+                if (meBs.get(i)) {
+                    meList.add(MeasurementOption.valueOf(MeasurementEnable.of(i).name()));
+                }
+            }
+        }
+
+        return meList;
+    }
+}
\ No newline at end of file
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java
new file mode 100644
index 0000000..faf2007
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.time.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 augmentedSysStatePlatform =
+                        (AugmentedSysPlatform) system.systemState()
+                        .platform().augmentation(DefaultAugmentedSysPlatform.class);
+                if (augmentedSysStatePlatform != null && augmentedSysStatePlatform.deviceIdentification() != null) {
+                    serialNumber = augmentedSysStatePlatform.deviceIdentification().serialNumber();
+                } else {
+                    log.warn("Serial Number of device not available: {}", handler().data().deviceId());
+                }
+                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 {}",
+                            handler().data().deviceId(), 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(), e);
+        }
+
+        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/ea1000/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java
new file mode 100644
index 0000000..41f297e
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import 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/ea1000/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java
new file mode 100644
index 0000000..a556765
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import 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/ea1000/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java
new file mode 100644
index 0000000..039b760
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi;
+
+import static org.onosproject.netconf.DatastoreId.datastore;
+import static org.slf4j.LoggerFactory.getLogger;
+
+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.onosproject.netconf.NetconfException;
+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(datastore(type.replace("cfgType=", "")));
+        } catch (NetconfException e) {
+            log.error("Configuration could not be retrieved {}", e.getMessage());
+        }
+        return UNABLE_TO_READ_CONFIG;
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java
new file mode 100644
index 0000000..3eb43ac
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+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/ea1000/src/main/java/org/onosproject/drivers/microsemi/package-info.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/package-info.java
new file mode 100644
index 0000000..994b65b
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for Microsemi device drivers.
+ */
+package org.onosproject.drivers.microsemi;
\ No newline at end of file
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java
new file mode 100644
index 0000000..d72050e
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import java.time.OffsetDateTime;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam;
+
+/**
+ * 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 systemShutdown.
+     *
+     * @param session An active NETCONF session
+     * @throws NetconfException if the session has any error
+     */
+    void systemShutdown(NetconfSession session) throws NetconfException;
+
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java
new file mode 100644
index 0000000..cbe41ba
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+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;
+
+import java.util.Optional;
+
+/**
+ * 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 minimal set of attributes of MEP.
+     *
+     * @param mdId The name of the MD
+     * @param maId The name of the MA
+     * @param mepId The ID of the MEP
+     * @param session An active NETCONF session
+     * @return mseaCfm
+     * @throws NetconfException if the session has any error
+     */
+    MseaCfm getMepEssentials(MdId mdId, MaIdShort maId, MepId mepId,
+                             NetconfSession session) throws NetconfException;
+
+    /**
+     * Returns full set of attributes of MEP.
+     * This returns config and state attributes of all children of the MEP
+     * except for Delay Measurements and Loss Measurements - these have to be
+     * retrieved separately, because of their potential size
+     * @param mdId The name of the MD
+     * @param maId The name of the MA
+     * @param mepId The ID of the MEP
+     * @param session An active NETCONF session
+     * @return mseaCfm
+     * @throws NetconfException if the session has any error
+     */
+    MseaCfm getMepFull(MdId mdId, MaIdShort maId, MepId mepId,
+            NetconfSession session) throws NetconfException;
+
+
+    /**
+     * Returns set of all MepIds from one Md or Ma or all.
+     *
+     * @param mdIdOptional An MdId to filter by, or empty to select all
+     * @param maIdOptional An MaId to filter by, or empty to select all
+     * @param session An active NETCONF session
+     * @param targetDs one of running, candidate or startup
+     * @return mseaCfm
+     * @throws NetconfException if the session has any error
+     */
+    MseaCfm getMepIds(Optional<MdId> mdIdOptional, Optional<MaIdShort> maIdOptional,
+                      NetconfSession session, DatastoreId targetDs) throws NetconfException;
+    /**
+     * Returns attributes of DM.
+     *
+     * @param mdId The name of the MD
+     * @param maId The name of the MA
+     * @param mepId The ID of the MEP
+     * @param dmId The Id of the Delay Measurement - if null then all DMs
+     * @param parts The parts of the DM to return
+     * @param session An active NETCONF session
+     * @return mseaCfm
+     * @throws NetconfException if the session has any error
+     */
+    MseaCfm getSoamDm(MdId mdId, MaIdShort maId, MepId mepId,
+                  SoamId dmId, DmEntryParts parts, 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;
+
+    /**
+     * Deletes named Meps of mseaCfm.
+     * Expects to see a list of Meps
+     *
+     * @param mseaCfm value of mseaCfm
+     * @param session An active NETCONF session
+     * @param targetDs one of running, candidate or startup
+     * @return Boolean to indicate success or failure
+     * @throws NetconfException if the session has any error
+     * @throws CfmConfigException if the Cfm config has any error
+     */
+    boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session,
+                            DatastoreId targetDs) throws NetconfException, CfmConfigException;
+
+    /**
+     * Deletes named Ma of mseaCfm.
+     * Expects to see a list of Mas
+     *
+     * @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
+     * @throws CfmConfigException if the Cfm config has any error
+     */
+    boolean deleteMseaMa(MseaCfmOpParam mseaCfm, NetconfSession session,
+                            DatastoreId targetDs) throws NetconfException, CfmConfigException;
+
+    /**
+     * Deletes a remote Mep from an MA.
+     * Expects one or more RMeps
+     *
+     * @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
+     * @throws CfmConfigException if the Cfm config has any error
+     */
+    boolean deleteMseaMaRMep(MseaCfmOpParam mseaCfm, NetconfSession session,
+                         DatastoreId targetDs) throws NetconfException, CfmConfigException;
+
+    /**
+     * Deletes named Md of mseaCfm.
+     * Expects to see a list of Mds
+     *
+     * @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
+     * @throws CfmConfigException if the Cfm config has any error
+     */
+    boolean deleteMseaMd(MseaCfmOpParam mseaCfm, NetconfSession session,
+                            DatastoreId targetDs) throws NetconfException, CfmConfigException;
+
+    /**
+     * Deletes named delay measurements of mseaCfm.
+     * Expects to see a list of Delay Measurements
+     *
+     * @param mseaCfm value of mseaCfm
+     * @param session An active NETCONF session
+     * @param targetDs one of running, candidate or startup
+     * @return Boolean to indicate success or failure
+     * @throws NetconfException if the session has any error
+     * @throws CfmConfigException if the Cfm config has any error
+     */
+    boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session,
+                       DatastoreId targetDs) throws NetconfException, CfmConfigException;
+
+    /**
+     * 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;
+
+    public enum DmEntryParts {
+        ALL_PARTS,
+        CURRENT_ONLY,
+        HISTORY_ONLY;
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java
new file mode 100644
index 0000000..e845e59
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java
new file mode 100644
index 0000000..1501dfb
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi.yang;
+
+import 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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java
new file mode 100644
index 0000000..a5b8a2d
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+/**
+ * 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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java
new file mode 100644
index 0000000..cb0e4bd
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java
new file mode 100644
index 0000000..a2932d2
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java
new file mode 100644
index 0000000..9c91840
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package 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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
new file mode 100644
index 0000000..074aad4
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.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.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.CcmIntervalEnum;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.lossmeasurements.lossmeasurement.MessagePeriodEnum;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceData;
+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;
+
+    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 = null;
+    protected YangSerializerContext yCtx = null;
+
+    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>)");
+    protected static final Pattern REGEX_RPC_OK =
+            Pattern.compile("\\R?\\s*(<ok/>)\\R?");
+    @Activate
+    public void activate() {
+        Set<YangSerializer> yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers();
+        xSer = (XmlSerializer) yangSer.stream()
+                .filter(ser -> (ser instanceof XmlSerializer)).findFirst().get();
+        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 setNetconfObject()");
+        } else if (targetDs == null) {
+            throw new NetconfException("TargetDs is null when calling setNetconfObject()");
+        }
+
+        String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations);
+        log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        //Some encoded values just have to be replaced
+        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX3MS.toString(), "3ms");
+        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX10MS.toString(), "10ms");
+        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX100MS.toString(), "100ms");
+        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX1000MS.toString(), "1000ms");
+
+        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX3_3MS.toString(), "3.3ms");
+        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX10MS.toString(), "10ms");
+        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX100MS.toString(), "100ms");
+        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX1S.toString(), "1s");
+
+        return session.editConfig(targetDs, null, xmlQueryStr);
+    }
+
+    /**
+     * Internal method to generically call a NETCONF custom RPC from a set of YANG objects.
+     *
+     * @param customRpcInput A YANG object model
+     * @param rpcName The name of the RPC - replaces 'input' in the XML payload
+     * @param session A NETCONF session
+     * @return ModelObjectData value indicating success or failure of command
+     * @throws NetconfException if the session has any error
+     */
+    protected final ModelObjectData customRpcNetconf(
+            ModelObjectData customRpcInput, String rpcName, NetconfSession session)
+            throws NetconfException {
+        if (customRpcInput == null) {
+            throw new NetconfException("Input object cannot be null");
+        } else if (session == null) {
+            throw new NetconfException("Session is null when calling customRpcNetconf()");
+        }
+
+        String xmlQueryStr = encodeMoToXmlStr(customRpcInput, null);
+        xmlQueryStr = xmlQueryStr.replace("input", rpcName);
+        log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.doWrappedRpc(xmlQueryStr);
+        xmlResult = removeRpcReplyData(xmlResult);
+        if (REGEX_RPC_OK.matcher(xmlResult).matches()) {
+            return null;
+        }
+
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+    }
+
+    protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter,
+                                            List<AnnotatedNodeInfo> annotations)
+            throws NetconfException {
+        //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) throws NetconfException {
+        rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst("");
+        if (rpcReplyXml.contains("<rpc-error")) {
+            throw new NetconfException("NETCONF rpc-error: " + rpcReplyXml);
+        }
+
+        rpcReplyXml = REGEX_RPC_REPLY.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA_NS.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA.matcher(rpcReplyXml).replaceFirst("");
+        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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java
new file mode 100644
index 0000000..0411967
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.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.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam;
+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 systemShutdown(NetconfSession session) {
+        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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
new file mode 100644
index 0000000..ef40928
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
@@ -0,0 +1,651 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import java.util.ArrayList;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+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.mefcfm.MaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
+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.Optional;
+import java.util.regex.Pattern;
+
+/**
+ * Implementation of the MseaCfmServiceNetconf YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaCfmManager extends AbstractYangServiceImpl
+    implements MseaCfmNetconfService {
+
+    private static final String MSEA_CFM = "org.onosproject.drivers.microsemi.yang.mseacfmservice";
+
+    private static final String MSEA_CFM_NS = "http://www.microsemi.com/microsemi-edge-assure/msea-cfm";
+    private static final String MSEA_CFM_PM_NS = "http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm";
+
+    //FIXME Remove when the issue with Null bits on onos-yang-tools is sorted
+    @Deprecated
+    protected static final Pattern REGEX_EMPTY_ACTIVE_DEFECTS =
+            Pattern.compile("(<active-defects)[ ]?(/>)", Pattern.DOTALL);
+    //FIXME Remove when the issue with Null bits on onos-yang-tools is sorted
+    @Deprecated
+    protected static final Pattern REGEX_EMPTY_LAST_DEFECT_SENT =
+            Pattern.compile("(<msea-soam-fm:last-defect-sent)[ ]?(/>)", Pattern.DOTALL);
+    private static final String MEF_CFM = "mef-cfm";
+    private static final String MAINTENANCE_DOMAIN = "maintenance-domain";
+    public static final String ID = "id";
+    private static final String MAINTENANCE_ASSOCIATION = "maintenance-association";
+    private static final String TRANSMIT_LOOPBACK = "transmit-loopback";
+    private static final String ABORT_LOOPBACK = "abort-loopback";
+    private static final String MAINTENANCE_ASSOCIATION_END_POINT = "maintenance-association-end-point";
+    private static final String MEP_ID = "mep-id";
+    private static final String DELAY_MEASUREMENTS = "delay-measurements";
+    private static final String DELAY_MEASUREMENT = "delay-measurement";
+    private static final String DM_ID = "dm-id";
+    private static final String MEP_IDENTIFIER = "mep-identifier";
+    private static final String REMOTE_MEPS = "remote-meps";
+
+    @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(MdId mdId, MaIdShort maId, MepId mepId,
+                                    NetconfSession session) throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getMepEssentials()");
+        }
+
+        String xmlQueryStr = buildMepEssentialsQueryString(mdId, maId, mepId);
+        log.debug("Sending <get> for MEP essentials" +
+                " query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.get(xmlQueryStr, null);
+        xmlResult = removeRpcReplyData(xmlResult);
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(
+                compositeData.resourceData());
+
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        for (ModelObject mo:mod.modelObjects()) {
+            if (mo instanceof DefaultMefCfm) {
+                mseaCfm.mefCfm((DefaultMefCfm) mo);
+            }
+        }
+        return mseaCfm;
+    }
+
+    @Override
+    public MseaCfm getMepFull(MdId mdId, MaIdShort maId, MepId mepId,
+            NetconfSession session) throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getMepFull()");
+        }
+
+        String xmlQueryStr = buildMepFullQueryString(mdId, maId, mepId);
+        log.debug("Sending <get> for full MEP" +
+                " query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.get(xmlQueryStr, null);
+        xmlResult = removeRpcReplyData(xmlResult);
+        xmlResult = removeEmptyActiveDefects(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 getMepIds(Optional<MdId> mdIdOptional, Optional<MaIdShort> maIdOptional,
+             NetconfSession session, DatastoreId targetDs) throws NetconfException {
+
+        ModelObjectData.Builder moQueryBldr = DefaultModelObjectData.builder();
+
+        ArrayList<AnnotatedNodeInfo> annotations = new ArrayList<>();
+        String xmlQueryStr = encodeMoToXmlStr(moQueryBldr.build(), annotations);
+
+        log.debug("Sending <get> for full MEP" +
+                " query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.get(xmlQueryStr, null);
+        xmlResult = removeRpcReplyData(xmlResult);
+        xmlResult = removeEmptyActiveDefects(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(MdId mdName, MaIdShort maName, MepId mepId,
+                             SoamId dmId, DmEntryParts parts, NetconfSession session)
+                    throws NetconfException {
+        String xmlQueryStr = buildDmQueryString(mdName, maName, mepId, dmId, parts);
+        log.debug("Sending <get> for " +
+                " query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.get(xmlQueryStr, null);
+        xmlResult = removeRpcReplyData(xmlResult);
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        for (ModelObject mo:mod.modelObjects()) {
+            if (mo instanceof DefaultMefCfm) {
+                mseaCfm.mefCfm((DefaultMefCfm) mo);
+            }
+        }
+
+        return mseaCfm;
+    }
+
+    @Override
+    public boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session,
+            DatastoreId targetDs) throws NetconfException {
+
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+        return setNetconfObject(moQuery, session, targetDs, null);
+    }
+
+    @Override
+    public boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session,
+                            DatastoreId targetDs) throws NetconfException, CfmConfigException {
+
+        if (mseaCfm.mefCfm() == null) {
+            throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+        }
+        ModelObjectData mseCfmDmList = DefaultModelObjectData.builder()
+                .addModelObject(mseaCfm).build();
+
+        ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+        for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+            if (md.id() == 0) {
+                throw new CfmConfigException("An MD numeric ID must be given");
+            }
+            for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+                if (ma.id() == 0) {
+                    throw new CfmConfigException("An MA numeric ID must be given");
+                }
+                for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) {
+                    AugmentedMseaCfmMaintenanceAssociationEndPoint mepAugment =
+                        mep.augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+                    if (mepAugment != null && mepAugment.delayMeasurements() != null) {
+                        for (DelayMeasurement dm:mepAugment.delayMeasurements().delayMeasurement()) {
+                            ResourceId.Builder ridBuilder = ResourceId.builder()
+                                    .addBranchPointSchema("/", null)
+                                    .addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
+                                    .addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
+                                    .addKeyLeaf(ID, MSEA_CFM_NS, md.id())
+                                    .addBranchPointSchema(MAINTENANCE_ASSOCIATION, MSEA_CFM_NS)
+                                    .addKeyLeaf(ID, MSEA_CFM_NS, ma.id())
+                                    .addBranchPointSchema(MAINTENANCE_ASSOCIATION_END_POINT, MSEA_CFM_NS)
+                                    .addKeyLeaf(MEP_ID, MSEA_CFM_NS, mep.mepIdentifier())
+                                    .addBranchPointSchema(DELAY_MEASUREMENTS, MSEA_CFM_PM_NS)
+                                    .addBranchPointSchema(DELAY_MEASUREMENT, MSEA_CFM_PM_NS)
+                                    .addKeyLeaf(DM_ID, MSEA_CFM_PM_NS, dm.dmId());
+                            AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                                    .resourceId(ridBuilder.build())
+                                    .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                                    .build();
+                            anis.add(ani);
+                        }
+                    }
+                }
+            }
+        }
+
+        return setNetconfObject(mseCfmDmList, session, targetDs, anis);
+    }
+
+    @Override
+    public boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session,
+                                   DatastoreId targetDs) throws NetconfException, CfmConfigException {
+
+        if (mseaCfm.mefCfm() == null) {
+            throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+        }
+        ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+
+        ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+        for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+            if (md.id() == 0) {
+                throw new CfmConfigException("An MD numeric ID must be given");
+            }
+            for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+                if (ma.id() == 0) {
+                    throw new CfmConfigException("An MA numeric ID must be given");
+                }
+                for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) {
+                    ResourceId.Builder ridBuilder = ResourceId.builder()
+                            .addBranchPointSchema("/", null)
+                            .addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
+                            .addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
+                            .addKeyLeaf(ID, MSEA_CFM_NS, md.id())
+                            .addBranchPointSchema(MAINTENANCE_ASSOCIATION, MSEA_CFM_NS)
+                            .addKeyLeaf(ID, MSEA_CFM_NS, ma.id())
+                            .addBranchPointSchema(MAINTENANCE_ASSOCIATION_END_POINT, MSEA_CFM_NS)
+                            .addKeyLeaf(MEP_IDENTIFIER, MSEA_CFM_NS, mep.mepIdentifier().uint16());
+                    AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                            .resourceId(ridBuilder.build())
+                            .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                            .build();
+                    anis.add(ani);
+                }
+            }
+        }
+
+        return setNetconfObject(mseCfmMepList, session, targetDs, anis);
+    }
+
+    @Override
+    public boolean deleteMseaMa(MseaCfmOpParam mseaCfm, NetconfSession session,
+                                 DatastoreId targetDs) throws NetconfException, CfmConfigException {
+        if (mseaCfm.mefCfm() == null) {
+            throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+        }
+
+        ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+        ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+        for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+            if (md.id() == 0) {
+                throw new CfmConfigException("An MD numeric ID must be given");
+            }
+            for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+                if (ma.id() == 0) {
+                    throw new CfmConfigException("An MA numeric ID must be given");
+                }
+                ResourceId.Builder ridBuilder = ResourceId.builder()
+                        .addBranchPointSchema("/", null)
+                        .addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
+                        .addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
+                        .addKeyLeaf(ID, MSEA_CFM_NS, md.id())
+                        .addBranchPointSchema(MAINTENANCE_ASSOCIATION, MSEA_CFM_NS)
+                        .addKeyLeaf(ID, MSEA_CFM_NS, ma.id());
+
+                AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                .resourceId(ridBuilder.build())
+                .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                .build();
+                anis.add(ani);
+            }
+        }
+
+        return setNetconfObject(mseCfmMepList, session, targetDs, anis);
+    }
+
+    @Override
+    public boolean deleteMseaMaRMep(MseaCfmOpParam mseaCfm, NetconfSession session,
+                                 DatastoreId targetDs) throws NetconfException, CfmConfigException {
+        if (mseaCfm.mefCfm() == null) {
+            throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+        }
+
+        ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+        ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+        for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+            if (md.id() == 0) {
+                throw new CfmConfigException("An MD numeric ID must be given");
+            }
+            for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+                if (ma.id() == 0) {
+                    throw new CfmConfigException("An MA numeric ID must be given");
+                }
+                for (MepIdType rmep:ma.remoteMeps()) {
+                    ResourceId.Builder ridBuilder = ResourceId.builder()
+                            .addBranchPointSchema("/", null)
+                            .addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
+                            .addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
+                            .addKeyLeaf(ID, MSEA_CFM_NS, md.id())
+                            .addBranchPointSchema(MAINTENANCE_ASSOCIATION, MSEA_CFM_NS)
+                            .addKeyLeaf(ID, MSEA_CFM_NS, ma.id())
+                            .addLeafListBranchPoint(REMOTE_MEPS, MSEA_CFM_NS,
+                                    rmep.uint16());
+                    AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                            .resourceId(ridBuilder.build())
+                            .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                            .build();
+                    anis.add(ani);
+                }
+            }
+        }
+
+        return setNetconfObject(mseCfmMepList, session, targetDs, anis);
+    }
+
+
+    @Override
+    public boolean deleteMseaMd(MseaCfmOpParam mseaCfm, NetconfSession session,
+                                DatastoreId targetDs) throws NetconfException, CfmConfigException {
+        if (mseaCfm.mefCfm() == null) {
+            throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+        }
+        ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+
+        ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+        for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+            if (md.id() == 0) {
+                throw new CfmConfigException("An MD numeric ID must be given");
+            }
+            ResourceId.Builder ridBuilder = ResourceId.builder()
+                    .addBranchPointSchema("/", null)
+                    .addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
+                    .addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
+                    .addKeyLeaf(ID, MSEA_CFM_NS, md.id());
+            AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                    .resourceId(ridBuilder.build())
+                    .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                    .build();
+            anis.add(ani);
+        }
+
+        return setNetconfObject(mseCfmMepList, session, targetDs, anis);
+    }
+
+    /**
+     * Call RPCs on the device through NETCONF.
+     */
+    @Override
+    public void transmitLoopback(TransmitLoopbackInput inputVar,
+            NetconfSession session) throws NetconfException {
+
+        ModelObjectData transLoopbackMo = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) inputVar).build();
+
+        customRpcNetconf(transLoopbackMo,
+                TRANSMIT_LOOPBACK, session);
+    }
+
+    @Override
+    public void abortLoopback(AbortLoopbackInput inputVar,
+            NetconfSession session) throws NetconfException {
+        ModelObjectData abortLoopbackMo = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) inputVar).build();
+
+        customRpcNetconf(abortLoopbackMo, ABORT_LOOPBACK, session);
+    }
+
+    @Override
+    public TransmitLinktraceOutput transmitLinktrace(
+            TransmitLinktraceInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    //FIXME Remove when the fix for null bits with onos-yang-tools
+    // https://gerrit.onosproject.org/#/c/15777/ is available
+    @Deprecated
+    private static String removeEmptyActiveDefects(String rpcReplyXml) throws NetconfException {
+        rpcReplyXml = REGEX_EMPTY_ACTIVE_DEFECTS.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_EMPTY_LAST_DEFECT_SENT.matcher(rpcReplyXml).replaceFirst("");
+
+        return rpcReplyXml;
+    }
+
+    @Deprecated //Replace this with a ModelObject defintion
+    private String buildMepEssentialsQueryString(MdId mdId, MaIdShort maId,
+            MepId mepId) {
+        StringBuilder rpc = new StringBuilder();
+
+        rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
+        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>");
+        rpc.append(mdId.mdName());
+        rpc.append("</name>\n");
+        rpc.append("<maintenance-association>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>");
+        rpc.append(maId.maName());
+        rpc.append("</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>");
+        rpc.append(mepId.id());
+        rpc.append("</mep-identifier>\n");
+        rpc.append("<mac-address/>\n");
+        rpc.append("<remote-mep-database>\n");
+        rpc.append("<remote-mep>\n");
+        rpc.append("<remote-mep-id/>\n");
+        rpc.append("</remote-mep>\n");
+        rpc.append("</remote-mep-database>\n");
+        rpc.append("<msea-soam-pm:delay-measurements>\n");
+        rpc.append("<msea-soam-pm:delay-measurement>\n");
+        rpc.append("<msea-soam-pm:dm-id/>\n");
+        rpc.append("</msea-soam-pm:delay-measurement>\n");
+        rpc.append("</msea-soam-pm:delay-measurements>\n");
+        rpc.append("<msea-soam-pm:loss-measurements>\n");
+        rpc.append("<msea-soam-pm:loss-measurement>\n");
+        rpc.append("<msea-soam-pm:lm-id/>\n");
+        rpc.append("</msea-soam-pm:loss-measurement>\n");
+        rpc.append("</msea-soam-pm:loss-measurements>\n");
+        rpc.append("</maintenance-association-end-point>\n");
+        rpc.append("</maintenance-association>\n");
+        rpc.append("</maintenance-domain>\n");
+        rpc.append("</mef-cfm>");
+
+        return rpc.toString();
+    }
+
+    @Deprecated //Replace this with a ModelObject defintion
+    private String buildMepFullQueryString(MdId mdId, MaIdShort maId, MepId mepId) {
+        StringBuilder rpc = new StringBuilder();
+
+        rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
+        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>");
+        rpc.append(mdId.mdName());
+        rpc.append("</name>\n");
+        rpc.append("<maintenance-association>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>");
+        rpc.append(maId.maName());
+        rpc.append("</name>\n");
+        rpc.append("<maintenance-association-end-point>\n");
+        rpc.append("<mep-identifier>");
+        rpc.append(mepId.id());
+        rpc.append("</mep-identifier>\n");
+        rpc.append("<interface/>\n");
+        //Direction will always be DOWN for EA1000
+        rpc.append("<primary-vid/>\n");
+        rpc.append("<administrative-state/>\n");
+        rpc.append("<mac-address/>\n");
+        rpc.append("<ccm-ltm-priority/>\n");
+        rpc.append("<continuity-check/>\n"); //Container
+        rpc.append("<loopback/>\n"); //Container
+        rpc.append("<linktrace/>\n"); //Container
+        rpc.append("<remote-mep-database/>\n"); //Container
+        rpc.append("<msea-soam-fm:operational-state/>\n");
+        rpc.append("<msea-soam-fm:connectivity-status/>\n");
+        rpc.append("<msea-soam-fm:port-status/>\n");
+        rpc.append("<msea-soam-fm:interface-status/>\n");
+        rpc.append("<msea-soam-fm:last-defect-sent/>\n");
+        rpc.append("<msea-soam-fm:rdi-transmit-status/>\n");
+        rpc.append("</maintenance-association-end-point>\n");
+        rpc.append("</maintenance-association>\n");
+        rpc.append("</maintenance-domain>\n");
+        rpc.append("</mef-cfm>");
+
+        return rpc.toString();
+    }
+
+    @Deprecated //Replace this with a ModelObject defintion
+    private String buildDmQueryString(MdId mdId, MaIdShort maId, MepId mepId,
+            SoamId dmId, DmEntryParts parts) {
+        StringBuilder rpc = new StringBuilder();
+
+        rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
+        rpc.append(" xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" ");
+        rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
+        rpc.append("<maintenance-domain>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>");
+        rpc.append(mdId.mdName());
+        rpc.append("</name>\n");
+        rpc.append("<maintenance-association>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>");
+        rpc.append(maId.maName());
+        rpc.append("</name>\n");
+        rpc.append("<maintenance-association-end-point>\n");
+        rpc.append("<mep-identifier>");
+        rpc.append(mepId.id());
+        rpc.append("</mep-identifier>\n");
+        if (dmId != null) {
+            rpc.append("<msea-soam-pm:delay-measurements>");
+            rpc.append("<msea-soam-pm:delay-measurement>\n");
+            rpc.append("<msea-soam-pm:dm-id>");
+            rpc.append(dmId.id());
+            rpc.append("</msea-soam-pm:dm-id>\n");
+            rpc.append("<msea-soam-pm:mep-id/>");
+            rpc.append("<msea-soam-pm:mac-address/>");
+            rpc.append("<msea-soam-pm:administrative-state/>\n");
+            rpc.append("<msea-soam-pm:measurement-enable/>\n");
+            rpc.append("<msea-soam-pm:message-period/>\n");
+            rpc.append("<msea-soam-pm:priority/>\n");
+            rpc.append("<msea-soam-pm:frame-size/>\n");
+            rpc.append("<msea-soam-pm:measurement-interval/>\n");
+            rpc.append("<msea-soam-pm:number-intervals-stored/>\n");
+            rpc.append("<msea-soam-pm:session-status/>\n");
+            rpc.append("<msea-soam-pm:frame-delay-two-way/>\n");
+            rpc.append("<msea-soam-pm:inter-frame-delay-variation-two-way/>\n");
+            if (parts != null && (parts.equals(DmEntryParts.CURRENT_ONLY) ||
+                    parts.equals(DmEntryParts.ALL_PARTS))) {
+                rpc.append("<msea-soam-pm:current-stats/>\n");
+            }
+            if (parts != null && (parts.equals(DmEntryParts.HISTORY_ONLY) ||
+                    parts.equals(DmEntryParts.ALL_PARTS))) {
+                rpc.append("<msea-soam-pm:history-stats/>\n");
+            }
+            rpc.append("</msea-soam-pm:delay-measurement>\n");
+            rpc.append("</msea-soam-pm:delay-measurements>");
+        } else {
+            rpc.append("<msea-soam-pm:delay-measurements/>");
+        }
+        rpc.append("</maintenance-association-end-point>\n");
+        rpc.append("</maintenance-association>\n");
+        rpc.append("</maintenance-domain>\n");
+        rpc.append("</mef-cfm>");
+
+        return rpc.toString();
+    }
+
+    @Deprecated //Replace this with a ModelObject defintion
+    private String buildAbortLoopbackQueryString(Short mdId, Short maId,
+            Short mepId) {
+        StringBuilder rpc = new StringBuilder();
+
+        rpc.append("<abort-loopback xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">");
+        rpc.append("<maintenance-domain>");
+        rpc.append(mdId);
+        rpc.append("</maintenance-domain>");
+        rpc.append("<maintenance-association>");
+        rpc.append(maId);
+        rpc.append("</maintenance-association>");
+        rpc.append("<maintenance-association-end-point>");
+        rpc.append(mepId);
+        rpc.append("</maintenance-association-end-point>");
+        rpc.append("</abort-loopback>");
+
+        return rpc.toString();
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
new file mode 100644
index 0000000..78c6315
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.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.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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
new file mode 100644
index 0000000..c0cba14
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.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()) {
+
+            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, bwpGrp.groupIndex());
+
+            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();
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java
new file mode 100644
index 0000000..c9bc2a3
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package 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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java
new file mode 100644
index 0000000..9922f39
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package 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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
new file mode 100644
index 0000000..76534d0
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import 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 ("0".equals(existingMap)) {
+            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/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java
new file mode 100644
index 0000000..7c67992
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import java.time.Instant;
+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());
+    }
+
+    /**
+     * Convert a from Date and Time in a ietf-yang-types format to the Java Time API as an Instant.
+     * @param dateAndTime A date and time from a YANG object
+     * @return The date and time as an Instant
+     */
+    public static Instant fromYangDateTimeToInstant(DateAndTime dateAndTime) {
+        return Instant.from(OffsetDateTime.parse(dateAndTime.toString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME));
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java
new file mode 100644
index 0000000..e18abe6
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import org.onlab.util.HexString;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.YangIdentifier;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNamePrimaryVid;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameRfc2685VpnId;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameUint16;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameY1731Icc;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.NameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.nameprimaryvid.NamePrimaryVidUnion;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+
+/**
+ * Utility for translating between Maintenance Association names in the CFM API model and the device YANG.
+ *
+ * This has to be in a separate file as a workaround for Checkstyle issue.
+ * https://github.com/checkstyle/checkstyle/issues/3850
+ * There are two types of DefaultNameCharacterString - one for MA and another for MD
+ * Putting both together in a file means that the full path has to be given which
+ * will then fail checkstyle
+ */
+public final class MaNameUtil {
+
+    private MaNameUtil() {
+        //Hidden
+    }
+
+    /**
+     * Convert CFM API MA identifier to the YANG model MA identifier.
+     * @param maId Maintenance Association ID in CFM API
+     * @return Maintenance Association ID in YANG API
+     * @throws CfmConfigException If there's a problem with the name
+     */
+    public static MaNameAndTypeCombo getYangMaNameFromApiMaId(MaIdShort maId)
+            throws CfmConfigException {
+        MaNameAndTypeCombo maName;
+        if (maId instanceof MaIdPrimaryVid) {
+            maName = new DefaultNamePrimaryVid();
+            ((DefaultNamePrimaryVid) maName).namePrimaryVid(NamePrimaryVidUnion.fromString(maId.maName()));
+        } else if (maId instanceof MaId2Octet) {
+            maName = new DefaultNameUint16();
+            ((DefaultNameUint16) maName).nameUint16(Integer.valueOf(maId.maName()));
+        } else if (maId instanceof MaIdRfc2685VpnId) {
+            maName = new DefaultNameRfc2685VpnId();
+            ((DefaultNameRfc2685VpnId) maName).nameRfc2685VpnId(HexString.fromHexString(maId.maName()));
+        } else if (maId instanceof MaIdIccY1731) {
+            maName = new DefaultNameY1731Icc();
+            ((DefaultNameY1731Icc) maName).nameY1731Icc(YangIdentifier.of(maId.maName()));
+        } else if (maId instanceof MaIdCharStr) {
+            maName = new DefaultNameCharacterString();
+            ((DefaultNameCharacterString) maName).name(Identifier45.fromString(maId.maName()));
+        } else {
+            throw new CfmConfigException("Unexpected error creating MD " +
+                    maId.getClass().getSimpleName());
+        }
+        return maName;
+    }
+
+    /**
+     * Convert YANG API MA identifier to the CFM API MA identifier.
+     * @param nameAndTypeCombo Maintenance Association ID in YANG API
+     * @return Maintenance Association ID in CFM API
+     */
+    public static MaIdShort getApiMaIdFromYangMaName(MaNameAndTypeCombo nameAndTypeCombo) {
+        MaIdShort maId;
+        if (nameAndTypeCombo instanceof DefaultNameCharacterString) {
+            maId = MaIdCharStr.asMaId(
+                    ((DefaultNameCharacterString) nameAndTypeCombo).name().string());
+        } else if (nameAndTypeCombo instanceof DefaultNamePrimaryVid) {
+            if (((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().enumeration() != null) {
+                maId = MaIdPrimaryVid.asMaId(
+                        ((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().enumeration().name());
+            } else if (((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().vlanIdType() != null) {
+                maId = MaIdPrimaryVid.asMaId(
+                        ((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().vlanIdType().uint16());
+            } else {
+                throw new IllegalArgumentException("Unexpected primaryVid for " +
+                        "MaNameAndTypeCombo: " + nameAndTypeCombo.toString());
+            }
+        } else if (nameAndTypeCombo instanceof DefaultNameUint16) {
+            maId = MaId2Octet.asMaId(((DefaultNameUint16) nameAndTypeCombo).nameUint16());
+
+        } else if (nameAndTypeCombo instanceof DefaultNameRfc2685VpnId) {
+            maId = MaIdRfc2685VpnId.asMaIdHex(
+                    HexString.toHexString(
+                            ((DefaultNameRfc2685VpnId) nameAndTypeCombo).nameRfc2685VpnId()));
+        } else if (nameAndTypeCombo instanceof DefaultNameY1731Icc) {
+            maId = MaIdIccY1731.asMaId(((DefaultNameY1731Icc) nameAndTypeCombo).nameY1731Icc().string());
+
+        } else {
+            throw new IllegalArgumentException("Unexpected type for " +
+                    "MaNameAndTypeCombo: " + nameAndTypeCombo.toString());
+        }
+
+        return maId;
+    }
+
+    /**
+     * Cast the YANG generic type of MaNameAndTypeCombo specifically to char string.
+     * @param maName a YANG generic MaNameAndTypeCombo
+     * @return a YANG specific MaNameAndTypeCombo for Char string
+     */
+    public static NameCharacterString cast(MaNameAndTypeCombo maName) {
+        return (NameCharacterString) maName;
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MdNameUtil.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MdNameUtil.java
new file mode 100644
index 0000000..ba0cc96
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MdNameUtil.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.DomainName;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultMacAddressAndUint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameDomainName;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameNone;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.MacAddressAndUint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MacAddressAndUintStr;
+
+/**
+ * Utility for translating between Maintenance Domain names in the CFM API model and the device YANG.
+ *
+ * This has to be in a separate file as a workaround for Checkstyle issue.
+ * https://github.com/checkstyle/checkstyle/issues/3850
+ * There are two types of DefaultNameCharacterString - one for MA and another for MD
+ * Putting both together in a file means that the full path has to be given which
+ * will then fail checkstyle
+ */
+public final class MdNameUtil {
+
+    private MdNameUtil() {
+        //Hidden
+    }
+
+    /**
+     * Convert CFM API MD identifier to the YANG model MD identifier.
+     * @param mdId Maintenance Domain ID in CFM API
+     * @return Maintenance Domain ID in YANG API
+     * @throws CfmConfigException If there's a problem with the name
+     */
+    public static MdNameAndTypeCombo getYangMdNameFromApiMdId(MdId mdId)
+            throws CfmConfigException {
+        MdNameAndTypeCombo mdName;
+        if (mdId instanceof MdIdDomainName) {
+            boolean isIpAddr = false;
+            try {
+                if (IpAddress.valueOf(mdId.mdName()) != null) {
+                    isIpAddr = true;
+                }
+            } catch (IllegalArgumentException e) {
+                //continue
+            }
+            if (isIpAddr) {
+                mdName = new DefaultNameDomainName();
+                ((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion.of(
+                        org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.
+                                IpAddress.fromString(mdId.mdName())));
+            } else {
+                mdName = new DefaultNameDomainName();
+                ((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion
+                        .of(DomainName.fromString(mdId.mdName())));
+            }
+        } else if (mdId instanceof MdIdMacUint) {
+            mdName = new DefaultMacAddressAndUint();
+            ((DefaultMacAddressAndUint) mdName).nameMacAddressAndUint(MacAddressAndUintStr.fromString(mdId.mdName()));
+        } else if (mdId instanceof MdIdNone) {
+            mdName = new DefaultNameNone();
+        } else if (mdId instanceof MdIdCharStr) {
+            mdName = new DefaultNameCharacterString();
+            ((DefaultNameCharacterString) mdName).name(Identifier45.fromString(mdId.mdName()));
+        } else {
+            throw new CfmConfigException("Unexpected error creating MD " +
+                    mdId.getClass().getSimpleName());
+        }
+        return mdName;
+    }
+
+    /**
+     * Convert YANG API MD identifier to the CFM API MD identifier.
+     * @param nameAndTypeCombo Maintenance Domain ID in YANG API
+     * @return Maintenance Domain ID in CFM API
+     */
+    public static MdId getApiMdIdFromYangMdName(MdNameAndTypeCombo nameAndTypeCombo) {
+        MdId mdId;
+        if (nameAndTypeCombo instanceof DefaultNameDomainName) {
+            NameDomainNameUnion domainName =
+                    ((DefaultNameDomainName) nameAndTypeCombo).nameDomainName();
+            if (domainName.ipAddress() != null) {
+                mdId = MdIdDomainName.asMdId(domainName.ipAddress().toString());
+            } else if (domainName.domainName() != null) {
+                mdId = MdIdDomainName.asMdId(domainName.domainName().string());
+            } else {
+                throw new IllegalArgumentException("Unexpected domainName for " +
+                        "MdNameAndTypeCombo: " + nameAndTypeCombo.toString());
+            }
+        } else if (nameAndTypeCombo instanceof DefaultNameCharacterString) {
+            mdId = MdIdCharStr.asMdId(
+                    ((NameCharacterString) nameAndTypeCombo).name().string());
+
+        } else if (nameAndTypeCombo instanceof DefaultMacAddressAndUint) {
+            mdId = MdIdMacUint.asMdId(
+                    ((MacAddressAndUint) nameAndTypeCombo).nameMacAddressAndUint().string());
+
+        } else if (nameAndTypeCombo instanceof DefaultNameNone) {
+            mdId = MdIdNone.asMdId();
+        } else {
+            throw new IllegalArgumentException("Unexpected type for " +
+                    "MdNameAndTypeCombo: " + nameAndTypeCombo.toString());
+        }
+
+        return mdId;
+    }
+
+    /**
+     * Cast the YANG generic type of MdNameAndTypeCombo specifically to char string.
+     * @param maName a YANG generic MdNameAndTypeCombo
+     * @return a YANG specific MdNameAndTypeCombo for Char string
+     */
+    public static NameCharacterString cast(MdNameAndTypeCombo maName) {
+        return (NameCharacterString) maName;
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil.java
new file mode 100644
index 0000000..cd1b9ef
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.RemoteMep;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep.MepId;
+
+/**
+ * This is a workaround for Checkstyle issue.
+ * https://github.com/checkstyle/checkstyle/issues/3850
+ *
+ */
+public final class MepIdUtil {
+    private MepIdUtil() {
+        //Hidden
+    }
+
+    public static MepId convertRemoteMepId(RemoteMep rmep) {
+        return (MepId) rmep;
+    }
+
+    public static AugmentedMseaCfmMaintenanceAssociationEndPoint
+        convertPmAugmentedMep(MaintenanceAssociationEndPoint mep) {
+        AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+            (AugmentedMseaCfmMaintenanceAssociationEndPoint) mep
+            .augmentation(
+                    DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+        return augmentedMep;
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil2.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil2.java
new file mode 100644
index 0000000..36f3a3a
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil2.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.TargetAddress;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.MepId;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.MacAddress;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
+
+/**
+ * This is a workaround for Checkstyle issue.
+ * https://github.com/checkstyle/checkstyle/issues/3850
+ *
+ */
+public final class MepIdUtil2 {
+    private MepIdUtil2() {
+        //Hidden
+    }
+
+    public static MepId convertTargetAddrToMepId(TargetAddress targetMep) {
+        return (MepId) targetMep.addressType();
+    }
+
+    public static MacAddress convertTargetAddrToMacAddress(TargetAddress targetMep) {
+        return (MacAddress) targetMep.addressType();
+    }
+
+    public static AugmentedMseaCfmMaintenanceAssociationEndPoint
+        convertFmAugmentedMep(MaintenanceAssociationEndPoint mep) {
+        return (AugmentedMseaCfmMaintenanceAssociationEndPoint) mep
+            .augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil3.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil3.java
new file mode 100644
index 0000000..37b6d7c
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MepIdUtil3.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.RemoteMep;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep.DefaultMepId;
+
+public final class MepIdUtil3 {
+    private MepIdUtil3() {
+        //Hidden
+    }
+
+    public static DefaultMepId convertPmRemoteMepToMepId(RemoteMep remoteMep) {
+        return (DefaultMepId) remoteMep;
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java
new file mode 100644
index 0000000..4920672
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for general utilities and helpers.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
\ No newline at end of file
diff --git a/drivers/microsemi/ea1000/src/main/resources/microsemi-drivers.xml b/drivers/microsemi/ea1000/src/main/resources/microsemi-drivers.xml
new file mode 100644
index 0000000..f1321d3
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/main/resources/microsemi-drivers.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2017-present Open Networking Foundation
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<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.service.CfmMepProgrammable"
+            impl="org.onosproject.drivers.microsemi.EA1000CfmMepProgrammable" />
+        <behaviour
+            api="org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable"
+            impl="org.onosproject.drivers.microsemi.EA1000SoamDmProgrammable" />
+    </driver>
+</drivers>
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java
new file mode 100644
index 0000000..1f87634
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static junit.framework.TestCase.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getYangMdNameFromApiMdId;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.onosproject.drivers.microsemi.yang.utils.MaNameUtil;
+import org.onosproject.drivers.microsemi.yang.utils.MdNameUtil;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.InterfaceStatusTlvType;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.PortStatusTlvType;
+import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo;
+
+import java.util.BitSet;
+import java.util.Optional;
+
+/**
+ * Test of the CFM implementation on EA1000 through the incubator/net/l2monitoring interface.
+ */
+public class EA1000CfmMepProgrammableTest {
+    public static final MdId MD_ID_1 = MdIdCharStr.asMdId("md-1");
+    public static final MaIdShort MA_ID_11 = MaIdCharStr.asMaId("ma-1-1");
+    public static final MepId MEP_111 = MepId.valueOf((short) 1);
+    public static final MepId MEP_112 = MepId.valueOf((short) 2);
+
+    private CfmMepProgrammable cfmProgrammable;
+
+    @Before
+    public void setUp() throws Exception {
+        cfmProgrammable = new EA1000CfmMepProgrammable();
+        cfmProgrammable.setHandler(new MockEa1000DriverHandler());
+        assertNotNull(cfmProgrammable.handler().data().deviceId());
+    }
+
+
+    @Ignore
+    @Test
+    public void testCreateMep() {
+        fail("Not yet implemented");
+    }
+
+    @Test
+    public void testGetMep() throws CfmConfigException {
+        MepEntry mepEntry = cfmProgrammable.getMep(MD_ID_1, MA_ID_11, MEP_111);
+
+        //Result will come from MockNetconfSessionEa1000.SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY
+        assertNotNull(mepEntry);
+        assertTrue(mepEntry.administrativeState());
+        assertTrue(mepEntry.cciEnabled());
+        assertEquals(Priority.PRIO5.name(), mepEntry.ccmLtmPriority().name());
+
+        assertTrue("Expecting remote-mac-error", mepEntry.activeMacStatusDefect()); //remote-mac-error
+        assertTrue("Expecting remote-rdi", mepEntry.activeRdiCcmDefect()); //remote-rdi
+
+        assertNotNull(mepEntry.activeRemoteMepList());
+
+//FIXME Waiting on patch https://gerrit.onosproject.org/#/c/15778/
+//        assertEquals("Expecting 2 Remote Meps", 2, mepEntry.activeRemoteMepList().size());
+        mepEntry.activeRemoteMepList().forEach(rmep -> {
+            if (rmep.remoteMepId().value() == 1) {
+                assertEquals(RemoteMepState.RMEP_FAILED.name(),
+                        rmep.state().toString());
+                assertEquals(54654654L, rmep.failedOrOkTime().toMillis());
+                assertEquals("aa:bb:cc:dd:ee:ff".toUpperCase(), rmep.macAddress().toString());
+                assertFalse(rmep.rdi());
+                assertEquals(PortStatusTlvType.PS_NO_STATUS_TLV.name(),
+                        rmep.portStatusTlvType().toString());
+                assertEquals(InterfaceStatusTlvType.IS_DORMANT.name(),
+                        rmep.interfaceStatusTlvType().toString());
+            }
+        });
+
+    }
+
+    @Test
+    public void testGetMep2() throws CfmConfigException {
+        MepEntry mepEntry = cfmProgrammable.getMep(MD_ID_1, MA_ID_11, MEP_112);
+
+        //Result will come from MockNetconfSessionEa1000.SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY
+        assertNotNull(mepEntry);
+        assertTrue(mepEntry.administrativeState());
+        assertTrue(mepEntry.cciEnabled());
+        assertEquals(Priority.PRIO4.name(), mepEntry.ccmLtmPriority().name());
+
+        assertNotNull(mepEntry.activeRemoteMepList());
+        BitSet bs1 = new BitSet();
+        bs1.clear();
+//FIXME Waiting on patch https://gerrit.onosproject.org/#/c/15778/
+//        assertEquals("Expecting 2 Remote Meps", 2, mepEntry.activeRemoteMepList().size());
+        mepEntry.activeRemoteMepList().forEach(rmep -> {
+            if (rmep.remoteMepId().value() == 1) {
+                assertEquals(RemoteMepState.RMEP_FAILED.name(),
+                        rmep.state().toString());
+                assertEquals(54654654L, rmep.failedOrOkTime().toMillis());
+                assertEquals("aa:bb:cc:dd:ee:ff".toUpperCase(), rmep.macAddress().toString());
+                assertFalse(rmep.rdi());
+                assertEquals(PortStatusTlvType.PS_NO_STATUS_TLV.name(),
+                        rmep.portStatusTlvType().toString());
+                assertEquals(InterfaceStatusTlvType.IS_DORMANT.name(),
+                        rmep.interfaceStatusTlvType().toString());
+            }
+        });
+
+    }
+
+    /**
+     * For sampleXmlRegexDeleteMseaCfmMep.
+     * @throws CfmConfigException If an error occurs
+     */
+    @Test
+    public void testDeleteMep() throws CfmConfigException {
+        assertTrue(cfmProgrammable.deleteMep(MD_ID_1, MA_ID_11, MEP_111, Optional.empty()));
+    }
+
+    /**
+     * Create the MD md-1 on the device.
+     * This will retrieve the MD from the MockCfmMdService and will create it
+     * and its MA on the device
+     * Depends on sampleXmlRegexCreateMseaCfmMa
+     */
+    @Test
+    public void testCreateMaintenanceDomainOnDevice() throws CfmConfigException {
+        boolean success =
+                cfmProgrammable.createMdOnDevice(MdIdCharStr.asMdId("md-1"));
+        assertTrue(success);
+    }
+
+    /**
+     * Create the MD md-2 on the device.
+     * This will retrieve the MD from the MockCfmMdService and will create it on
+     * the device. This MD has no MA
+     * Depends on sampleXmlRegexCreateMseaCfmMa
+     */
+    @Test
+    public void testCreateMaintenanceDomainOnDevice2() throws CfmConfigException {
+        boolean success =
+                cfmProgrammable.createMdOnDevice(MdIdCharStr.asMdId("md-2"));
+        assertTrue(success);
+    }
+
+    /**
+     * Delete the MD md-1 on the device.
+     * This will retrieve the MD from the MockCfmMdService and will delete it on
+     * the device.
+     * Depends on sampleXmlRegexCreateMseaCfmMa
+     */
+    @Test
+    public void testDeleteMaintenanceDomainOnDevice() throws CfmConfigException {
+        boolean success =
+                cfmProgrammable.deleteMdOnDevice(MdIdCharStr.asMdId("md-1"), Optional.empty());
+        assertTrue(success);
+    }
+
+
+    /**
+     * Create the MA ma-1-1 on the device.
+     * This will retrieve the MA from the MockCfmMdService and will create it
+     * on the device under md-1
+     * Depends on sampleXmlRegexCreateMseaCfmMa
+     */
+    @Test
+    public void testCreateMaintenanceAssociationOnDevice() throws CfmConfigException {
+        boolean success =
+                cfmProgrammable.createMaOnDevice(
+                        MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"));
+        assertTrue(success);
+    }
+
+    /**
+     * Delete the MD md-1 on the device.
+     * This will retrieve the MD from the MockCfmMdService and will delete it on
+     * the device.
+     * Depends on sampleXmlRegexCreateMseaCfmMa
+     */
+    @Test
+    public void testDeleteMaintenanceAssociationOnDevice() throws CfmConfigException {
+        boolean success =
+                cfmProgrammable.deleteMaOnDevice(
+                        MdIdCharStr.asMdId("md-1"),
+                        MaIdCharStr.asMaId("ma-1-1"),
+                        Optional.empty());
+        assertTrue(success);
+    }
+
+    /**
+     * Create the Remote Mep 10001 in ma-1-1 on the device.
+     * This will retrieve the MA from the MockCfmMdService and will create the
+     * new remote mep under it on the device
+     * Depends on sampleXmlRegexCreateMseaCfmMa
+     */
+    @Test
+    public void testCreateRemoteMepOnDevice() throws CfmConfigException {
+        boolean success =
+                cfmProgrammable.createMaRemoteMepOnDevice(
+                        MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"),
+                        MepId.valueOf((short) 1001));
+        assertTrue(success);
+    }
+
+    /**
+     * Delete the Remote Mep 1002 in ma-1-1 on the device.
+     * This will retrieve the MA from the MockCfmMdService and will delete the
+     * existing remote mep under it on the device
+     * Depends on sampleXmlRegexCreateMseaCfmMa
+     */
+    @Test
+    public void testDeleteRemoteMepOnDevice() throws CfmConfigException {
+        boolean success =
+                cfmProgrammable.deleteMaRemoteMepOnDevice(
+                        MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"),
+                        MepId.valueOf((short) 1001));
+        assertTrue(success);
+    }
+
+    /**
+     * For sampleXmlRegexTransmitLoopback.
+     * @throws CfmConfigException If an error occurs
+     */
+    @Test
+    public void testTransmitLoopback() throws CfmConfigException {
+        MepLbCreate.MepLbCreateBuilder lbCreate =
+                    DefaultMepLbCreate.builder(MepId.valueOf((short) 12));
+        lbCreate.numberMessages(5);
+//        lbCreate.dataTlvHex("AA:BB:CC:DD:EE");
+        lbCreate.vlanPriority(Priority.PRIO3);
+        lbCreate.vlanDropEligible(true);
+
+        cfmProgrammable.transmitLoopback(MD_ID_1, MA_ID_11, MEP_111, lbCreate.build());
+    }
+
+    @Test
+    public void testAbortLoopback() throws CfmConfigException {
+        cfmProgrammable.abortLoopback(MD_ID_1, MA_ID_11, MEP_111);
+    }
+
+    @Ignore
+    @Test
+    public void testTransmitLinktrace() {
+        fail("Not yet implemented");
+    }
+
+    @Test
+    public void testGetYangMdNameFromApiMdId() throws CfmConfigException {
+        MdNameAndTypeCombo name = getYangMdNameFromApiMdId(MdIdCharStr.asMdId("md-1"));
+
+        assertEquals(org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                .maintenancedomain.mdnameandtypecombo
+                .DefaultNameCharacterString.class, name.getClass());
+
+        assertEquals("md-1", MdNameUtil.cast(name).name().string());
+    }
+
+    @Test
+    public void testGetYangMaNameFromApiMaId() throws CfmConfigException {
+        MaNameAndTypeCombo name = MaNameUtil
+                .getYangMaNameFromApiMaId(MaIdCharStr.asMaId("ma-1-1"));
+        assertEquals(org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+                .maintenancedomain.maintenanceassociation.manameandtypecombo
+                .DefaultNameCharacterString.class, name.getClass());
+
+        assertEquals("ma-1-1", MaNameUtil.cast(name).name().string());
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java
new file mode 100644
index 0000000..aa04dab
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.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/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java
new file mode 100644
index 0000000..1e70a9e
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import 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/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java
new file mode 100644
index 0000000..59c674e
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmCreateBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus;
+
+public class EA1000SoamDmProgrammableTest {
+
+    EA1000SoamDmProgrammable dmProgrammable;
+    MdId mdId1 = MdIdCharStr.asMdId("md-1");
+    MaIdShort maId11 = MaIdCharStr.asMaId("ma-1-1");
+    MepId mep111 = MepId.valueOf((short) 1);
+
+    @Before
+    public void setUp() throws Exception {
+        dmProgrammable = new EA1000SoamDmProgrammable();
+        dmProgrammable.setHandler(new MockEa1000DriverHandler());
+        assertNotNull(dmProgrammable.handler().data().deviceId());
+    }
+
+    //TODO Implement all these tests
+//    @Test
+//    public void testEA1000SoamDmProgrammable() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetAllDms() {
+//        fail("Not yet implemented");
+//    }
+
+    /**
+     * From SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY.
+     * @throws CfmConfigException
+     * @throws SoamConfigException
+     */
+    @Test
+    public void testGetDm() throws CfmConfigException, SoamConfigException {
+        DelayMeasurementEntry dmEntry =
+                dmProgrammable.getDm(mdId1, maId11, mep111, SoamId.valueOf(1));
+        assertEquals(1, dmEntry.dmId().id().intValue());
+        assertEquals(2, dmEntry.measurementsEnabled().size());
+        assertEquals(SessionStatus.ACTIVE.name(), dmEntry.sessionStatus().name());
+        assertEquals(100, dmEntry.frameDelayTwoWay().toNanos() / 1000);
+        assertEquals(101, dmEntry.interFrameDelayVariationTwoWay().toNanos() / 1000);
+    }
+
+    @Test
+    public void testCreateDm() throws CfmConfigException, SoamConfigException {
+        DmCreateBuilder dmBuilder = (DmCreateBuilder) DefaultDelayMeasurementCreate
+            .builder(DmType.DMDMM, Version.Y17312011,
+                MepId.valueOf((short) 10), Priority.PRIO3)
+            .frameSize((short) 1200);
+
+        dmProgrammable.createDm(mdId1, maId11, mep111, dmBuilder.build());
+    }
+
+    @Test
+    public void testCreateDmWrongMsgPeriod()
+            throws CfmConfigException, SoamConfigException {
+        DmCreateBuilder dmBuilder = (DmCreateBuilder) DefaultDelayMeasurementCreate
+                .builder(DmType.DMDMM, Version.Y17312011,
+                        MepId.valueOf((short) 10), Priority.PRIO3)
+                .messagePeriod(Duration.ofMillis(1234));
+
+        try {
+            dmProgrammable.createDm(mdId1, maId11, mep111, dmBuilder.build());
+            fail("Expecting to get an exception");
+        } catch (SoamConfigException e) {
+            assertTrue(e.getMessage()
+                    .contains("EA1000 supports only Message Periods"));
+        }
+
+    }
+
+//    @Test
+//    public void testGetDmCurrentStat() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetDmHistoricalStats() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testAbortDmMdIdMaIdShortMepIdSoamId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testBuildApiDmFromYangDm() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testAbortDmMdIdMaIdShortMepId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testClearDelayHistoryStatsMdIdMaIdShortMepId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testClearDelayHistoryStatsMdIdMaIdShortMepIdSoamId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetAllLms() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetLm() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetLmCurrentStat() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testGetLmHistoricalStats() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testCreateLm() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testAbortLmMdIdMaIdShortMepId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testAbortLmMdIdMaIdShortMepIdSoamId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testClearLossHistoryStatsMdIdMaIdShortMepId() {
+//        fail("Not yet implemented");
+//    }
+//
+//    @Test
+//    public void testClearLossHistoryStatsMdIdMaIdShortMepIdSoamId() {
+//        fail("Not yet implemented");
+//    }
+
+    @Test
+    public void testCreateTestSignal() {
+        try {
+            dmProgrammable.createTestSignal(mdId1, maId11, mep111, null);
+            fail("Expected an exception");
+        } catch (UnsupportedOperationException e) {
+            assertEquals("Not supported by EA1000", e.getMessage());
+        } catch (CfmConfigException e) {
+            fail("CfmConfigException was not expected");
+        }
+    }
+
+    @Test
+    public void testAbortTestSignal() {
+        try {
+            dmProgrammable.abortTestSignal(mdId1, maId11, mep111);
+            fail("Expected an exception");
+        } catch (UnsupportedOperationException e) {
+            assertEquals("Not supported by EA1000", e.getMessage());
+        } catch (CfmConfigException e) {
+            fail("CfmConfigException was not expected");
+        }
+    }
+
+    @Test
+    public void testMeasurementEnableCollectionOfMeasurementOption() {
+        BitSet meBs = BitSet.valueOf(new byte[]{0x05});
+        Collection<MeasurementOption> moSet =
+                EA1000SoamDmProgrammable.getMeasurementOptions(meBs);
+        assertTrue(moSet.contains(MeasurementOption.SOAM_PDUS_RECEIVED));
+        assertTrue(moSet.contains(MeasurementOption.FRAME_DELAY_TWO_WAY_MIN));
+    }
+
+    @Test
+    public void testMeasurementEnableBitSetEmpty() {
+        Collection<MeasurementOption> moSet = new ArrayList<>();
+        try {
+            BitSet bitSet = EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet);
+            assertEquals("{}", bitSet.toString());
+        } catch (SoamConfigException e) {
+            fail("Was not expecting exception here");
+        }
+    }
+
+    @Test
+    public void testMeasurementEnableBitSetInvalid() {
+        Collection<MeasurementOption> moSet = new ArrayList<>();
+        moSet.add(MeasurementOption.FRAME_DELAY_BACKWARD_BINS);
+        moSet.add(MeasurementOption.FRAME_DELAY_RANGE_BACKWARD_AVERAGE);
+        try {
+            EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet);
+            fail("Was expecting an exception");
+        } catch (SoamConfigException e) {
+            assertTrue(e.getMessage()
+                    .contains("Measurement Option is not supported on EA1000"));
+        }
+    }
+
+    @Test
+    public void testMeasurementEnableBitSet2Good() {
+        Collection<MeasurementOption> moSet = new ArrayList<>();
+        moSet.add(MeasurementOption.FRAME_DELAY_TWO_WAY_BINS);
+        moSet.add(MeasurementOption.FRAME_DELAY_TWO_WAY_AVERAGE);
+        try {
+            BitSet bitSet = EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet);
+            assertEquals("{1, 4}", bitSet.toString());
+        } catch (SoamConfigException e) {
+            fail("Was not expecting exception here");
+        }
+    }
+
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java
new file mode 100644
index 0000000..6820721
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import 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/ea1000/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
new file mode 100644
index 0000000..742f8c9
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onosproject.core.CoreService;
+import org.onosproject.drivers.microsemi.yang.MockCfmMdService;
+import org.onosproject.drivers.microsemi.yang.MockCfmMepService;
+import org.onosproject.drivers.microsemi.yang.MockMseaCfmManager;
+import org.onosproject.drivers.microsemi.yang.MockMseaSaFilteringManager;
+import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager;
+import org.onosproject.drivers.microsemi.yang.MockNetconfSessionEa1000;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.drivers.netconf.MockCoreService;
+import org.onosproject.drivers.netconf.MockNetconfController;
+import org.onosproject.drivers.netconf.MockNetconfDevice;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
+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 MockMseaCfmManager mseaCfmService;
+    private MockCfmMdService mockMdService;
+    private MockCfmMepService mockMepService;
+    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();
+
+        mseaCfmService = new MockMseaCfmManager();
+        mseaCfmService.activate();
+
+        mockMdService = new MockCfmMdService();
+        mockMdService.activate();
+
+        mockMepService = new MockCfmMepService();
+        mockMepService.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(MseaCfmNetconfService.class)) {
+            return (T) mseaCfmService;
+
+        } else if (serviceClass.equals(CoreService.class)) {
+            return (T) coreService;
+
+        } else if (serviceClass.equals(CfmMdService.class)) {
+            return (T) mockMdService;
+
+        } else if (serviceClass.equals(CfmMepService.class)) {
+            return (T) mockMepService;
+
+        }
+
+        return null;
+    }
+
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java
new file mode 100644
index 0000000..235017f
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.junit.Assert.*;
+
+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/ea1000/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java
new file mode 100644
index 0000000..e303e9d
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import 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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java
new file mode 100644
index 0000000..e5c4f4a
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/CeVlanMapUtilsTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import 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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java
new file mode 100644
index 0000000..8a5e6f4
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/IetfSystemManagerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import 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("EA1000 unit test.", 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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java
new file mode 100644
index 0000000..3d0fb5f
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMdManager;
+import static org.easymock.EasyMock.*;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore;
+
+import java.util.Optional;
+
+/**
+ * Supports testing of services that reply on the CfmMdService.
+ */
+public class MockCfmMdService extends CfmMdManager {
+
+    @Override
+    public void activate() {
+        store = createMock(MdStore.class);
+
+        try {
+            MaintenanceAssociation ma = DefaultMaintenanceAssociation
+                    .builder(MaIdCharStr.asMaId("ma-1-1"), 6)
+                    .maNumericId((short) 1)
+                    .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_3MS)
+                    .addToRemoteMepIdList(MepId.valueOf((short) 10))
+                    .addToRemoteMepIdList(MepId.valueOf((short) 20))
+                    .addToComponentList(
+                            DefaultComponent.builder(1)
+                                    .addToVidList(VlanId.vlanId((short) 101)).build())
+                    .build();
+
+            MdId md1Name = MdIdCharStr.asMdId("md-1");
+            MaintenanceDomain md1 = DefaultMaintenanceDomain
+                    .builder(md1Name)
+                    .mdNumericId((short) 1)
+                    .mdLevel(MaintenanceDomain.MdLevel.LEVEL3)
+                    .addToMaList(ma)
+                    .build();
+
+            MdId md2Name = MdIdCharStr.asMdId("md-2");
+            MaintenanceDomain md2 = DefaultMaintenanceDomain
+                    .builder(md1Name)
+                    .mdNumericId((short) 2)
+                    .mdLevel(MaintenanceDomain.MdLevel.LEVEL2)
+                    .build();
+
+            expect(store.createUpdateMaintenanceDomain(md1))
+                    .andReturn(true);
+            expect(store.createUpdateMaintenanceDomain(md2))
+                    .andReturn(true);
+            expect(store.getMaintenanceDomain(md1Name))
+                    .andReturn(Optional.of(md1)).anyTimes();
+            expect(store.getMaintenanceDomain(md2Name))
+                    .andReturn(Optional.of(md2)).anyTimes();
+            replay(store);
+
+        } catch (CfmConfigException e) {
+            throw new IllegalArgumentException("Error creating MDs for test", e);
+        }
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMepService.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMepService.java
new file mode 100644
index 0000000..c00fc4e
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMepService.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onlab.junit.TestUtils;
+import org.onlab.packet.ChassisId;
+import org.onosproject.common.event.impl.TestEventDispatcher;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
+import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMdManager;
+import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMepManager;
+import org.onosproject.incubator.net.l2monitoring.cfm.impl.TestCfmMepProgrammable;
+import org.onosproject.incubator.net.l2monitoring.cfm.impl.TestDeviceDiscoveryBehavior;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStore;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable;
+import org.onosproject.incubator.net.l2monitoring.soam.impl.TestSoamDmProgrammable;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceDescriptionDiscovery;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.DefaultDriver;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.onosproject.net.NetTestTools.injectEventDispatcher;
+
+/**
+ * Supports testing of services that reply on the CfmMepService.
+ */
+public class MockCfmMepService extends CfmMepManager {
+    private static final String TEST_MFR = "testMfr";
+    private static final String TEST_HW_VERSION = "testHwVersion";
+    private static final String TEST_SW_VERSION = "testSwVersion";
+    private static final String TEST_SN = "testSn";
+    private static final String TEST_DRIVER = "testDriver";
+    protected static final DeviceId DEVICE_ID1 = DeviceId.deviceId("netconf:1.2.3.4:830");
+
+
+    private final DriverService driverService = createMock(DriverService.class);
+
+    private Device device1;
+    private Driver testDriver;
+
+
+    @Override
+    public void activate() {
+        mepStore = createMock(MepStore.class);
+        cfmMdService = new MockCfmMdService();
+        deviceService = createMock(DeviceService.class);
+        ((CfmMdManager) cfmMdService).activate();
+
+        device1 = new DefaultDevice(
+                ProviderId.NONE, DEVICE_ID1, Device.Type.SWITCH,
+                TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION, TEST_SN,
+                new ChassisId(1),
+                DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, TEST_DRIVER).build());
+
+        Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours = new HashMap<>();
+        behaviours.put(DeviceDescriptionDiscovery.class, TestDeviceDiscoveryBehavior.class);
+        behaviours.put(CfmMepProgrammable.class, TestCfmMepProgrammable.class);
+        behaviours.put(SoamDmProgrammable.class, TestSoamDmProgrammable.class);
+
+        TestUtils.setField(this, "coreService", new TestCoreService());
+        TestUtils.setField(this, "deviceService", deviceService);
+        injectEventDispatcher(this, new TestEventDispatcher());
+
+        testDriver = new DefaultDriver(
+                TEST_DRIVER, new ArrayList<Driver>(),
+                TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION,
+                behaviours, new HashMap<>());
+
+        try {
+            Mep mep1 = DefaultMep.builder(
+                        MepId.valueOf((short) 10),
+                        DEVICE_ID1,
+                        PortNumber.P0,
+                        Mep.MepDirection.UP_MEP,
+                        MdIdCharStr.asMdId("md-1"),
+                        MaIdCharStr.asMaId("ma-1-1"))
+                    .build();
+
+            expect(mepStore.getMep(new MepKeyId(mep1))).andReturn(Optional.of(mep1)).anyTimes();
+        } catch (CfmConfigException e) {
+            throw new IllegalArgumentException("Error creating MEPs for test", e);
+        }
+    }
+
+    private class TestCoreService extends CoreServiceAdapter {
+
+        @Override
+        public IdGenerator getIdGenerator(String topic) {
+            return new IdGenerator() {
+                private AtomicLong counter = new AtomicLong(0);
+
+                @Override
+                public long getNewId() {
+                    return counter.getAndIncrement();
+                }
+            };
+        }
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java
new file mode 100644
index 0000000..4cbb88a
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockIetfSystemManager.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+
+import org.onosproject.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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java
new file mode 100644
index 0000000..2576c78
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaCfmManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java
new file mode 100644
index 0000000..31fe61a
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaSaFilteringManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java
new file mode 100644
index 0000000..3cf3a42
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockMseaUniEvcServiceManager.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java
new file mode 100644
index 0000000..6bf67c0
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java
@@ -0,0 +1,1422 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
+
+import org.onosproject.drivers.microsemi.EA1000CfmMepProgrammableTest;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfDeviceInfo;
+import org.onosproject.netconf.NetconfDeviceOutputEventListener;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSessionAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MockNetconfSessionEa1000 extends NetconfSessionAdapter {
+    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>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<source-ipaddress-filtering).*(</source-ipaddress-filtering>)\\R?"
+                    + "(</filter>)\\R?(</get>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexSaFilteringErrorScenario =
+            Pattern.compile("(<\\?xml).*"
+                    + "(<rpc).*(<get>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<source-ipaddress-filtering).*"
+                    + "(<interface-eth0>)\\R?"
+                    + "(<source-address-range>)\\R?"
+                    + "(<range-id>)10(</range-id>)\\R?"
+                    + "(</source-address-range>)\\R?"
+                    + "(</interface-eth0>)\\R?"
+                    + "(</source-ipaddress-filtering>)\\R?"
+                    + "(</filter>)\\R?(</get>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexEditConfigSaFilt =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>).*"
+                    + "(<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?"
+                    + "(<mac-address/>)?\\R?"
+                    + "((<remote-mep-database>)\\R?"
+                    + "(<remote-mep>)\\R?"
+                    + "(<remote-mep-id/>)\\R?"
+                    + "(</remote-mep>)\\R?"
+                    + "(</remote-mep-database>))?\\R?"
+                    + "((<msea-soam-pm:delay-measurements>)\\R?"
+                    + "(<msea-soam-pm:delay-measurement>)\\R?"
+                    + "((<msea-soam-pm:dm-id/>)|(<msea-soam-pm:dm-id>[0-9]*</msea-soam-pm:dm-id>))\\R?"
+                    + "(</msea-soam-pm:delay-measurement>)\\R?"
+                    + "(</msea-soam-pm:delay-measurements>))?\\R?"
+                    + "((<msea-soam-pm:loss-measurements>)\\R?"
+                    + "(<msea-soam-pm:loss-measurement>)\\R?"
+                    + "((<msea-soam-pm:lm-id/>)|(<msea-soam-pm:lm-id>[0-9]*</msea-soam-pm:lm-id>))\\R?"
+                    + "(</msea-soam-pm:loss-measurement>)\\R?"
+                    + "(</msea-soam-pm:loss-measurements>))?\\R?"
+                    + "(</maintenance-association-end-point>)\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</filter>)\\R?"
+                    + "(</get>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    //For testGetMep
+    private String sampleXmlRegexGetMseaCfmFullStr =
+            "(<\\?xml).*(<rpc).*(<get>)\\R?"
+            + "(<filter type=\"subtree\">)\\R?"
+            + "(<mef-cfm).*"
+            + "(<maintenance-domain>)\\R?"
+            + "(<id/>)\\R?"
+            + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+            + "(<md-level/>)?\\R?"
+            + "(<maintenance-association>)\\R?"
+            + "(<id/>)\\R?"
+            + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+            + "(<maintenance-association-end-point>)\\R?"
+            + "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
+            + "(<interface/>)?\\R?"
+            + "(<primary-vid/>)?\\R?"
+            + "(<administrative-state/>)?\\R?"
+            + "(<mac-address/>)?\\R?"
+            + "(<ccm-ltm-priority/>)?\\R?"
+            + "(<continuity-check/>)?\\R?"
+            + "(<loopback/>)?\\R?"
+            + "(<linktrace/>)?\\R?"
+            + "(<remote-mep-database/>)\\R?"
+            + "(<msea-soam-fm:operational-state/>)\\R?"
+            + "(<msea-soam-fm:connectivity-status/>)\\R?"
+            + "(<msea-soam-fm:port-status/>)\\R?"
+            + "(<msea-soam-fm:interface-status/>)\\R?"
+            + "(<msea-soam-fm:last-defect-sent/>)\\R?"
+            + "(<msea-soam-fm:rdi-transmit-status/>)\\R?"
+            + "(</maintenance-association-end-point>)\\R?"
+            + "(</maintenance-association>)\\R?"
+            + "(</maintenance-domain>)\\R?"
+            + "(</mef-cfm>)\\R?"
+            + "(</filter>)\\R?"
+            + "(</get>)\\R?"
+            + "(</rpc>)\\R?"
+            + "(]]>){2}";
+
+    private Pattern sampleXmlRegexGetMseaCfmFull =
+            Pattern.compile(sampleXmlRegexGetMseaCfmFullStr
+                    .replace("(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)",
+                            "(<mep-identifier>)" +
+                                    EA1000CfmMepProgrammableTest.MEP_111 +
+                                    "(</mep-identifier>)"),
+                    Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexGetMseaCfmFull2 =
+            Pattern.compile(sampleXmlRegexGetMseaCfmFullStr
+                    .replace("(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)",
+                            "(<mep-identifier>)" +
+                                    EA1000CfmMepProgrammableTest.MEP_112 +
+                                    "(</mep-identifier>)"),
+                    Pattern.DOTALL);
+
+    //For testGetConfigMseaCfmEssentials
+    private Pattern sampleXmlRegexGetMseaDelay =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<get>)\\R?"
+                    + "(<filter type=\"subtree\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "(<id/>)\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<maintenance-association>)\\R?"
+                    + "(<id/>)\\R?"
+                    + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+                    + "(<maintenance-association-end-point>)\\R?"
+                    + "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
+                    + "((<msea-soam-pm:delay-measurements>)\\R?"
+                    + "(<msea-soam-pm:delay-measurement>)\\R?"
+                    + "((<msea-soam-pm:dm-id/>)|(<msea-soam-pm:dm-id>[0-9]*</msea-soam-pm:dm-id>))\\R?"
+                    + "(<msea-soam-pm:mep-id/>)\\R?"
+                    + "(<msea-soam-pm:mac-address/>)\\R?"
+                    + "(<msea-soam-pm:administrative-state/>)\\R?"
+                    + "(<msea-soam-pm:measurement-enable/>)\\R?"
+                    + "(<msea-soam-pm:message-period/>)\\R?"
+                    + "(<msea-soam-pm:priority/>)\\R?"
+                    + "(<msea-soam-pm:frame-size/>)\\R?"
+                    + "(<msea-soam-pm:measurement-interval/>)\\R?"
+                    + "(<msea-soam-pm:number-intervals-stored/>)\\R?"
+                    + "(<msea-soam-pm:session-status/>)\\R?"
+                    + "(<msea-soam-pm:frame-delay-two-way/>)\\R?"
+                    + "(<msea-soam-pm:inter-frame-delay-variation-two-way/>)\\R?"
+                    + "(<msea-soam-pm:current-stats/>)?\\R?"
+                    + "(<msea-soam-pm:history-stats/>)?\\R?"
+                    + "(</msea-soam-pm:delay-measurement>)\\R?"
+                    + "(</msea-soam-pm:delay-measurements>))?\\R?"
+                    + "(</maintenance-association-end-point>)\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</filter>)\\R?"
+                    + "(</get>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    //For testGetConfigMseaCfmEssentials
+    private Pattern sampleXmlRegexDeleteMseaCfmMep =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target>\\R?<running/>\\R?</target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "(<id>[0-9]{1,5}</id>)?\\R?"
+                    + "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
+                    + "(<maintenance-association>)\\R?"
+                    + "(<id>[0-9]{1,5}</id>)?\\R?"
+                    + "((<name>[a-zA-Z0-9\\-:\\.]{1,48}</name>)|"
+                    + "(<name-primary-vid>[0-9]{1,4}</name-primary-vid>))?\\R?"
+                    + "(<maintenance-association-end-point nc:operation=\"delete\">)\\R?"
+                    + "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
+                    + "(</maintenance-association-end-point>)\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</config>)\\R?"
+                    + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    //For testGetConfigMseaCfmEssentials
+    private Pattern sampleXmlRegexCreateMseaCfmMa =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target>\\R?<running/>\\R?</target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "(<id>)([0-9]){1,4}(</id>)\\R?"
+                    + "((<md-level>)([0-9]){1}(</md-level>))?\\R?"
+                    + "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
+                    + "((<maintenance-association>)\\R?"
+                    + "(<id>)([0-9]){1,4}(</id>)\\R?"
+                    + "((<ccm-interval>)(3.3ms)(</ccm-interval>))?\\R?"
+                    + "((<remote-meps>)([0-9]){1,4}(</remote-meps>))*\\R?"
+                    + "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
+                    + "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
+                    + "((<component-list>)\\R?"
+                    + "(<vid>)([0-9]){1,4}(</vid>)\\R?"
+                    + "(</component-list>))?\\R?"
+                    + "(</maintenance-association>))*\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</config>)\\R?"
+                    + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    //For testGetConfigMseaCfmEssentials
+    private Pattern sampleXmlRegexDeleteMseaCfmMa =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target>\\R?<running/>\\R?</target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "((<id/>)|((<id>)([0-9]){1,4}(</id>)))?\\R?"
+                    + "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
+                    + "(<maintenance-association nc:operation=\"delete\">)\\R?"
+                    + "((<id/>)|((<id>)([0-9]){1,4}(</id>)))?\\R?"
+                    + "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
+                    + "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</config>)\\R?"
+                    + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    //For testDeleteMseaMepRemoteMep
+    private Pattern sampleXmlRegexDeleteMseaCfmRmep =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target>\\R?<running/>\\R?</target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain>)\\R?"
+                    + "((<id>)[0-9]{1,4}(</id>))?\\R?"
+                    + "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
+                    + "(<maintenance-association>)\\R?"
+                    + "((<id>)[0-9]{1,4}(</id>))?\\R?"
+                    + "((<remote-meps nc:operation=\"delete\">)([0-9]){1,4}(</remote-meps>))*\\R?"
+                    + "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
+                    + "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
+                    + "(</maintenance-association>)\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</config>)\\R?"
+                    + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+    //For testDeleteMseaMd
+    private Pattern sampleXmlRegexDeleteMseaCfmMd =
+            Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+                    + "(<target>\\R?<running/>\\R?</target>)\\R?"
+                    + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                    + "(<mef-cfm).*"
+                    + "(<maintenance-domain nc:operation=\"delete\">)\\R?"
+                    + "((<id/>)|(<id>([0-9]){1,4}(</id>)))?\\R?"
+                    + "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|\\R?"
+                    + "((<name-domain-name>)([a-zA-Z0-9\\-\\.]){1,48}(</name-domain-name>)))?\\R?"
+                    + "(</maintenance-domain>)\\R?"
+                    + "(</mef-cfm>)\\R?"
+                    + "(</config>)\\R?"
+                    + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+
+    private Pattern sampleXmlRegexTransmitLoopback =
+            Pattern.compile("(<\\?xml).*(<rpc).*\\R?"
+                    + "(<transmit-loopback xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">)\\R?"
+                    + "((<number-of-messages>)[0-9]*(</number-of-messages>))?\\R?"
+                    + "((<data-tlv>)[a-zA-Z0-9+=/]*(</data-tlv>))?\\R?"
+                    + "((<vlan-priority>)[0-9]{1}(</vlan-priority>))?\\R?"
+                    + "((<vlan-drop-eligible>)((true)|(false))(</vlan-drop-eligible>))?\\R?"
+                    + "(<maintenance-association-end-point>)[0-9]{1,4}(</maintenance-association-end-point>)\\R?"
+                    + "(<maintenance-association>)[0-9]{1,5}(</maintenance-association>)\\R?"
+                    + "(<maintenance-domain>)[0-9]{1,5}(</maintenance-domain>)\\R?"
+                    + "(<target-address>)\\R?"
+                    + "((<mep-id>)[0-9]{1,4}(</mep-id>))?\\R?"
+                    + "((<mac-address>)[a-fA-F0-9:-]{17}(</mac-address>))?\\R?"
+                    + "(</target-address>)\\R?"
+                    + "(</transmit-loopback>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    private Pattern sampleXmlRegexAbortLoopback =
+            Pattern.compile("(<\\?xml).*(<rpc).*\\R?"
+                    + "(<abort-loopback xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">)\\R?"
+                    + "(<maintenance-association-end-point>)[0-9]{1,4}(</maintenance-association-end-point>)\\R?"
+                    + "(<maintenance-association>)[0-9]{1,5}(</maintenance-association>)\\R?"
+                    + "(<maintenance-domain>)[0-9]{1,5}(</maintenance-domain>)\\R?"
+                    + "(</abort-loopback>)\\R?"
+                    + "(</rpc>)\\R?"
+                    + "(]]>){2}", Pattern.DOTALL);
+
+    //For testCreateDm()
+    private Pattern sampleXmlRegexEditConfigDmCreate =
+        Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+            + "(<target>\\R?<running/>\\R?</target>)\\R?"
+            + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+            + "(<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">)\\R?"
+            + "(<maintenance-domain>)\\R?"
+            + "(<id>)[0-9]*(</id>)\\R?"
+            + "(<maintenance-association>)\\R?"
+            + "(<id>)[0-9]*(</id>)\\R?"
+            + "(<maintenance-association-end-point>)\\R?"
+            + "(<mep-identifier>)[0-9]*(</mep-identifier>)\\R?"
+            + "(<delay-measurements xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">)\\R?"
+            + "(<delay-measurement>)\\R?"
+            + "(<dm-id>)[0-9]*(</dm-id>)\\R?"
+            + "((<administrative-state>)(true|false)(</administrative-state>))?\\R?"
+            + "((<message-period>)(1000ms|100ms|10ms|3ms)(</message-period>))?\\R?"
+            + "(<priority>)[0-9]*(</priority>)\\R?"
+            + "((<frame-size>)[0-9]*(</frame-size>))?\\R?"
+            + "(<mep-id>)[0-9]*(</mep-id>)\\R?"
+            + "(</delay-measurement>)\\R?"
+            + "(</delay-measurements>)\\R?"
+            + "(</maintenance-association-end-point>)\\R?"
+            + "(</maintenance-association>)\\R?"
+            + "(</maintenance-domain>)\\R?"
+            + "(</mef-cfm>)\\R?"
+            + "(</config>)\\R?"
+            + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+
+    private static final String SAMPLE_SYSTEM_REPLY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<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>EA1000 unit test.</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_ERROR_REPLY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<rpc-error>"
+            + "<error-type>application</error-type>"
+            + "<error-tag>data-missing</error-tag>"
+            + "<error-severity>error</error-severity>"
+            + "<error-message>Request could not be completed because " +
+                "the relevant data model content does not exist.</error-message>"
+            + "</rpc-error>"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEAEVCUNI_REPLY_INIT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
+            + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+            + "<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_ESSENTIALS_REPLY =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"47\">"
+            + "<data>"
+            + "<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" "
+            + "xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" "
+            + "xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">"
+            + "<maintenance-domain>"
+            + "<id>1</id>"
+            + "<name>md-1</name>"
+            + "<maintenance-association>"
+            + "<id>1</id>"
+            + "<name>ma-1-1</name>"
+            + "<maintenance-association-end-point>"
+            + "<mep-identifier>1</mep-identifier>"
+            + "<mac-address>00:b0:ae:03:ff:31</mac-address>"
+            + "<remote-mep-database>"
+            + "<remote-mep>"
+            + "<remote-mep-id>1</remote-mep-id>"
+            + "</remote-mep>"
+            + "<remote-mep>"
+            + "<remote-mep-id>2</remote-mep-id>"
+            + "</remote-mep>"
+            + "</remote-mep-database>"
+            + "<msea-soam-pm:delay-measurements>"
+            + "<msea-soam-pm:delay-measurement>"
+            + "<msea-soam-pm:dm-id>1</msea-soam-pm:dm-id>"
+            + "</msea-soam-pm:delay-measurement>"
+            + "</msea-soam-pm:delay-measurements>"
+            + "<msea-soam-pm:loss-measurements>"
+            + "<msea-soam-pm:loss-measurement>"
+            + "<msea-soam-pm:lm-id>1</msea-soam-pm:lm-id>"
+            + "</msea-soam-pm:loss-measurement>"
+            + "<msea-soam-pm:loss-measurement>"
+            + "<msea-soam-pm:lm-id>2</msea-soam-pm:lm-id>"
+            + "</msea-soam-pm:loss-measurement>"
+            + "</msea-soam-pm:loss-measurements>"
+            + "</maintenance-association-end-point>"
+            + "</maintenance-association>"
+            + "</maintenance-domain>"
+            + "</mef-cfm>"
+            + "</data>"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"47\">"
+            + "<data>"
+            + "<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>" + EA1000CfmMepProgrammableTest.MD_ID_1 + "</name>"
+            + "<maintenance-association>"
+            + "<id>1</id>"
+            + "<name>" + EA1000CfmMepProgrammableTest.MA_ID_11 + "</name>"
+            + "<ccm-interval>3.3ms</ccm-interval>"
+            + "<maintenance-association-end-point>"
+            + "<mep-identifier>" + EA1000CfmMepProgrammableTest.MEP_111 + "</mep-identifier>"
+            + "<interface>eth0</interface>"
+            + "<primary-vid>20</primary-vid>"
+            + "<administrative-state>true</administrative-state>"
+            + "<mac-address>00:b0:ae:03:ff:31</mac-address>"
+            + "<ccm-ltm-priority>5</ccm-ltm-priority>"
+            + "<continuity-check>"
+                + "<cci-enabled>true</cci-enabled>"
+                + "<fng-state>defect-reported</fng-state>"
+                + "<highest-priority-defect-found>remote-invalid-ccm</highest-priority-defect-found>"
+                + "<active-defects>remote-rdi remote-invalid-ccm</active-defects>"
+                + "<ccm-sequence-error-count>0</ccm-sequence-error-count>"
+                + "<sent-ccms>197</sent-ccms>"
+            + "</continuity-check>"
+            + "<loopback>"
+            + "</loopback>"
+            + "<linktrace>"
+            + "</linktrace>"
+            + "<remote-mep-database>"
+                + "<remote-mep>"
+                    + "<remote-mep-id>1</remote-mep-id>"
+                    + "<remote-mep-state>failed</remote-mep-state>"
+                    + "<failed-ok-time>54654654</failed-ok-time>"
+                    + "<mac-address>aa:bb:cc:dd:ee:ff</mac-address>"
+                    + "<rdi>false</rdi>"
+                    + "<port-status-tlv>no-status-tlv</port-status-tlv>"
+                    + "<interface-status-tlv>dormant</interface-status-tlv>"
+                + "</remote-mep>"
+                + "<remote-mep>"
+                    + "<remote-mep-id>2</remote-mep-id>"
+                    + "<remote-mep-state>failed</remote-mep-state>"
+                    + "<failed-ok-time>54654654</failed-ok-time>"
+                    + "<mac-address>aa:bb:cc:dd:ee:ff</mac-address>"
+                    + "<rdi>false</rdi>"
+                    + "<port-status-tlv>no-status-tlv</port-status-tlv>"
+                    + "<interface-status-tlv>dormant</interface-status-tlv>"
+                + "</remote-mep>"
+            + "</remote-mep-database>"
+            + "<msea-soam-fm:operational-state>enabled</msea-soam-fm:operational-state>"
+            + "<msea-soam-fm:connectivity-status>partially-active</msea-soam-fm:connectivity-status>"
+            + "<msea-soam-fm:port-status>up</msea-soam-fm:port-status>"
+            + "<msea-soam-fm:interface-status>up</msea-soam-fm:interface-status>"
+            + "<msea-soam-fm:last-defect-sent>remote-rdi remote-mac-error</msea-soam-fm:last-defect-sent>"
+            + "<msea-soam-fm:rdi-transmit-status>true</msea-soam-fm:rdi-transmit-status>"
+            + "</maintenance-association-end-point>"
+            + "</maintenance-association>"
+            + "</maintenance-domain>"
+            + "</mef-cfm>"
+            + "</data>"
+            + "</rpc-reply>";
+
+
+    /**
+     * With an empty <last-defect-sent />. Retrieved from simulator.
+     */
+    private static final String SAMPLE_MSEACFM_MD_MA_MEP_FULL_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>" + EA1000CfmMepProgrammableTest.MD_ID_1 + "</name>"
+                + "<maintenance-association>"
+                    + "<id>1</id>"
+                    + "<name>" + EA1000CfmMepProgrammableTest.MA_ID_11 + "</name>"
+                    + "<maintenance-association-end-point>"
+                        + "<mep-identifier>" + EA1000CfmMepProgrammableTest.MEP_112 + "</mep-identifier>"
+                        + "<interface>eth0</interface>"
+                        + "<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>U2FtcGxlIGxhc3QgZXJyb3IgY2NtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+                            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+                            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+                            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
+                            + "</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 />"
+                        + "<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>20</remote-mep-id>"
+                                + "<remote-mep-state>ok</remote-mep-state>"
+                                + "<failed-ok-time>150859498</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>no-status-tlv</interface-status-tlv>"
+                            + "</remote-mep>"
+                            + "<remote-mep>"
+                                + "<remote-mep-id>30</remote-mep-id>"
+                                + "<remote-mep-state>ok</remote-mep-state>"
+                                + "<failed-ok-time>150859498</failed-ok-time>"
+                                + "<mac-address>53:65:61:6e:20:43</mac-address>"
+                                + "<rdi>true</rdi>"
+                                + "<port-status-tlv>no-status-tlv</port-status-tlv>"
+                                + "<interface-status-tlv>down</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>"
+                + "</maintenance-association>"
+            + "</maintenance-domain>"
+            + "</mef-cfm>"
+            + "</data>"
+            + "</rpc-reply>";
+
+    private static final String SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"47\">"
+            + "<data>"
+            + "<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" "
+            + "xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" "
+            + "xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">"
+            + "<maintenance-domain>"
+            + "<id>1</id>"
+            + "<name>md-1</name>"
+            + "<maintenance-association>"
+            + "<id>1</id>"
+            + "<name>ma-1-1</name>"
+            + "<maintenance-association-end-point>"
+            + "<mep-identifier>1</mep-identifier>"
+            + "<msea-soam-pm:delay-measurements>"
+            + "<msea-soam-pm:delay-measurement>"
+            + "<msea-soam-pm:dm-id>1</msea-soam-pm:dm-id>"
+            + "<msea-soam-pm:mep-id>10</msea-soam-pm:mep-id>"
+            + "<msea-soam-pm:administrative-state>true</msea-soam-pm:administrative-state>"
+            + "<msea-soam-pm:measurement-enable>frame-delay-two-way-bins "
+            + "frame-delay-two-way-max</msea-soam-pm:measurement-enable>"
+            + "<msea-soam-pm:message-period>3ms</msea-soam-pm:message-period>"
+            + "<msea-soam-pm:priority>6</msea-soam-pm:priority>"
+            + "<msea-soam-pm:frame-size>1000</msea-soam-pm:frame-size>"
+            + "<msea-soam-pm:measurement-interval>15</msea-soam-pm:measurement-interval>"
+            + "<msea-soam-pm:number-intervals-stored>32</msea-soam-pm:number-intervals-stored>"
+            + "<msea-soam-pm:session-status>active</msea-soam-pm:session-status>"
+            + "<msea-soam-pm:frame-delay-two-way>100</msea-soam-pm:frame-delay-two-way>"
+            + "<msea-soam-pm:inter-frame-delay-variation-two-way>101</msea-soam-pm:inter-frame-delay-variation-two-way>"
+//            + "<msea-soam-pm:current-stats>"
+//            + "</msea-soam-pm:current-stats>"
+//            + "<msea-soam-pm:history-stats>"
+//            + "</msea-soam-pm:history-stats>"
+            + "</msea-soam-pm:delay-measurement>"
+            + "</msea-soam-pm:delay-measurements>"
+            + "</maintenance-association-end-point>"
+            + "</maintenance-association>"
+            + "</maintenance-domain>"
+            + "</mef-cfm>"
+            + "</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(DatastoreId.datastore(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 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 (sampleXmlRegexSaFilteringErrorScenario.matcher(request).matches()) {
+            return SAMPLE_ERROR_REPLY;
+
+        } 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_ESSENTIALS_REPLY;
+
+        } else if (sampleXmlRegexGetMseaCfmFull.matcher(request).matches()) {
+            return SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY;
+
+        } else if (sampleXmlRegexGetMseaCfmFull2.matcher(request).matches()) {
+            return SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY2;
+
+        } else if (sampleXmlRegexDeleteMseaCfmMep.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexCreateMseaCfmMa.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexDeleteMseaCfmMa.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexDeleteMseaCfmRmep.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexDeleteMseaCfmMd.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexGetMseaDelay.matcher(request).matches()) {
+            return SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY;
+
+        } else if (sampleXmlRegexEditConfigDmCreate.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexTransmitLoopback.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else if (sampleXmlRegexAbortLoopback.matcher(request).matches()) {
+            return SAMPLE_REPLY_OK;
+
+        } else {
+            throw new NetconfException("MocknetconfSession. No sendRequest() case for query: " +
+                    request);
+        }
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java
new file mode 100644
index 0000000..bb65a4d
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import 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.MseaCfmNetconfService.DmEntryParts;
+import org.onosproject.drivers.microsemi.yang.impl.MseaCfmManager;
+import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil;
+import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil2;
+import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil3;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfDeviceInfo;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.MacAddress;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.DefaultAbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultMaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNamePrimaryVid;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.NamePrimaryVid;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.nameprimaryvid.NamePrimaryVidUnion;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameDomainName;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameDomainName;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.AddressType;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMacAddress;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMepId;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.DefaultTransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.DefaultTargetAddress;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.lossmeasurements.lossmeasurement.MessagePeriodEnum;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.sessionstatustype.SessionStatusTypeEnum;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
+
+public class MseaCfmManagerTest {
+
+    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, CfmConfigException {
+        MseaCfm mseaCfm = mseaCfmService.getMepEssentials(
+                MdIdCharStr.asMdId("md-1"),
+                MaIdCharStr.asMaId("ma-1-1"),
+                MepId.valueOf((short) 1), session);
+        assertNotNull(mseaCfm);
+
+        //See SAMPLE_MSEACFM_MD_MA_MEP_ESSENTIALS_REPLY in MockNetconfSessionEa1000
+        assertEquals(1, mseaCfm.mefCfm().maintenanceDomain().size());
+    }
+
+    @Test
+    public void testGetConfigMseaCfmFull()
+            throws NetconfException, CfmConfigException {
+        MseaCfm mseaCfm = mseaCfmService.getMepFull(
+                MdIdCharStr.asMdId("md-1"),
+                MaIdCharStr.asMaId("ma-1-1"),
+                MepId.valueOf((short) 1), session);
+        assertNotNull(mseaCfm);
+
+        //See SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY in MockNetconfSessionEa1000
+        assertEquals(1, mseaCfm.mefCfm().maintenanceDomain().size());
+        MaintenanceAssociationEndPoint mep = mseaCfm.mefCfm()
+                .maintenanceDomain().get(0)
+                .maintenanceAssociation().get(0)
+                .maintenanceAssociationEndPoint().get(0);
+        assertTrue(mep.administrativeState());
+        assertEquals("00:b0:ae:03:ff:31", mep.macAddress().toString());
+
+        org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain
+        .maintenanceassociation.maintenanceassociationendpoint
+        .AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+            MepIdUtil2.convertFmAugmentedMep(mep);
+
+        assertEquals("partially-active", augmentedMep.connectivityStatus().toString());
+        assertEquals("up", augmentedMep.interfaceStatus().enumeration().toString());
+    }
+
+    /**
+     * Driven by SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY.
+     * @throws NetconfException If there's a problem
+     */
+    @Test
+    public void testGetSoamDm() throws NetconfException {
+        MseaCfm mseaCfmWithDm = mseaCfmService.getSoamDm(
+                MdIdCharStr.asMdId("md-1"),
+                MaIdCharStr.asMaId("ma-1-1"),
+                MepId.valueOf((short) 1),
+                SoamId.valueOf(1),
+                DmEntryParts.ALL_PARTS, session);
+
+        assertNotNull(mseaCfmWithDm);
+        MaintenanceAssociationEndPoint mep = mseaCfmWithDm.mefCfm()
+            .maintenanceDomain().get(0)
+            .maintenanceAssociation().get(0)
+            .maintenanceAssociationEndPoint().get(0);
+
+        //Because of a checkstyle problem with typecasts including really long
+        //package names, this has to be handed off to a different class
+        org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain
+        .maintenanceassociation.maintenanceassociationendpoint
+        .AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep =
+                MepIdUtil.convertPmAugmentedMep(mep);
+
+        DelayMeasurement dm = augmentedMep.delayMeasurements().delayMeasurement().get(0);
+        assertEquals(true, dm.administrativeState());
+        assertTrue(dm.measurementEnable().get(3)); //frame-delay-two-way-bins
+        assertTrue(dm.measurementEnable().get(1)); //frame-delay-two-way-max
+
+        assertEquals(MessagePeriodEnum.YANGAUTOPREFIX3MS.name(), dm.messagePeriod().name());
+        assertEquals(6, dm.priority().uint8());
+        assertEquals(1000, dm.frameSize());
+        assertEquals(15, dm.measurementInterval());
+        assertEquals(32, dm.numberIntervalsStored());
+        assertEquals(SessionStatusTypeEnum.ACTIVE.name(),
+                dm.sessionStatus().enumeration().name());
+        assertEquals(100, dm.frameDelayTwoWay().uint32());
+        assertEquals(101, dm.interFrameDelayVariationTwoWay().uint32());
+
+        //The remoteMep of the DM is a choice, which for mepId is a leafref object
+        org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep
+        .DefaultMepId remoteMepId = MepIdUtil3.convertPmRemoteMepToMepId(dm.remoteMep());
+        assertNotNull(remoteMepId);
+        assertEquals(10, ((MepIdType) remoteMepId.mepId()).uint16());
+
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * Using mep Id 10.
+     */
+    @Test
+    public void testDeleteMseaMep() {
+        MaintenanceAssociationEndPoint mep10 = new DefaultMaintenanceAssociationEndPoint();
+        mep10.mepIdentifier(MepIdType.of(10));
+
+        MaintenanceAssociation ma1100 = new DefaultMaintenanceAssociation();
+        NamePrimaryVid pvid1100Name = new DefaultNamePrimaryVid();
+        pvid1100Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1100"));
+        ma1100.maNameAndTypeCombo(pvid1100Name);
+        ma1100.id((short) 1100);
+        ma1100.addToMaintenanceAssociationEndPoint(mep10);
+
+        MaintenanceDomain md = new DefaultMaintenanceDomain();
+        NameCharacterString mdName = new DefaultNameCharacterString();
+        mdName.name(new Identifier45("md-1"));
+        md.mdNameAndTypeCombo(mdName);
+        md.id((short) 1);
+        md.addToMaintenanceAssociation(ma1100);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(md);
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        mseaCfm.mefCfm(mefCfm);
+
+        try {
+            boolean deleted = mseaCfmService.deleteMseaMep(mseaCfm, session, DatastoreId.RUNNING);
+            assertTrue(deleted);
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail();
+        } catch (CfmConfigException e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    /**
+     * Using mep Id 10.
+     */
+    @Test
+    public void testDeleteMseaMa() {
+        MaintenanceAssociation ma1300 = new DefaultMaintenanceAssociation();
+        NamePrimaryVid pvid1300Name = new DefaultNamePrimaryVid();
+        pvid1300Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1300"));
+        ma1300.id((short) 1300);
+        ma1300.maNameAndTypeCombo(pvid1300Name);
+
+        MaintenanceDomain md = new DefaultMaintenanceDomain();
+        NameCharacterString mdName = new DefaultNameCharacterString();
+        mdName.name(new Identifier45("md-13"));
+        md.mdNameAndTypeCombo(mdName);
+        md.id((short) 13);
+        md.addToMaintenanceAssociation(ma1300);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(md);
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        mseaCfm.mefCfm(mefCfm);
+
+        try {
+            boolean deleted = mseaCfmService.deleteMseaMa(mseaCfm, session, DatastoreId.RUNNING);
+            assertTrue(deleted);
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail();
+        } catch (CfmConfigException e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+
+    @Test
+    public void testDeleteMseaRemoteMep() {
+        MaintenanceAssociation ma1100 = new DefaultMaintenanceAssociation();
+        NamePrimaryVid pvid1100Name = new DefaultNamePrimaryVid();
+        pvid1100Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1100"));
+        ma1100.maNameAndTypeCombo(pvid1100Name);
+        ma1100.id((short) 1100);
+        ma1100.addToRemoteMeps(MepIdType.of(100));
+        ma1100.addToRemoteMeps(MepIdType.of(101));
+
+        MaintenanceDomain md = new DefaultMaintenanceDomain();
+        NameCharacterString mdName = new DefaultNameCharacterString();
+        mdName.name(new Identifier45("md-1"));
+        md.mdNameAndTypeCombo(mdName);
+        md.id((short) 1);
+        md.addToMaintenanceAssociation(ma1100);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(md);
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        mseaCfm.mefCfm(mefCfm);
+
+        try {
+            boolean deleted = mseaCfmService.deleteMseaMaRMep(mseaCfm, session, DatastoreId.RUNNING);
+            assertTrue(deleted);
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail();
+        } catch (CfmConfigException e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    /**
+     * Using mep Id 10.
+     */
+    @Test
+    public void testDeleteMseaMdById() {
+
+        MaintenanceDomain md = new DefaultMaintenanceDomain();
+        NameDomainName mdName = new DefaultNameDomainName();
+        mdName.nameDomainName(NameDomainNameUnion.fromString("www.opennetworking.org"));
+        md.mdNameAndTypeCombo(mdName);
+        md.id((short) 10);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(md);
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        mseaCfm.mefCfm(mefCfm);
+
+        try {
+            boolean deleted = mseaCfmService.deleteMseaMd(mseaCfm, session, DatastoreId.RUNNING);
+            assertTrue(deleted);
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail();
+        } catch (CfmConfigException e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    /**
+     * Using mep Id 10.
+     */
+    @Test
+    public void testDeleteMseaMdByName() {
+
+        MaintenanceDomain md = new DefaultMaintenanceDomain();
+        NameDomainName mdName = new DefaultNameDomainName();
+        mdName.nameDomainName(NameDomainNameUnion.fromString("www.opennetworking.org"));
+        md.mdNameAndTypeCombo(mdName);
+
+        MefCfm mefCfm = new DefaultMefCfm();
+        mefCfm.addToMaintenanceDomain(md);
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        mseaCfm.mefCfm(mefCfm);
+
+        try {
+            mseaCfmService.deleteMseaMd(mseaCfm, session, DatastoreId.RUNNING);
+            fail("Should not have succeeded as no numeric id was given");
+        } catch (NetconfException | CfmConfigException e) {
+            assertEquals("An MD numeric ID must be given", e.getMessage());
+        }
+    }
+
+
+    /**
+     * Using Remote remote MEP ID and all arguments.
+     */
+    @Test
+    public void testTransmitLoopback1() {
+        TransmitLoopbackInput lbTr1 = new DefaultTransmitLoopbackInput();
+        lbTr1.maintenanceDomain(Short.valueOf((short) 1));
+        lbTr1.maintenanceAssociation(Short.valueOf((short) 2));
+        lbTr1.maintenanceAssociationEndPoint(Short.valueOf((short) 3));
+
+        DefaultTargetAddress ta = new DefaultTargetAddress();
+        DefaultMepId mepId = new DefaultMepId();
+        mepId.mepId(MepIdType.of(4));
+        ta.addressType((AddressType) mepId);
+        lbTr1.targetAddress(ta);
+
+//        lbTr1.dataTlv(new byte[]{0x01, 0x02, 0x03}); Not supported in onos-yang-tools just yet
+        lbTr1.numberOfMessages(10);
+        lbTr1.vlanDropEligible(true);
+        lbTr1.vlanPriority(PriorityType.of((short) 1));
+        try {
+            mseaCfmService.transmitLoopback(lbTr1, session);
+        } catch (NetconfException e) {
+            fail("Calling of TransmitLoopback failed: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Using Remote Mac address in place of remote MEP ID and fewer arguments.
+     */
+    @Test
+    public void testTransmitLoopback2() {
+        TransmitLoopbackInput lbTr2 = new DefaultTransmitLoopbackInput();
+
+        lbTr2.maintenanceDomain(Short.valueOf((short) 63));
+        lbTr2.maintenanceAssociation(Short.valueOf((short) 62));
+        lbTr2.maintenanceAssociationEndPoint(Short.valueOf((short) 61));
+
+        DefaultTargetAddress ta = new DefaultTargetAddress();
+        DefaultMacAddress macAddr = new DefaultMacAddress();
+        macAddr.macAddress(MacAddress.of("FF:EE:DD:CC:BB:AA"));
+        ta.addressType(macAddr);
+        lbTr2.targetAddress(ta);
+        try {
+            mseaCfmService.transmitLoopback(lbTr2, session);
+        } catch (NetconfException e) {
+            fail("Calling of TransmitLoopback failed: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAbortLoopback() throws NetconfException {
+        AbortLoopbackInput lbAbort = new DefaultAbortLoopbackInput();
+
+        lbAbort.maintenanceDomain((short) 70);
+        lbAbort.maintenanceAssociation((short) 71);
+        lbAbort.maintenanceAssociationEndPoint((short) 72);
+
+        try {
+            mseaCfmService.abortLoopback(lbAbort, session);
+        } catch (NetconfException e) {
+            fail("Calling of AbortLoopback failed: " + e.getMessage());
+        }
+    }
+
+    @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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java
new file mode 100644
index 0000000..29ac4a3
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
+
+import java.io.UncheckedIOException;
+import java.util.List;
+
+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());
+            }
+        }
+    }
+
+    /**
+     * See sampleXmlRegexSaFilteringErrorScenario in MockNetconfSessionEa1000.
+     */
+    @Test
+    public void testGetMseaSaFilteringMseaSaFilteringOpParamNetconfSessionError() {
+
+        SourceAddressRange sar = new DefaultSourceAddressRange();
+        sar.rangeId((short) 10);
+
+        InterfaceEth0 eth0 = new DefaultInterfaceEth0();
+        eth0.addToSourceAddressRange(sar);
+
+        SourceIpaddressFiltering sip = new DefaultSourceIpaddressFiltering();
+        sip.interfaceEth0(eth0);
+
+        MseaSaFilteringOpParam mseaSaFilteringConfig = new MseaSaFilteringOpParam();
+        mseaSaFilteringConfig.sourceIpaddressFiltering(sip);
+
+        try {
+            MseaSaFiltering result = mseaSaSvc.getMseaSaFiltering(mseaSaFilteringConfig, session);
+            fail("Should have thrown exception");
+        } catch (NetconfException ne) {
+            assertTrue(ne.getMessage().startsWith("NETCONF rpc-error"));
+        }
+    }
+
+    @Test
+    public void testSetMseaSaFilteringMseaSaFilteringOpParamNetconfSessionNcDsType() {
+
+        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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java
new file mode 100644
index 0000000..2865b5b
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceManagerTest.java
@@ -0,0 +1,496 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import 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/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java
new file mode 100644
index 0000000..7508511
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtilsTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import 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/ea1000/src/test/java/org/onosproject/yang/MockMicrosemiRegistrator.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/MockMicrosemiRegistrator.java
new file mode 100644
index 0000000..785ba8d
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/MockMicrosemiRegistrator.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.yang;
+
+import com.google.common.collect.ImmutableMap;
+import org.onosproject.models.microsemi.MicrosemiModelRegistrator;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.tool.YangNodeInfo;
+import org.onosproject.yang.model.YangModuleId;
+import org.onosproject.yang.runtime.AppModuleInfo;
+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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.fail;
+import static org.onosproject.yang.compiler.tool.YangCompilerManager.deSerializeDataModel;
+import static org.onosproject.yang.compiler.tool.YangCompilerManager.getYangNodes;
+import static org.onosproject.yang.compiler.tool.YangCompilerManager.processYangModel;
+
+public class MockMicrosemiRegistrator extends MicrosemiModelRegistrator {
+    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;
+
+    @Override
+    public void activate() {
+        modelRegistry = new DefaultYangModelRegistry();
+        List<YangNodeInfo> nodes = new ArrayList<>();
+        try {
+            for (YangNode node : getYangNodes(deSerializeDataModel(META_PATH))) {
+                nodes.add(new YangNodeInfo(node, false));
+            }
+
+            model = processYangModel(META_PATH, nodes, "test", false);
+            ModelRegistrationParam.Builder b =
+                    DefaultModelRegistrationParam.builder().setYangModel(model);
+            b.setYangModel(model);
+
+            ModelRegistrationParam registrationParam = getAppInfo(b).setYangModel(model).build();
+            modelRegistry.registerModel(registrationParam);
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            fail();
+        }
+    }
+
+
+    public void addAppInfo(Map<YangModuleId, AppModuleInfo> map) {
+        Map<YangModuleId, AppModuleInfo> appInfoCopy = new HashMap<>();
+        appInfoCopy.putAll(appInfo);
+        appInfoCopy.putAll(map);
+        appInfo = ImmutableMap.copyOf(appInfoCopy);
+    }
+
+    public YangModelRegistry registry() {
+        return modelRegistry;
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/MockYangRegistrator.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/MockYangRegistrator.java
new file mode 100644
index 0000000..c564e9a
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/MockYangRegistrator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.yang;
+
+import org.onosproject.models.common.YangModelRegistrator;
+import org.onosproject.yang.model.YangModuleId;
+import org.onosproject.yang.runtime.AppModuleInfo;
+
+
+import java.util.Map;
+
+public class MockYangRegistrator extends YangModelRegistrator {
+    public Map<YangModuleId, AppModuleInfo> getAppInfo() {
+        return appInfo;
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java
new file mode 100644
index 0000000..5cfa3ef
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/MockYangRuntimeManager.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.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.ModelObjectId;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.RpcContext;
+import org.onosproject.yang.model.SchemaContext;
+import org.onosproject.yang.model.SchemaContextProvider;
+import org.onosproject.yang.model.YangModel;
+import org.onosproject.yang.model.YangModule;
+import org.onosproject.yang.model.YangModuleId;
+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.DefaultSchemaContextProvider;
+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;
+        private DefaultSchemaContextProvider schemaContextProvider;
+
+        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);
+            schemaContextProvider = new DefaultSchemaContextProvider(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 YangModel getModel(String s) {
+            return modelRegistry.getModel(s);
+        }
+
+        @Override
+        public YangModule getModule(YangModuleId yangModuleId) {
+            return modelRegistry.getModule(yangModuleId);
+        }
+
+        @Override
+        public void registerSerializer(YangSerializer ys) {
+            serializerRegistry.registerSerializer(ys);
+        }
+
+        @Override
+        public void unregisterSerializer(YangSerializer ys) {
+            serializerRegistry.unregisterSerializer(ys);
+        }
+
+        @Override
+        public void registerAnydataSchema(ModelObjectId arg0, ModelObjectId arg1) {
+            throw new UnsupportedOperationException("registerAnydataSchema() needs to be implemented");
+        }
+
+        @Override
+        public void unregisterAnydataSchema(Class id, Class id1) {
+            throw new UnsupportedOperationException("unregisterAnydataSchema() needs to be implemented");
+
+        }
+
+        @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;
+        }
+
+    @Override
+    public RpcContext getRpcContext(ResourceId resourceId) {
+        return schemaContextProvider.getRpcContext(resourceId);
+    }
+}
diff --git a/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java b/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java
new file mode 100644
index 0000000..bb931f0
--- /dev/null
+++ b/drivers/microsemi/ea1000/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.yang.serializers.xml;
+
+import org.onosproject.yang.MockMicrosemiRegistrator;
+import org.onosproject.yang.MockYangRegistrator;
+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 MockMicrosemiRegistrator schemaProviderMicrosemi =
+            new MockMicrosemiRegistrator();
+    private static MockYangRegistrator schemaProviderYang =
+            new MockYangRegistrator();
+    private static final String NETCONF_NS =
+            "urn:ietf:params:xml:ns:netconf:base:1.0";
+    private static final String XMNLS_NC = "xmlns:xc";
+
+    public MockYangSerializerContext() {
+        schemaProviderMicrosemi.addAppInfo(schemaProviderYang.getAppInfo());
+        schemaProviderMicrosemi.activate();
+    }
+
+    @Override
+    public SchemaContext getContext() {
+        DefaultYangModelRegistry registry = (DefaultYangModelRegistry) schemaProviderMicrosemi.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/ea1000/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt b/drivers/microsemi/ea1000/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt
new file mode 100644
index 0000000..04db8030
--- /dev/null
+++ b/drivers/microsemi/ea1000/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/ea1000/src/test/resources/getConfigSaFiltering.xml b/drivers/microsemi/ea1000/src/test/resources/getConfigSaFiltering.xml
new file mode 100644
index 0000000..53bfe46
--- /dev/null
+++ b/drivers/microsemi/ea1000/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/ea1000/src/test/resources/getConfigSaFilteringReply.xml b/drivers/microsemi/ea1000/src/test/resources/getConfigSaFilteringReply.xml
new file mode 100644
index 0000000..6e1e040
--- /dev/null
+++ b/drivers/microsemi/ea1000/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/ea1000/src/test/resources/systemReply-Sample1.xml b/drivers/microsemi/ea1000/src/test/resources/systemReply-Sample1.xml
new file mode 100644
index 0000000..206bf45
--- /dev/null
+++ b/drivers/microsemi/ea1000/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/ea1000/src/test/resources/systemReply-Sample2.xml b/drivers/microsemi/ea1000/src/test/resources/systemReply-Sample2.xml
new file mode 100644
index 0000000..9592538
--- /dev/null
+++ b/drivers/microsemi/ea1000/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