Initial import of Microsemi Driver

Change-Id: I431d5f2c18e0b66a84c36273c3d9f0b84f223841

Added in BUCK files for building driver

Change-Id: I70681327f5b89f67e904c45d5974ab393652d51f

Corrected some syntax errors

Change-Id: I11150cc499c212005f80619e3900e747f1c23d96

Updated pom file to clean build

Change-Id: I6613ddc9e6802aa882e716cf04df210249870835

Added in utility functions for EA1000 Init

Change-Id: I51ffe0cf0daf9ffcea0e2479ee9982fcd1755440

Added YMS code to Microsemi Driver

Change-Id: I6f2a14e454c6909bf9e9f6025321c74c98c13c72

Updated driver to work with YMS and YCH

Change-Id: If7dbe3cd5bd1b6f902d09d6b2dc3895605d70f70

Implemented IetfSystemManager as a service and call on YMS as a service

Change-Id: If1c5e8482b1f53f578a3b0b770accd50024111cf

Moved YMS calls over in to Yang Service implementation

Change-Id: I044aad06f1ef7452bc48e88987787a683666cd72

improved unit test for IetfSystemManager

Change-Id: I48fbf831e7e5ca0e1ef3de8288e56da1b5ebb7a4

Major changes to IetfSystemManager to work in live system

Change-Id: I6e3aa118ba422151f314b9a666860d90905c9929

Added in retry mechanism for DeviceDescription to wait for YCH

Change-Id: If8e0f2c2f315ffd6db15627a11382a00217dd262

Added in implementation of MseaSaFiltering and unit tests

Change-Id: I34bf888e0e732bd4664d1fb8ef5abb679b1506fe

Updated driver with unit tests for MseaSaFiltering

Change-Id: I7ea2407a546622ff55d1ab21610c45697546d632

Modified removeFlowRules of Ea1000FlowRuleProgrammable

Change-Id: Ibb4a555f61887a8e6e42af588bb42f7b70f58efb

Added in manager for MseaUniEvc service with unit tests

Change-Id: Idc5853f46051548973f52a0659f7f88982ff960c

Implemented getFlowEntries() for EVCs from EA1000

Change-Id: Ie85dadfa7760f0b30a9bdf6ccd09cca9f097fff9

Added in translation of FlowRules in to EVC on EA1000

Change-Id: Icfb65171c3300c96b3ca4e18cbd327f0ed2190be

Added in handling of FlowRule deletion including complex ceVlanMaps

Change-Id: I7fd0bb0ef04d1b40e4b7d6a6db7f7ee662329780

Updated Service entries for new onos-yang-tools

Change-Id: I44e655202f3a45073e1e16f83737caed6e01afa8

Revert "Updated Service entries for new onos-yang-tools"

This reverts commit 642b550ef1de12ed59bad2eaa3a2da414d2e5e59.

Improved timeout mechanism for YANG model loading

Change-Id: If744ecd206372e822edf2b736c83226321a12256

Minor edits of EVC creation

Change-Id: Ib0a4763deaf6dce37625ba77f5095b39cd98272d

Added in CustomEvc and supporting classes

Change-Id: Iad60eb1bcd48d2aec55b894b2d419b51852c3b2f

Created CeVlanUtils to resolve loading problem

Change-Id: I0d63931ad2c5ad2725861ebc7dccc4d5fe7b9298

Modified startup check

Change-Id: I6e6bcfa7e615044cb08fe7ee2f8a6c8b89aabb21

Modified handlin of flow rules

Change-Id: I965a79c23298866122aeb94c6d9d584aafee3bd5

Fixed problem with ceVlanMap

Change-Id: If1458c35d0b95b5b25b6636f098292f9e91c06c6

Minor Pom edits

Change-Id: I5cefb18674aa04b1f50bd7e2306260c1c3ad3814

Commented out extension references in YANG files to avoid onos-yang-tools problems

Change-Id: I32fdb34c4f476f495fe28e75d0f410aaf14e2ec1

Corrected error in removing 0 in CeVlanMapUtils

Change-Id: I8cd1fd02788b81c2613364d5639ef6e090057f80

Changes in YMS to accomodate EA1000 driver

Change-Id: I6ae2b9bd2be49eae8d4ad2f929dfe3214c514550
diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java
new file mode 100644
index 0000000..24aad06
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammableTest.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.EthType.EtherType;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowEntry.FlowEntryState;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class EA1000FlowRuleProgrammableTest {
+    EA1000FlowRuleProgrammable frProgramable;
+
+    @Before
+    public void setUp() throws Exception {
+        frProgramable = new EA1000FlowRuleProgrammable();
+        frProgramable.setHandler(new MockEa1000DriverHandler());
+        assertNotNull(frProgramable.handler().data().deviceId());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testGetFlowEntries() {
+        //From MockNetconfSession sample of MseaSaFiltering
+        Collection<FlowEntry> flowEntries = frProgramable.getFlowEntries();
+
+        assertNotNull(flowEntries);
+        //There will be 12 flow entries
+        // 2 for IP Src Address filtering
+        // 2 for EVC 7 - one each port
+        // 8 for EVC 8 - one for host port, 7 on optics port because of ceVlanMap 12:14,20:22,25
+        assertEquals(12, flowEntries.size());
+
+        //Test the first Flow Entry
+        Iterator<FlowEntry> feIter = flowEntries.iterator();
+        while (feIter.hasNext()) {
+            FlowEntry fe = feIter.next();
+            assertTrue(fe.isPermanent());
+            assertEquals(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT, fe.priority());
+
+            Set<Criterion> criteria = fe.selector().criteria();
+            IPCriterion ipCr = null;
+            PortNumber port = null;
+            for (Criterion cr:criteria.toArray(new Criterion[criteria.size()])) {
+                if (cr.type() == Criterion.Type.IPV4_SRC) {
+                    ipCr = (IPCriterion) cr;
+                } else if (cr.type() == Criterion.Type.IN_PORT) {
+                    port = ((PortCriterion) cr).port();
+                } else if (cr.type() == Criterion.Type.VLAN_VID) {
+                    VlanId vid = ((VlanIdCriterion) cr).vlanId();
+                } else {
+                    fail("Unexpected Criterion type: " + cr.type().toString());
+                }
+            }
+            if (ipCr != null && (port == null || port.toLong() != 0L)) {
+                fail("Port number not equal 0 when IP Src Address filter is present");
+            }
+
+            List<Instruction> instructions = fe.treatment().allInstructions();
+
+            if (fe.tableId() == 1) {
+                //Note that in MockNetconf session 10.10.10.10/16 was entered
+                //but it has been corrected to the following by the OF implementation
+                assertEquals("10.10.0.0/16", ipCr.ip().toString());
+                assertEquals(FlowEntryState.ADDED, fe.state());
+            } else if (fe.tableId() == 2) {
+                //Likewise 20.30.40.50 has been truncated because of the 18 bit mask
+                assertEquals("20.30.0.0/18", ipCr.ip().toString());
+                assertEquals(FlowEntryState.ADDED, fe.state());
+            } else if (fe.tableId() == 7 || fe.tableId() == 8) {
+                // 7 and 8 are EVC entries - 2 elements - IN_PORT and VLAN_ID
+                assertEquals(2, fe.selector().criteria().size());
+                //In MockNetconfSession we're rigged it so that the last two chars of the
+                //flow id is the same as the VlanId
+                short vlanId = ((VlanIdCriterion) fe.selector().getCriterion(Type.VLAN_VID)).vlanId().toShort();
+                long flowId = fe.id().id();
+                String flowIdStr = String.valueOf(flowId).substring(String.valueOf(flowId).length() - 2);
+                assertEquals(flowIdStr, String.valueOf(vlanId));
+                if (((PortCriterion) fe.selector().getCriterion(Type.IN_PORT)).port().toLong() == 1L) {
+                    assertEquals(Instruction.Type.L2MODIFICATION, instructions.get(0).type());
+                }
+            } else {
+                fail("Unexpected Flow Entry Rule " + fe.tableId());
+            }
+        }
+    }
+
+    @Test
+    public void testSetFlowEntries() {
+        Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0));
+
+        TrafficTreatment treatmentDrop = DefaultTrafficTreatment.builder().drop().build();
+
+        Collection<FlowRule> frAddedList = new HashSet<FlowRule>();
+
+        FlowRule fr4 = new DefaultFlowRule.Builder()
+            .forDevice(frProgramable.handler().data().deviceId())
+            .forTable(4)
+            .withSelector(DefaultTrafficSelector.builder()
+                    .matchIPSrc(IpPrefix.valueOf("192.168.60.0/22"))
+                    .add(matchInPort).build())
+            .withTreatment(treatmentDrop)
+            .fromApp(new DefaultApplicationId(4, "Filter4"))
+            .makePermanent()
+            .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+            .build();
+        frAddedList.add(fr4);
+
+        FlowRule fr5 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(5)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchIPSrc(IpPrefix.valueOf("192.168.50.0/23"))
+                        .add(matchInPort).build())
+                .withTreatment(treatmentDrop)
+                .withCookie(Long.valueOf("5e0000abaa2772", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(fr5);
+
+        //Add in some EVCs - especially with complex ceVlanMaps
+        FlowRule frEvc1Vid19P0 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(1)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchInPort(PortNumber.portNumber(0L))
+                        .matchVlanId(VlanId.vlanId((short) 19))
+                        .build())
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .popVlan()
+                        .build())
+                .withCookie(Long.valueOf("1e0000abaa0019", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(frEvc1Vid19P0);
+
+        FlowRule frEvc1Vid20P0 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(1)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchInPort(PortNumber.portNumber(0L))
+                        .matchVlanId(VlanId.vlanId((short) 20))
+                        .build())
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .popVlan()
+                        .build())
+                .withCookie(Long.valueOf("1e0000abaa0020", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(frEvc1Vid20P0);
+
+        FlowRule frEvc1Vid21P1 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(1)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchInPort(PortNumber.portNumber(1L))
+                        .matchVlanId(VlanId.vlanId((short) 21))
+                        .build())
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .setVlanId(VlanId.vlanId((short) 250))
+                        .pushVlan(EtherType.QINQ.ethType())
+                        .build())
+                .withCookie(Long.valueOf("1e0000abaa0121", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(frEvc1Vid21P1);
+
+        FlowRule frEvc1Vid22P1 = new DefaultFlowRule.Builder()
+                .forDevice(frProgramable.handler().data().deviceId())
+                .forTable(1)
+                .withSelector(DefaultTrafficSelector.builder()
+                        .matchInPort(PortNumber.portNumber(1L))
+                        .matchVlanId(VlanId.vlanId((short) 22))
+                        .build())
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .setVlanId(VlanId.vlanId((short) 250))
+                        .pushVlan(EtherType.QINQ.ethType())
+                        .build())
+                .withCookie(Long.valueOf("1e0000abaa0122", 16))
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frAddedList.add(frEvc1Vid22P1);
+
+        Collection<FlowRule> returnedFrList = frProgramable.applyFlowRules(frAddedList);
+
+        assertNotNull(returnedFrList);
+        assertEquals(6, returnedFrList.size());
+
+        //Test the scenario like in FlowRuleManager$InternalFlowRuleProviderService.pushFlowMetricsInternal()
+        Map<FlowEntry, FlowEntry> storedRules = Maps.newHashMap();
+        frAddedList.forEach(f -> storedRules.put(new DefaultFlowEntry(f), new DefaultFlowEntry(f)));
+        List<FlowEntry> feList = Lists.newArrayList();
+        returnedFrList.forEach(f -> feList.add(new DefaultFlowEntry(f)));
+
+        for (FlowEntry rule : feList) {
+            FlowEntry fer = storedRules.remove(rule);
+            assertNotNull(fer);
+            assertTrue(fer.exactMatch(rule));
+        }
+
+        for (FlowRule fr:returnedFrList.toArray(new FlowRule[2])) {
+            if (fr.tableId() == 4) {
+                assertEquals("IPV4_SRC:192.168.60.0/22",
+                        ((IPCriterion) fr.selector().getCriterion(Type.IPV4_SRC)).toString());
+            } else if (fr.tableId() == 5) {
+                assertEquals("IPV4_SRC:192.168.50.0/23",
+                        ((IPCriterion) fr.selector().getCriterion(Type.IPV4_SRC)).toString());
+                assertEquals(Long.valueOf("5e0000abaa2772", 16), fr.id().id());
+            } else if (fr.tableId() == 1) {
+                //TODO add in tests
+            } else {
+                fail("Unexpected flow rule " + fr.tableId() + " in test");
+            }
+        }
+    }
+
+    @Test
+    public void testRemoveFlowEntries() {
+        TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();
+        Criterion matchInPort0 = Criteria.matchInPort(PortNumber.portNumber(0));
+        Criterion matchInPort1 = Criteria.matchInPort(PortNumber.portNumber(1));
+
+        TrafficTreatment.Builder trDropBuilder = DefaultTrafficTreatment.builder();
+        TrafficTreatment treatmentDrop = trDropBuilder.drop().build();
+
+        Collection<FlowRule> frRemoveList = new HashSet<FlowRule>();
+        ApplicationId app = new DefaultApplicationId(1, "org.onosproject.rest");
+
+        Criterion matchIpSrc1 = Criteria.matchIPSrc(IpPrefix.valueOf("10.10.10.10/16"));
+        TrafficSelector selector1 = tsBuilder.add(matchIpSrc1).add(matchInPort0).build();
+        FlowRule.Builder frBuilder1 = new DefaultFlowRule.Builder();
+        frBuilder1.forDevice(frProgramable.handler().data().deviceId())
+                .withSelector(selector1)
+                .withTreatment(treatmentDrop)
+                .forTable(2)
+                .fromApp(app)
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT);
+        frRemoveList.add(frBuilder1.build());
+
+        Criterion matchIpSrc2 = Criteria.matchIPSrc(IpPrefix.valueOf("10.30.10.10/16"));
+        TrafficSelector selector2 = tsBuilder.add(matchIpSrc2).add(matchInPort0).build();
+        FlowRule.Builder frBuilder2 = new DefaultFlowRule.Builder();
+        frBuilder2.forDevice(frProgramable.handler().data().deviceId())
+                .withSelector(selector2)
+                .withTreatment(treatmentDrop)
+                .forTable(3)
+                .fromApp(app)
+                .makePermanent()
+                .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+                .build();
+        frRemoveList.add(frBuilder2.build());
+
+
+        TrafficTreatment.Builder trVlanPopBuilder = DefaultTrafficTreatment.builder();
+        TrafficTreatment treatmentVlanPop = trVlanPopBuilder.popVlan().build();
+
+
+        Criterion matchVlan710 = Criteria.matchVlanId(VlanId.vlanId((short) 710));
+        TrafficSelector selector3 = DefaultTrafficSelector.builder().add(matchVlan710).add(matchInPort1).build();
+        FlowRule.Builder frBuilder3 = new DefaultFlowRule.Builder();
+        frBuilder3.forDevice(frProgramable.handler().data().deviceId())
+            .withSelector(selector3)
+            .withTreatment(treatmentVlanPop)
+            .forTable(7)
+            .fromApp(app)
+            .makePermanent()
+            .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+            .build();
+        frRemoveList.add(frBuilder3.build());
+
+
+        Criterion matchVlan101 = Criteria.matchVlanId(VlanId.vlanId((short) 101));
+        TrafficSelector selector4 = DefaultTrafficSelector.builder().add(matchVlan101).add(matchInPort1).build();
+        FlowRule.Builder frBuilder4 = new DefaultFlowRule.Builder();
+        frBuilder4.forDevice(frProgramable.handler().data().deviceId())
+            .withSelector(selector4)
+            .withTreatment(treatmentVlanPop)
+            .forTable(1)
+            .fromApp(app)
+            .makePermanent()
+            .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+            .build();
+        frRemoveList.add(frBuilder4.build());
+
+        Criterion matchVlan102 = Criteria.matchVlanId(VlanId.vlanId((short) 102));
+        TrafficSelector selector5 = DefaultTrafficSelector.builder().add(matchVlan102).add(matchInPort0).build();
+        FlowRule.Builder frBuilder5 = new DefaultFlowRule.Builder();
+        frBuilder5.forDevice(frProgramable.handler().data().deviceId())
+            .withSelector(selector5)
+            .withTreatment(treatmentVlanPop)
+            .forTable(1)
+            .fromApp(app)
+            .makePermanent()
+            .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT)
+            .build();
+        frRemoveList.add(frBuilder5.build());
+
+        Collection<FlowRule> removedFrList = frProgramable.removeFlowRules(frRemoveList);
+        assertNotNull(removedFrList);
+        assertEquals(5, removedFrList.size());
+
+        for (FlowRule frRemoved:removedFrList) {
+            assertNotNull(frRemoved);
+        }
+    }
+}
diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java
new file mode 100644
index 0000000..b00b321
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/EA1000MeterProviderTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import java.util.HashSet;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager;
+import org.onosproject.drivers.microsemi.yang.MockNetconfSessionEa1000;
+import org.onosproject.drivers.netconf.MockNetconfController;
+import org.onosproject.drivers.netconf.MockNetconfDevice;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.DefaultBand;
+import org.onosproject.net.meter.DefaultMeter;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.Meter.Unit;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.net.meter.MeterOperation;
+import org.onosproject.net.meter.MeterOperation.Type;
+import org.onosproject.netconf.NetconfController;
+
+public class EA1000MeterProviderTest {
+
+    private EA1000MeterProvider meterProvider;
+    private NetconfController controller;
+    private DeviceId mockDeviceId;
+    private MockMseaUniEvcServiceManager mseaUniEvcServiceSvc;
+
+    @Before
+    public void setUp() throws Exception {
+        mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+        controller = new MockNetconfController();
+        MockNetconfDevice device = (MockNetconfDevice) controller.connectDevice(mockDeviceId);
+        device.setNcSessionImpl(MockNetconfSessionEa1000.class);
+        mseaUniEvcServiceSvc = new MockMseaUniEvcServiceManager();
+        mseaUniEvcServiceSvc.activate();
+        meterProvider = new TestEA1000MeterProvider(controller, mseaUniEvcServiceSvc);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testPerformMeterOperationDeviceIdMeterAdd() {
+        DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+
+        Band cbsBand = DefaultBand.builder()
+                .ofType(Band.Type.REMARK) //Committed - CIR & CBS
+                .withRate(37500L)
+                .burstSize(2000)
+                .dropPrecedence((short) 0)
+                .build();
+
+        Band ebsBand = DefaultBand.builder()
+                .ofType(Band.Type.DROP) //Excess - EIR & EBS
+                .withRate(50000L) //The rate at which we drop - for EA 1000 subtract CIR to get EIR
+                .burstSize(3000) //The burst rate to drop at
+                .build();
+
+        Meter.Builder mBuilder = DefaultMeter.builder()
+                .forDevice(mockDeviceId)
+                .withId(MeterId.meterId(1))
+                .fromApp(new DefaultApplicationId(101, "unit.test"))
+                .burst()
+                .withUnit(Unit.KB_PER_SEC)
+                .withBands(new HashSet<Band>() { { add(cbsBand); add(ebsBand); } });
+
+        MeterOperation meterOp = new MeterOperation(mBuilder.build(), Type.ADD);
+
+        meterProvider.performMeterOperation(mockDeviceId, meterOp);
+        //The NETCONF XML generated by this matches the pattern
+        // sampleXmlRegexEditConfigBwpGroup1
+        // in MockNetconfSession
+    }
+
+    @Test
+    public void testPerformMeterOperationDeviceIdMeterRemove() {
+        DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+
+        Band cbsBand = DefaultBand.builder()
+                .ofType(Band.Type.REMARK) //Committed - CIR & CBS
+                .withRate(37500L)
+                .burstSize(2000)
+                .dropPrecedence((short) 0)
+                .build();
+
+        Meter.Builder mBuilder = DefaultMeter.builder()
+                .forDevice(mockDeviceId)
+                .withId(MeterId.meterId(1))
+                .fromApp(new DefaultApplicationId(101, "unit.test"))
+                .burst()
+                .withBands(new HashSet<Band>() { { add(cbsBand); } });
+
+        MeterOperation meterOp = new MeterOperation(mBuilder.build(), Type.REMOVE);
+
+        meterProvider.performMeterOperation(mockDeviceId, meterOp);
+        //The NETCONF XML generated by this matches the pattern
+        // sampleXmlRegexEditConfigBwpGroup1
+        // in MockNetconfSession
+    }
+
+}
diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java
new file mode 100644
index 0000000..a53c6e3
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoaderTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import org.junit.Before;
+import org.onosproject.net.driver.AbstractDriverLoaderTest;
+
+
+/**
+ * Microsemi drivers loader test.
+ */
+public class MicrosemiDriversLoaderTest extends AbstractDriverLoaderTest {
+
+    @Before
+    public void setUp() {
+        loader = new MicrosemiDriversLoader();
+    }
+}
diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
new file mode 100644
index 0000000..78a9d32
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onosproject.core.CoreService;
+import org.onosproject.drivers.microsemi.yang.MockMseaSaFilteringManager;
+import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager;
+import org.onosproject.drivers.microsemi.yang.MockNetconfSessionEa1000;
+import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.drivers.netconf.MockCoreService;
+import org.onosproject.drivers.netconf.MockNetconfController;
+import org.onosproject.drivers.netconf.MockNetconfDevice;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.DefaultDriver;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.flow.FlowRuleProgrammable;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+
+/**
+ * A Mock implementation of the DriverHandler to facilitate unit tests.
+ *
+ * This brings in the implementations of MockMseaSaFilteringManager, MockMseaUniEvcServiceManager,
+ * MockCoreService, MockNetconfDevice and MockNetconfSessionEa1000
+ */
+public class MockEa1000DriverHandler implements DriverHandler {
+
+    private static final String MICROSEMI_DRIVERS = "com.microsemi.drivers";
+
+    private DriverData mockDriverData;
+
+    private NetconfController ncc;
+    private MockMseaSaFilteringManager mseaSaFilteringService;
+    private MockMseaUniEvcServiceManager mseaUniEvcService;
+    private CoreService coreService;
+
+    public MockEa1000DriverHandler() throws NetconfException {
+        Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours =
+                new HashMap<Class<? extends Behaviour>, Class<? extends Behaviour>>();
+        behaviours.put(FlowRuleProgrammable.class, FlowRuleProgrammable.class);
+
+        Map<String, String> properties = new HashMap<String, String>();
+
+        Driver mockDriver =
+                new DefaultDriver("mockDriver", null, "ONOSProject", "1.0.0", "1.0.0", behaviours, properties);
+        DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+        mockDriverData = new DefaultDriverData(mockDriver, mockDeviceId);
+
+
+        ncc = new MockNetconfController();
+        MockNetconfDevice device = (MockNetconfDevice) ncc.connectDevice(mockDeviceId);
+        device.setNcSessionImpl(MockNetconfSessionEa1000.class);
+
+        mseaSaFilteringService = new MockMseaSaFilteringManager();
+        mseaSaFilteringService.activate();
+
+        mseaUniEvcService = new MockMseaUniEvcServiceManager();
+        mseaUniEvcService.activate();
+
+        coreService = new MockCoreService();
+        coreService.registerApplication(MICROSEMI_DRIVERS);
+    }
+
+    @Override
+    public Driver driver() {
+        return mockDriverData.driver();
+    }
+
+    @Override
+    public DriverData data() {
+        return mockDriverData;
+    }
+
+    @Override
+    public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T> T get(Class<T> serviceClass) {
+        if (serviceClass.equals(NetconfController.class)) {
+            return (T) ncc;
+
+        } else if (serviceClass.equals(MseaSaFilteringNetconfService.class)) {
+            return (T) mseaSaFilteringService;
+
+        } else if (serviceClass.equals(MseaUniEvcServiceNetconfService.class)) {
+            return (T) mseaUniEvcService;
+
+        } else if (serviceClass.equals(CoreService.class)) {
+            return (T) coreService;
+
+        }
+
+        return null;
+    }
+
+}
diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java
new file mode 100644
index 0000000..64dd80e
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/RpcResultParserTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.junit.Assert.*;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.junit.Test;
+
+public class RpcResultParserTest {
+
+    private static final String SAMPLE1_XML = "/systemReply-Sample1.xml";
+    private static final String SAMPLE2_XML = "/systemReply-Sample2.xml";
+
+    @Test
+    public void testSerialNumber1() {
+        String serialNumberReply = loadXml(SAMPLE1_XML);
+        String serialNumber = RpcResultParser.parseXml(serialNumberReply, "serial-number");
+        assertEquals("Eagle Simulator.", serialNumber);
+    }
+
+    @Test
+    public void testSerialNumber2() {
+        String serialNumberReply = loadXml(SAMPLE2_XML);
+        String serialNumber = RpcResultParser.parseXml(serialNumberReply, "serial-number");
+        assertEquals(null, serialNumber);
+    }
+
+    @Test
+    public void testOsRelease1() {
+        String osReleaseReply = loadXml(SAMPLE1_XML);
+        String osRelease = RpcResultParser.parseXml(osReleaseReply, "os-release");
+        assertEquals("2.6.33-arm1-MSEA1000--00326-g643be76.x.0.0.212", osRelease);
+    }
+
+    @Test
+    public void testOsRelease2() {
+        String osReleaseReply = loadXml(SAMPLE2_XML);
+        String osRelease = RpcResultParser.parseXml(osReleaseReply, "os-release");
+        assertEquals(null, osRelease);
+    }
+
+    @Test
+    public void testLongitude() {
+        String longitudeReply = loadXml(SAMPLE1_XML);
+        String longitudeStr = RpcResultParser.parseXml(longitudeReply, "longitude");
+        assertEquals("-8.4683990", longitudeStr);
+    }
+
+    @Test
+    public void testLatitude() {
+        String latitudeReply = loadXml(SAMPLE1_XML);
+        String latitudeStr = RpcResultParser.parseXml(latitudeReply, "latitude");
+        assertEquals("51.9036140", latitudeStr);
+    }
+
+
+    private static String loadXml(final String fileName) {
+
+        InputStream inputStream = RpcResultParserTest.class.getResourceAsStream(fileName);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+        StringBuilder result = new StringBuilder();
+        try {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                result.append(line);
+            }
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return result.toString();
+    }
+}
\ No newline at end of file
diff --git a/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java
new file mode 100644
index 0000000..e56e121
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/src/test/java/org/onosproject/drivers/microsemi/TestEA1000MeterProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.netconf.NetconfController;
+
+public class TestEA1000MeterProvider extends EA1000MeterProvider {
+
+    public TestEA1000MeterProvider(NetconfController controller,
+            MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc) {
+        this.controller = controller;
+        this.mseaUniEvcServiceSvc = mseaUniEvcServiceSvc;
+    }
+}
diff --git a/drivers/microsemi/ea1000driver/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt b/drivers/microsemi/ea1000driver/src/test/resources/CarrierEthernetFeature-sampleEvcConfig1.txt
new file mode 100644
index 0000000..04db8030
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/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/ea1000driver/src/test/resources/getConfigSaFiltering.xml b/drivers/microsemi/ea1000driver/src/test/resources/getConfigSaFiltering.xml
new file mode 100644
index 0000000..53bfe46
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/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/ea1000driver/src/test/resources/getConfigSaFilteringReply.xml b/drivers/microsemi/ea1000driver/src/test/resources/getConfigSaFilteringReply.xml
new file mode 100644
index 0000000..6e1e040
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/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/ea1000driver/src/test/resources/systemReply-Sample1.xml b/drivers/microsemi/ea1000driver/src/test/resources/systemReply-Sample1.xml
new file mode 100644
index 0000000..206bf45
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/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/ea1000driver/src/test/resources/systemReply-Sample2.xml b/drivers/microsemi/ea1000driver/src/test/resources/systemReply-Sample2.xml
new file mode 100644
index 0000000..9592538
--- /dev/null
+++ b/drivers/microsemi/ea1000driver/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