Updating Microsemi Driver to onos-yang-tools 2.x
Change-Id: I80e3348087518a8f9a742c813b6238371a3f8f97
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java
new file mode 100644
index 0000000..4df22ec
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000FlowRuleProgrammable.java
@@ -0,0 +1,974 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.math.BigInteger;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
+
+import org.onlab.packet.EthType;
+import org.onlab.packet.EthType.EtherType;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.drivers.microsemi.yang.UniSide;
+import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnic;
+import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnin;
+import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowEntry.FlowEntryState;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleProgrammable;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanHeaderInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfDevice;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.DefaultSourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.DefaultInterfaceEth0;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.InterfaceEth0;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.DefaultSourceAddressRange;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.FilterAdminStateEnum;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.VlanIdType;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.DefaultFlowMapping;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagOverwrite;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPop;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPush;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagOverwrite;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPop;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPush;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.tagpush.tagpush.PushTagTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultUni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Uni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.DefaultEvc;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.Evc;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.DefaultEvcPerUni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.EvcPerUni;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin;
+import org.slf4j.Logger;
+
+/**
+ * An implementation of the FlowRuleProgrammable behaviour for the EA10000 device.
+ *
+ * This device is not a native Open Flow device. It has only a NETCONF interface for configuration
+ * status retrieval and notifications. It supports only a small subset of OpenFlow rules.<br>
+ *
+ * The device supports only:<br>
+ * 1) Open flow rules that blocks certain IP address ranges, but only those incoming on Port 0
+ * and has a limit of 10 such rules<br>
+ * 2) Open flow rules that PUSH, POP and OVERWRITE VLAN tags on both ports. This can push and overwrite
+ * both C-TAGs (0x8100) and S-TAGs (0x88a8).
+ */
+public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
+
+ protected final Logger log = getLogger(getClass());
+ public static final String MICROSEMI_DRIVERS = "com.microsemi.drivers";
+ public static final int PRIORITY_DEFAULT = 50000;
+ //To protect the NETCONF session from concurrent access across flow addition and removal
+ static Semaphore sessionMutex = new Semaphore(1);
+
+ /**
+ * Get the flow entries that are present on the EA1000.
+ * Since the EA1000 does not have any 'real' flow entries these are retrieved from 2 configuration
+ * areas on the EA1000 NETCONF model - from SA filtering YANG model and from EVC UNI YANG model.<br>
+ * The flow entries must match exactly the FlowRule entries in the ONOS store. If they are not an
+ * exact match the device will be requested to remove those flows and the FlowRule will stay in a
+ * PENDING_ADD state.
+ * @return A collection of Flow Entries
+ */
+ @Override
+ public Collection<FlowEntry> getFlowEntries() {
+ Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
+
+ UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
+ NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+ NetconfDevice ncDevice = controller.getDevicesMap().get(handler().data().deviceId());
+ if (ncDevice == null) {
+ log.error("Internal ONOS Error. Device has been marked as reachable, " +
+ "but deviceID {} is not in Devices Map. Continuing with empty description",
+ handler().data().deviceId());
+ return flowEntryCollection;
+ }
+ NetconfSession session = ncDevice.getSession();
+ CoreService coreService = checkNotNull(handler().get(CoreService.class));
+ ApplicationId appId = coreService.getAppId(MICROSEMI_DRIVERS);
+ MseaSaFilteringNetconfService mseaSaFilteringService =
+ (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
+ MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
+ (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
+ log.debug("getFlowEntries() called on EA1000FlowRuleProgrammable");
+
+ //First get the MseaSaFiltering rules
+ SourceIpaddressFiltering sip =
+ new DefaultSourceIpaddressFiltering();
+
+ MseaSaFilteringOpParam op =
+ new MseaSaFilteringOpParam();
+ op.sourceIpaddressFiltering(sip);
+
+ try {
+ MseaSaFiltering saFilteringCurrent =
+ mseaSaFilteringService.getMseaSaFiltering(op, session);
+ if (saFilteringCurrent != null &&
+ saFilteringCurrent.sourceIpaddressFiltering() != null) {
+ flowEntryCollection.addAll(
+ convertSaFilteringToFlowRules(saFilteringCurrent, appId));
+ }
+ } catch (NetconfException e) {
+ if (e.getCause() instanceof TimeoutException) {
+ log.warn("Timeout exception getting SA Filt Flow Entries from {}",
+ handler().data().deviceId());
+ return flowEntryCollection;
+ } else {
+ log.error("Unexpected error on SA Filt getFlowEntries on {}",
+ handler().data().deviceId(), e);
+ }
+ }
+
+
+ //Then get the EVCs - there will be a flow entry per EVC
+ MefServices mefServices = new DefaultMefServices();
+ mefServices.uni(new DefaultUni());
+
+ MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
+ mseaUniEvcServiceFilter.mefServices(mefServices);
+ try {
+ MseaUniEvcService uniEvcCurrent =
+ mseaUniEvcServiceSvc.getConfigMseaUniEvcService(mseaUniEvcServiceFilter,
+ session, DatastoreId.RUNNING);
+
+ flowEntryCollection.addAll(
+ convertEvcUniToFlowRules(uniEvcCurrent, portAssignment));
+
+ } catch (NetconfException e) {
+ if (e.getCause() instanceof TimeoutException) {
+ log.warn("Timeout exception getting EVC Flow Entries from {}",
+ handler().data().deviceId());
+ return flowEntryCollection;
+ } else {
+ log.error("Unexpected error on EVC getFlowEntries on {}",
+ handler().data().deviceId(), e);
+ }
+ }
+
+ return flowEntryCollection;
+ }
+
+ /**
+ * Apply the flow entries to the EA1000.
+ * Since the EA1000 does not have any 'real' flow entries these are converted 2 configuration
+ * areas on the EA1000 NETCONF model - to SA filtering YANG model and to EVC UNI YANG model.<br>
+ * Only a subset of the possible OpenFlow rules are supported. Any rule that's not handled
+ * will not be in the returned set.
+ *
+ * @param rules A collection of Flow Rules to be applied to the EA1000
+ * @return A collection of the Flow Rules that have been added.
+ */
+ @Override
+ public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
+ Collection<FlowRule> frAdded = new HashSet<FlowRule>();
+ if (rules == null || rules.size() == 0) {
+ return rules;
+ }
+ NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+ NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+ MseaSaFilteringNetconfService mseaSaFilteringService =
+ (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
+ MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
+ (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
+ log.debug("applyFlowRules() called on EA1000FlowRuleProgrammable with {} rules.", rules.size());
+ // FIXME: Change this so it's dynamically driven
+ UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
+
+ List<SourceAddressRange> saRangeList = new ArrayList<SourceAddressRange>();
+ Map<Integer, Evc> evcMap = new HashMap<>();
+
+ //Retrieve the list of actual EVCs and the CeVlanMaps from device
+ List<Evc> activeEvcs = new ArrayList<>();
+ try {
+ sessionMutex.acquire();
+ MseaUniEvcService evcResponse =
+ mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING);
+ //There could be zero or more EVCs
+ if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) {
+ activeEvcs.addAll(evcResponse.mefServices().uni().evc());
+ }
+ } catch (NetconfException | InterruptedException e1) {
+ log.warn("Unexpected error on applyFlowRules", e1);
+ }
+
+ for (FlowRule fr : rules) {
+
+ // IP SA Filtering can only apply to Port 0 optics
+ if (fr.selector().getCriterion(Type.IPV4_SRC) != null &&
+ fr.selector().getCriterion(Type.IN_PORT) != null &&
+ ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) {
+ parseFrForSaRange(frAdded, saRangeList, fr);
+
+ // EVCs will be defined by Flow Rules relating to VIDs
+ } else if (fr.selector().getCriterion(Type.VLAN_VID) != null &&
+ fr.selector().getCriterion(Type.IN_PORT) != null) {
+ //There could be many Flow Rules for one EVC depending on the ceVlanMap
+ //Cannot build up the EVC until we know the details - the key is the tableID and port
+ parseFrForEvcs(frAdded, evcMap, activeEvcs, portAssignment, fr);
+ } else {
+ log.info("Unexpected Flow Rule type applied: " + fr);
+ }
+ }
+
+ //If there are IPv4 Flow Rules created commit them now through the
+ //MseaSaFiltering service
+ if (saRangeList.size() > 0) {
+ try {
+ mseaSaFilteringService.setMseaSaFiltering(
+ buildSaFilteringObject(saRangeList), session, DatastoreId.RUNNING);
+ } catch (NetconfException e) {
+ log.error("Error applying Flow Rules to SA Filtering - will try again: " + e.getMessage());
+ sessionMutex.release();
+ return frAdded;
+ }
+ }
+ //If there are EVC flow rules then populate the MseaUniEvc part of EA1000
+ if (evcMap.size() > 0) {
+ List<Evc> evcList = evcMap.entrySet().stream()
+ .map(x -> x.getValue())
+ .collect(Collectors.toList());
+ Uni uni = new DefaultUni();
+ URI deviceName = handler().data().deviceId().uri();
+ uni.name(new Identifier45("Uni-on-"
+ + deviceName.getSchemeSpecificPart()));
+ uni.evc(evcList);
+
+ List<BwpGroup> bwpGroupList = new ArrayList<BwpGroup>();
+ BwpGroup bwpGrp = new DefaultBwpGroup();
+ bwpGrp.groupIndex((short) 0);
+ bwpGroupList.add(bwpGrp);
+ Profiles profiles = new DefaultProfiles();
+ profiles.bwpGroup(bwpGroupList);
+
+ MefServices mefServices = new DefaultMefServices();
+ mefServices.uni(uni);
+ mefServices.profiles(profiles);
+
+ MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
+ mseaUniEvcServiceFilter.mefServices(mefServices);
+ try {
+ mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, DatastoreId.RUNNING);
+ } catch (NetconfException e) {
+ log.error("Error applying Flow Rules to EVC - will try again: " + e.getMessage());
+ sessionMutex.release();
+ return frAdded;
+ }
+ }
+ sessionMutex.release();
+ return frAdded;
+ }
+
+ /**
+ * Remove flow rules from the EA1000.
+ * Since the EA1000 does not have any 'real' flow entries these are converted 2 configuration
+ * areas on the EA1000 NETCONF model - to SA filtering YANG model and to EVC UNI YANG model.
+ *
+ * @param rulesToRemove A collection of Flow Rules to be removed to the EA1000
+ * @return A collection of the Flow Rules that have been removed.
+ */
+ @Override
+ public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rulesToRemove) {
+ NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+ NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+ MseaSaFilteringNetconfService mseaSaFilteringService =
+ (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
+ MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
+ (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
+ UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
+ log.debug("removeFlowRules() called on EA1000FlowRuleProgrammable with {} rules.", rulesToRemove.size());
+
+ if (rulesToRemove.size() == 0) {
+ return rulesToRemove;
+ }
+
+ //Retrieve the list of actual EVCs and the CeVlanMaps from device
+ List<Evc> activeEvcs = new ArrayList<>();
+ List<Short> acvtiveFiltRanges = new ArrayList<>();
+ try {
+ sessionMutex.acquire();
+ MseaUniEvcService evcResponse =
+ mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING);
+ //There could be zero or more EVCs
+ if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) {
+ activeEvcs.addAll(evcResponse.mefServices().uni().evc());
+ }
+ mseaSaFilteringService.getConfigMseaSaFilterIds(session).forEach(
+ r -> acvtiveFiltRanges.add(r.rangeId()));
+
+ } catch (NetconfException | InterruptedException e1) {
+ log.warn("Error on removeFlowRules.", e1);
+ }
+
+ List<SourceAddressRange> saRangeList = new ArrayList<SourceAddressRange>();
+ Map<Integer, String> ceVlanMapMap = new HashMap<>();
+ Map<Integer, List<Short>> flowIdMap = new HashMap<>();
+
+ Collection<FlowRule> rulesRemoved = new HashSet<FlowRule>();
+ for (FlowRule ruleToRemove : rulesToRemove) {
+ // IP SA Filtering can only apply to Port 0 optics
+ if (ruleToRemove.selector().getCriterion(Type.IPV4_SRC) != null &&
+ ruleToRemove.selector().getCriterion(Type.IN_PORT) != null &&
+ ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) {
+ SourceAddressRange sar = new DefaultSourceAddressRange();
+ sar.rangeId((short) ruleToRemove.tableId());
+ acvtiveFiltRanges.remove(Short.valueOf((short) ruleToRemove.tableId()));
+ rulesRemoved.add(ruleToRemove);
+ saRangeList.add(sar);
+
+ } else if (ruleToRemove.selector().getCriterion(Type.VLAN_VID) != null &&
+ ruleToRemove.selector().getCriterion(Type.IN_PORT) != null) {
+ PortNumber portNumber = ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port();
+ VlanId vlanId = ((VlanIdCriterion) ruleToRemove.selector().getCriterion(Type.VLAN_VID)).vlanId();
+ int evcId = ruleToRemove.tableId();
+ int evcKey = (evcId << 2) + (int) portNumber.toLong();
+ String activeCeVlanMap = "";
+ //If this is one of many VLANs belonging to an EVC then we should only remove this VLAN
+ // from the ceVlanMap and not the whole EVC
+ if (!ceVlanMapMap.containsKey(evcKey)) {
+ for (Evc activeEvc:activeEvcs) {
+ if (activeEvc.evcIndex() == evcId) {
+ if (Ea1000Port.fromNum(portNumber.toLong()).nOrC(portAssignment) ==
+ UniSide.CUSTOMER) {
+ activeCeVlanMap = activeEvc.evcPerUni().evcPerUnic().ceVlanMap().string();
+ } else if (Ea1000Port.fromNum(portNumber.toLong()).nOrC(portAssignment) ==
+ UniSide.NETWORK) {
+ activeCeVlanMap = activeEvc.evcPerUni().evcPerUnin().ceVlanMap().string();
+ }
+ }
+ }
+ }
+
+ ceVlanMapMap.put(evcKey, CeVlanMapUtils.removeFromCeVlanMap(activeCeVlanMap, vlanId.id()));
+ if (!flowIdMap.containsKey(evcKey)) {
+ flowIdMap.put(evcKey, new ArrayList<>());
+ }
+ flowIdMap.get(evcKey).add(vlanId.id());
+ rulesRemoved.add(ruleToRemove);
+
+ } else {
+ log.info("Unexpected Flow Rule type removal: " + ruleToRemove);
+ }
+ }
+
+ //If there are IPv4 Flow Rules created commit them now through the
+ //MseaSaFiltering service
+ if (saRangeList.size() > 0 && acvtiveFiltRanges.size() == 0) {
+ try {
+ SourceIpaddressFiltering saFilter =
+ new DefaultSourceIpaddressFiltering();
+ MseaSaFilteringOpParam mseaSaFiltering = new MseaSaFilteringOpParam();
+ mseaSaFiltering.sourceIpaddressFiltering(saFilter);
+
+ mseaSaFilteringService.deleteMseaSaFilteringRange(
+ mseaSaFiltering, session, DatastoreId.RUNNING);
+ } catch (NetconfException e) {
+ log.warn("Remove FlowRule on MseaSaFilteringService could not delete all SARules - "
+ + "they may already have been deleted: " + e.getMessage());
+ }
+ } else if (saRangeList.size() > 0) {
+ try {
+ mseaSaFilteringService.deleteMseaSaFilteringRange(
+ buildSaFilteringObject(saRangeList), session, DatastoreId.RUNNING);
+ } catch (NetconfException e) {
+ log.warn("Remove FlowRule on MseaSaFilteringService could not delete SARule - "
+ + "it may already have been deleted: " + e.getMessage());
+ }
+ }
+
+ if (ceVlanMapMap.size() > 0) {
+ try {
+ mseaUniEvcServiceSvc.removeEvcUniFlowEntries(ceVlanMapMap, flowIdMap,
+ session, DatastoreId.RUNNING, portAssignment);
+ } catch (NetconfException e) {
+ log.warn("Remove FlowRule on MseaUniEvcService could not delete EVC - "
+ + "it may already have been deleted: " + e.getMessage());
+ }
+ }
+
+ sessionMutex.release();
+ return rulesRemoved;
+ }
+
+ /**
+ * An internal method for extracting one EVC from a list and returning its ceVlanMap.
+ *
+ * @param evcList - the list of known EVCs
+ * @param evcIndex - the index of the EVC we're looking for
+ * @param side - the side of the UNI
+ * @return - the CEVlanMap we're looking for
+ */
+ private String getCeVlanMapForIdxFromEvcList(List<Evc> evcList, long evcIndex, UniSide side) {
+ if (evcList != null && evcList.size() > 0) {
+ for (Evc evc:evcList) {
+ if (evc.evcIndex() == evcIndex && evc.evcPerUni() != null) {
+ if (side == UniSide.CUSTOMER &&
+ evc.evcPerUni().evcPerUnic() != null &&
+ evc.evcPerUni().evcPerUnic().ceVlanMap() != null) {
+ return evc.evcPerUni().evcPerUnic().ceVlanMap().string();
+ } else if (side == UniSide.NETWORK &&
+ evc.evcPerUni().evcPerUnin() != null &&
+ evc.evcPerUni().evcPerUnin().ceVlanMap() != null) {
+ return evc.evcPerUni().evcPerUnin().ceVlanMap().string();
+ }
+ }
+ }
+ }
+
+ return ""; //The EVC required was not in the list
+ }
+
+ /**
+ * An internal method to convert from a FlowRule to SARange.
+ *
+ * @param frList A collection of flow rules
+ * @param saRangeList A list of SARanges
+ * @param fr A flow rule
+ */
+ private void parseFrForSaRange(Collection<FlowRule> frList, List<SourceAddressRange> saRangeList, FlowRule fr) {
+ String ipAddrStr = fr.selector().getCriterion(Type.IPV4_SRC).toString().substring(9);
+ log.debug("Applying IP address to " + ipAddrStr
+ + " (on Port 0) to IP SA Filtering on EA1000 through NETCONF");
+
+ SourceAddressRange sar =
+ new DefaultSourceAddressRange();
+
+ sar.rangeId((short) fr.tableId());
+ sar.name("Flow:" + fr.id().toString());
+ sar.ipv4AddressPrefix(ipAddrStr);
+
+ frList.add(fr);
+ saRangeList.add(sar);
+ }
+
+ private void parseFrForEvcs(Collection<FlowRule> frList, Map<Integer, Evc> evcMap,
+ List<Evc> activeEvcs, UniSideInterfaceAssignmentEnum portAssignment, FlowRule fr) {
+ //There could be many Flow Rules for one EVC depending on the ceVlanMap
+ //Cannot build up the EVC until we know the details - the key is the tableID and port
+ Ea1000Port port = Ea1000Port.fromNum(
+ ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong());
+ Integer evcKey = (fr.tableId() << 2) + port.portNum();
+ VlanId sourceVid = ((VlanIdCriterion) fr.selector().getCriterion(Type.VLAN_VID)).vlanId();
+ FlowMapping fm = new DefaultFlowMapping();
+ fm.ceVlanId(VlanIdType.of(sourceVid.id()));
+ fm.flowId(BigInteger.valueOf(fr.id().value()));
+
+ if (evcMap.containsKey(evcKey)) { //Is there an entry already for this EVC and port?
+ //Replace ceVlanMap
+ if (port.nOrC(portAssignment) == UniSide.CUSTOMER) {
+ evcMap.get(evcKey).evcPerUni().evcPerUnic().addToFlowMapping(fm);
+ ServiceListType newCeVlanMap = new ServiceListType(
+ CeVlanMapUtils.addtoCeVlanMap(
+ evcMap.get(evcKey).evcPerUni().evcPerUnic().ceVlanMap().toString(),
+ sourceVid.toShort()));
+ evcMap.get(evcKey).evcPerUni().evcPerUnic().ceVlanMap(newCeVlanMap);
+ } else {
+ evcMap.get(evcKey).evcPerUni().evcPerUnin().addToFlowMapping(fm);
+ ServiceListType newCeVlanMap = new ServiceListType(
+ CeVlanMapUtils.addtoCeVlanMap(
+ evcMap.get(evcKey).evcPerUni().evcPerUnin().ceVlanMap().toString(),
+ sourceVid.toShort()));
+ evcMap.get(evcKey).evcPerUni().evcPerUnin().ceVlanMap(newCeVlanMap);
+ }
+ } else if (evcMap.containsKey((evcKey ^ 1))) { //Is there an entry for this EVC but the opposite port?
+ TagManipulation tm = getTagManipulation(fr);
+ if (port.nOrC(portAssignment) == UniSide.NETWORK) {
+ ServiceListType newCeVlanMap = new ServiceListType(
+ CeVlanMapUtils.addtoCeVlanMap(
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ceVlanMap().toString(),
+ sourceVid.toShort()));
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ceVlanMap(newCeVlanMap);
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().tagManipulation(tm);
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().addToFlowMapping(fm);
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ingressBwpGroupIndex(getMeterId(fr.treatment()));
+ } else {
+ ServiceListType newCeVlanMap = new ServiceListType(
+ CeVlanMapUtils.addtoCeVlanMap(
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ceVlanMap().toString(),
+ sourceVid.toShort()));
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ceVlanMap(newCeVlanMap);
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().tagManipulation(tm);
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().addToFlowMapping(fm);
+ evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ingressBwpGroupIndex(getMeterId(fr.treatment()));
+ }
+ } else {
+ Evc evc = new DefaultEvc();
+ EvcPerUnin epun = new CustomEvcPerUnin();
+ EvcPerUnic epuc = new CustomEvcPerUnic();
+ TagManipulation tm = getTagManipulation(fr);
+
+ UniSide side = port.nOrC(portAssignment);
+ String oldCeVlanMap = getCeVlanMapForIdxFromEvcList(activeEvcs, fr.tableId(), side);
+ String newCeVlanMap =
+ CeVlanMapUtils.addtoCeVlanMap(oldCeVlanMap, sourceVid.id());
+ String oppositeCeVlanMap =
+ getCeVlanMapForIdxFromEvcList(activeEvcs, fr.tableId(),
+ port.opposite().nOrC(portAssignment));
+ oppositeCeVlanMap = oppositeCeVlanMap.isEmpty() ? "0" : oppositeCeVlanMap;
+ if (side == UniSide.NETWORK) {
+ epun.ceVlanMap(new ServiceListType(newCeVlanMap));
+ epun.tagManipulation(tm);
+ epun.addToFlowMapping(fm);
+ epun.ingressBwpGroupIndex(getMeterId(fr.treatment()));
+
+ epuc.ceVlanMap(new ServiceListType(oppositeCeVlanMap));
+ epuc.ingressBwpGroupIndex(new Long(0));
+ } else {
+ epuc.ceVlanMap(new ServiceListType(newCeVlanMap));
+ epuc.tagManipulation(tm);
+ epuc.addToFlowMapping(fm);
+ epuc.ingressBwpGroupIndex(getMeterId(fr.treatment()));
+
+ epun.ceVlanMap(new ServiceListType(oppositeCeVlanMap));
+ epun.ingressBwpGroupIndex(new Long(0));
+ }
+
+ evc.evcIndex(fr.tableId());
+ evc.name(new Identifier45("EVC-" + String.valueOf(fr.tableId())));
+
+ DefaultEvcPerUni epu = new DefaultEvcPerUni();
+ epu.evcPerUnin(epun);
+ epu.evcPerUnic(epuc);
+ evc.evcPerUni(epu);
+
+ evcMap.put(evcKey, evc);
+ }
+
+ frList.add(fr);
+ }
+
+
+ private MseaSaFilteringOpParam buildSaFilteringObject(List<SourceAddressRange> saRangeList) {
+ InterfaceEth0 saIf = new DefaultInterfaceEth0();
+ for (SourceAddressRange sa:saRangeList) {
+ saIf.addToSourceAddressRange(sa);
+ }
+ saIf.filterAdminState(FilterAdminStateEnum.BLACKLIST);
+
+ SourceIpaddressFiltering saFilter =
+ new DefaultSourceIpaddressFiltering();
+ saFilter.interfaceEth0(saIf);
+
+ MseaSaFilteringOpParam mseaSaFiltering = new MseaSaFilteringOpParam();
+ mseaSaFiltering.sourceIpaddressFiltering(saFilter);
+
+ return mseaSaFiltering;
+ }
+
+ private Collection<FlowEntry> convertSaFilteringToFlowRules(
+ MseaSaFiltering saFilteringCurrent, ApplicationId appId) {
+ Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
+
+ List<SourceAddressRange> saRangelist =
+ saFilteringCurrent.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
+ Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0));
+ TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();
+
+ if (saRangelist != null) {
+ for (SourceAddressRange sa : saRangelist) {
+ Criterion matchIpSrc = Criteria.matchIPSrc(IpPrefix.valueOf(sa.ipv4AddressPrefix()));
+
+ TrafficSelector selector = tsBuilder.add(matchIpSrc).add(matchInPort).build();
+
+ TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder();
+ TrafficTreatment treatment = trBuilder.drop().build();
+
+ FlowRule.Builder feBuilder = new DefaultFlowRule.Builder();
+ if (sa.name() != null && sa.name().startsWith("Flow:")) {
+ String[] nameParts = sa.name().split(":");
+ Long cookie = Long.valueOf(nameParts[1], 16);
+ feBuilder = feBuilder.withCookie(cookie);
+ } else {
+ feBuilder = feBuilder.fromApp(appId);
+ }
+
+ FlowRule fr = feBuilder
+ .forDevice(handler().data().deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .forTable(sa.rangeId())
+ .makePermanent()
+ .withPriority(PRIORITY_DEFAULT)
+ .build();
+
+ flowEntryCollection.add(
+ new DefaultFlowEntry(fr, FlowEntryState.ADDED, 0, 0, 0));
+ }
+ }
+ return flowEntryCollection;
+ }
+
+
+ private Collection<FlowEntry> convertEvcUniToFlowRules(
+ MseaUniEvcService uniEvcCurrent, UniSideInterfaceAssignmentEnum portAssignment) {
+ Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
+
+ if (uniEvcCurrent == null || uniEvcCurrent.mefServices() == null ||
+ uniEvcCurrent.mefServices().uni() == null || uniEvcCurrent.mefServices().uni().evc() == null) {
+ log.info("No EVC's found when getting flow rules");
+ return flowEntryCollection;
+ }
+
+ for (Evc evc:uniEvcCurrent.mefServices().uni().evc()) {
+ FlowRule.Builder frBuilder = new DefaultFlowRule.Builder();
+ TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();
+
+ TrafficTreatment uniNTreatment = treatmentForUniSde(evc.evcPerUni(), true);
+ //Depending on the ceVlanMap there may be multiple VLans and hence multiple flow entries
+ Short[] vlanIdsUniN =
+ CeVlanMapUtils.getVlanSet(ceVlanMapForUniSide(evc.evcPerUni(), true));
+ for (Short vlanId:vlanIdsUniN) {
+ if (vlanId == 0) {
+ continue;
+ }
+ Criterion uniNportCriterion = criterionPortForUniSide(portAssignment, true);
+ TrafficSelector tsUniN = tsBuilder.matchVlanId(VlanId.vlanId(vlanId)).add(uniNportCriterion).build();
+ long flowId = getFlowIdForVlan(evc.evcPerUni().evcPerUnin().flowMapping(), vlanId);
+
+ FlowRule frUniN = frBuilder
+ .forDevice(handler().data().deviceId())
+ .withSelector(tsUniN)
+ .withTreatment(uniNTreatment)
+ .forTable(new Long(evc.evcIndex()).intValue()) //narrowing to int
+ .makePermanent()
+ .withPriority(PRIORITY_DEFAULT)
+ .withCookie(flowId)
+ .build();
+ flowEntryCollection.add(new DefaultFlowEntry(frUniN, FlowEntryState.ADDED, 0, 0, 0));
+ }
+
+ TrafficTreatment uniCTreatment = treatmentForUniSde(evc.evcPerUni(), false);
+ //Depending on the ceVlanMap there may be multiple VLans and hence multiple flow entries
+ Short[] vlanIdsUniC =
+ CeVlanMapUtils.getVlanSet(ceVlanMapForUniSide(evc.evcPerUni(), false));
+ if (vlanIdsUniC != null && vlanIdsUniC.length > 0) {
+ for (Short vlanId:vlanIdsUniC) {
+ if (vlanId == 0) {
+ continue;
+ }
+ Criterion uniCportCriterion = criterionPortForUniSide(portAssignment, false);
+ TrafficSelector tsUniC =
+ tsBuilder.matchVlanId(VlanId.vlanId(vlanId)).add(uniCportCriterion).build();
+ long flowId = getFlowIdForVlan(evc.evcPerUni().evcPerUnic().flowMapping(), vlanId);
+
+ FlowRule frUniC = frBuilder
+ .forDevice(handler().data().deviceId())
+ .withSelector(tsUniC)
+ .withTreatment(uniCTreatment)
+ .forTable(new Long(evc.evcIndex()).intValue()) //narrowing to int
+ .makePermanent()
+ .withPriority(PRIORITY_DEFAULT)
+ .withCookie(flowId)
+ .build();
+ flowEntryCollection.add(new DefaultFlowEntry(frUniC, FlowEntryState.ADDED, 0, 0, 0));
+ }
+ }
+ }
+
+ return flowEntryCollection;
+ }
+
+ private long getFlowIdForVlan(List<FlowMapping> fmList, Short vlanId) {
+ if (fmList == null || vlanId == null) {
+ log.warn("Flow Mapping list is null when reading EVCs");
+ return -1L;
+ }
+ for (FlowMapping fm:fmList) {
+ if (fm.ceVlanId().uint16() == vlanId.intValue()) {
+ return fm.flowId().longValue();
+ }
+ }
+ return 0L;
+ }
+
+ private String ceVlanMapForUniSide(
+ EvcPerUni evcPerUni, boolean portN) {
+ if (portN) {
+ return evcPerUni.evcPerUnin().ceVlanMap().string();
+ } else {
+ return evcPerUni.evcPerUnic().ceVlanMap().string();
+ }
+ }
+
+ private Criterion criterionPortForUniSide(
+ UniSideInterfaceAssignmentEnum portAssignment, boolean portN) {
+ boolean cOnOptics = (portAssignment == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS);
+ int portNum = ((cOnOptics && portN) || (!cOnOptics && !portN)) ? 1 : 0;
+ return Criteria.matchInPort(PortNumber.portNumber(portNum));
+ }
+
+ private TrafficTreatment treatmentForUniSde(
+ EvcPerUni evcPerUni, boolean portN) {
+ TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder();
+
+ TagManipulation tm = null;
+ short meterId = 0;
+ if (portN) {
+ tm = evcPerUni.evcPerUnin().tagManipulation();
+ meterId = (short) evcPerUni.evcPerUnin().ingressBwpGroupIndex();
+ } else {
+ tm = evcPerUni.evcPerUnic().tagManipulation();
+ meterId = (short) evcPerUni.evcPerUnic().ingressBwpGroupIndex();
+ }
+
+ if (meterId > 0L) {
+ trBuilder = trBuilder.meter(MeterId.meterId((long) meterId));
+// trBuilder = trBuilder.meter(MeterId.meterId(meterId)).transition(0);
+ }
+
+ if (tm == null) {
+ return trBuilder.build(); //no tag manipulation found
+ }
+
+ if (tm.getClass().equals(DefaultTagPush.class)) {
+ VlanId pushVlanNum = VlanId.vlanId((short) ((TagPush) tm).tagPush().outerTagVlan().uint16());
+ PushTagTypeEnum pushTagType = ((TagPush) tm).tagPush().pushTagType();
+ //Note - the order of elements below MUST match the order of the Treatment in the stored FlowRule
+ // to be an exactMatch. See DefaultFlowRule.exactMatch()
+ trBuilder = trBuilder
+ .pushVlan(pushTagType.equals(PushTagTypeEnum.PUSHCTAG) ?
+ EtherType.VLAN.ethType() : EtherType.QINQ.ethType())
+ .setVlanId(pushVlanNum).transition(Integer.valueOf(0));
+
+ } else if (tm.getClass().equals(DefaultTagPop.class)) {
+ trBuilder = trBuilder.popVlan();
+
+ } else if (tm.getClass().equals(DefaultTagOverwrite.class)) {
+ TagOverwrite to = (TagOverwrite) tm;
+ VlanId ovrVlanNum = VlanId
+ .vlanId((short) (
+ //There are 2 classes TagOverwrite - the other one is already imported
+ to
+ .tagOverwrite()
+ .outerTagVlan()
+ .uint16()));
+ trBuilder = trBuilder.setVlanId(ovrVlanNum);
+
+ }
+
+ return trBuilder.build();
+ }
+
+ private static TagManipulation getTagManipulation(FlowRule fr) {
+ boolean isPop = false;
+ boolean isPush = false;
+ VlanId vlanId = null;
+ EthType ethType = EtherType.VLAN.ethType(); //Default
+ for (Instruction inst:fr.treatment().allInstructions()) {
+ if (inst.type() == Instruction.Type.L2MODIFICATION) {
+ L2ModificationInstruction l2Mod = (L2ModificationInstruction) inst;
+ if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) {
+ isPop = true;
+ } else if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
+ isPush = true;
+ ethType = ((ModVlanHeaderInstruction) l2Mod).ethernetType();
+ } else if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_ID) {
+ vlanId = ((ModVlanIdInstruction) l2Mod).vlanId();
+ }
+ }
+ }
+
+ if (isPop) {
+ //The should be no vlanId in this case
+ TagPop pop = new DefaultTagPop();
+ org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
+ .evcperuniextensionattributes.tagmanipulation
+ .tagpop.TagPop popInner =
+ new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
+ .mseaunievcservice.evcperuniextensionattributes
+ .tagmanipulation.tagpop.DefaultTagPop();
+ pop.tagPop(popInner);
+ return pop;
+
+ } else if (isPush && vlanId != null) {
+ TagPush push = new DefaultTagPush();
+ org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
+ .evcperuniextensionattributes.tagmanipulation
+ .tagpush.TagPush pushInner =
+ new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
+ .mseaunievcservice.evcperuniextensionattributes
+ .tagmanipulation.tagpush.DefaultTagPush();
+ pushInner.outerTagVlan(new VlanIdType(vlanId.id()));
+ pushInner.pushTagType(ethType.equals(EtherType.VLAN.ethType()) ?
+ PushTagTypeEnum.PUSHCTAG : PushTagTypeEnum.PUSHSTAG);
+ push.tagPush(pushInner);
+ return push;
+
+ } else if (vlanId != null) { //This is overwrite, as it has vlanId, but not push or pop
+ TagOverwrite ovr = new DefaultTagOverwrite();
+ org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
+ .evcperuniextensionattributes.tagmanipulation
+ .tagoverwrite.TagOverwrite ovrInner =
+ new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
+ .mseaunievcservice.evcperuniextensionattributes
+ .tagmanipulation.tagoverwrite.DefaultTagOverwrite();
+ ovrInner.outerTagVlan(new VlanIdType(vlanId.id()));
+ ovr.tagOverwrite(ovrInner);
+ return ovr;
+ }
+
+ return null;
+ }
+
+ private static long getMeterId(TrafficTreatment treatment) {
+ return (treatment.metered() != null && treatment.metered().meterId() != null)
+ ? treatment.metered().meterId().id() : 0L;
+ }
+
+ /**
+ * An enumerated type that characterises the 2 port layout of the EA1000 device.
+ * The device is in an SFP package and has only 2 ports, the HOST port which
+ * plugs in to the chassis (Port 1) and the Optics Port on the rear (Port 0).
+ */
+ public enum Ea1000Port {
+ HOST(1),
+ OPTICS(0);
+
+ private int num = 0;
+ private Ea1000Port(int num) {
+ this.num = num;
+ }
+
+ /**
+ * The numerical assignment of this port.
+ * @return The port number
+ */
+ public int portNum() {
+ return num;
+ }
+
+ /**
+ * Return the enumerated value from a port number.
+ * @param num The port number
+ * @return An enumerated value
+ */
+ public static Ea1000Port fromNum(long num) {
+ for (Ea1000Port a:Ea1000Port.values()) {
+ if (a.num == num) {
+ return a;
+ }
+ }
+ return HOST;
+ }
+
+ /**
+ * Get the port that the UNI-N is present on.
+ * @param side The assignment of UNI-side to port
+ * @return An enumerated value
+ */
+ public static Ea1000Port uniNNum(UniSideInterfaceAssignmentEnum side) {
+ if (side.equals(UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST)) {
+ return OPTICS;
+ } else {
+ return HOST;
+ }
+ }
+
+ /**
+ * Get the port that the UNI-C is present on.
+ * @param side The assignment of UNI-side to port
+ * @return An enumerated value
+ */
+ public static Ea1000Port uniCNum(UniSideInterfaceAssignmentEnum side) {
+ if (side.equals(UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST)) {
+ return HOST;
+ } else {
+ return OPTICS;
+ }
+ }
+
+ /**
+ * Get the port opposite the current port.
+ * @return An enumerated value for the opposite side
+ */
+ public Ea1000Port opposite() {
+ if (this.equals(HOST)) {
+ return OPTICS;
+ } else {
+ return HOST;
+ }
+ }
+
+ /**
+ * Evaluate which side of the UNI on the EA1000 device this port refers to.
+ * @param side The assignment of UNI-side to port
+ * @return An enumerated value representing the UniSide
+ */
+ public UniSide nOrC(UniSideInterfaceAssignmentEnum side) {
+ if ((this == HOST && side == UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST) ||
+ (this == OPTICS && side == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS)) {
+ return UniSide.CUSTOMER;
+ } else {
+ return UniSide.NETWORK;
+ }
+ }
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java
new file mode 100644
index 0000000..226ad2f
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000MeterProvider.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi;
+
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.CoreService;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.Meter.Unit;
+import org.onosproject.net.meter.MeterOperation;
+import org.onosproject.net.meter.MeterOperations;
+import org.onosproject.net.meter.MeterProvider;
+import org.onosproject.net.meter.MeterProviderRegistry;
+import org.onosproject.net.meter.MeterProviderService;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.CosColorType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.coscolortype.CosColorTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.Cos;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultCos;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.Bwp;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.DefaultBwp;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.DefaultEvcCosTypeEvcColorId;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.EvcCosTypeEvcColorId;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.DefaultEvcCosTypeAll8PrioTo1EvcColor;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.EvcCosTypeAll8PrioTo1EvcColor;
+import org.slf4j.Logger;
+
+/**
+ * Provider which uses an NETCONF controller to handle meters.
+ *
+ * TODO: move this to an architecture similar to FlowRuleDriverProvider in order
+ * to use a behavior to discover meters.
+ */
+@Component(immediate = true, enabled = true)
+public class EA1000MeterProvider extends AbstractProvider implements MeterProvider {
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetconfController controller;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MeterProviderRegistry providerRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc;
+
+ private MeterProviderService providerService;
+
+ private static final int COS_INDEX_1 = 1;
+ private static final short DEFAULT_OUTGOING_PRIO = 3;
+
+ /**
+ * Creates a OpenFlow meter provider.
+ */
+ public EA1000MeterProvider() {
+ super(new ProviderId("netconf", "org.onosproject.provider.meter.microsemi"));
+ }
+
+ @Activate
+ public void activate() {
+ providerService = providerRegistry.register(this);
+
+ }
+
+ @Deactivate
+ public void deactivate() {
+ providerRegistry.unregister(this);
+
+ providerService = null;
+ }
+
+ @Override
+ public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) {
+ log.debug("Adding meterOps to Microsemi Meter Store");
+ }
+
+ @Override
+ public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) {
+ if (meterOp == null || deviceId == null) {
+ log.warn("Missing argument for performMeterOperation()");
+ return;
+ }
+ log.debug("{} meterOp {} to Microsemi Meter Store", meterOp.type(), meterOp);
+
+ long meterId = meterOp.meter().id().id();
+ String deviceName = deviceId.uri().getSchemeSpecificPart();
+ Unit unit = meterOp.meter().unit();
+
+ Profiles profiles = new DefaultProfiles();
+ if (meterOp.type() == MeterOperation.Type.ADD || meterOp.type() == MeterOperation.Type.MODIFY) {
+ Bwp bwp = new DefaultBwp();
+ bwp.cosIndex(COS_INDEX_1);
+ bwp.name("BWP-" + String.valueOf(meterId) + "-" + deviceName);
+
+ long cirRateKbps = 0L;
+ long cbsRateKbps = 0L;
+ long eirRateKbps = 0L;
+ long ebsRateKbps = 0L;
+ for (Band band:meterOp.meter().bands()) {
+ if (band.type() == Band.Type.REMARK) {
+ //This relates to CIR/CBS
+ cirRateKbps = toBitsPerSec(band.rate(), unit);
+ cbsRateKbps = band.burst(); //Already in kbps
+ } else if (band.type() == Band.Type.DROP) {
+ //This relates to EIR/EBS
+ eirRateKbps = toBitsPerSec(band.rate(), unit);
+ ebsRateKbps = band.burst(); //Already in kbps
+ }
+ }
+ bwp.committedInformationRate(cirRateKbps);
+ bwp.excessInformationRate(eirRateKbps - cirRateKbps);
+ if (meterOp.meter().isBurst()) {
+ bwp.committedBurstSize(cbsRateKbps);
+ bwp.excessBurstSize(ebsRateKbps - cbsRateKbps);
+ }
+
+ BwpGroup bwpg = new DefaultBwpGroup();
+ bwpg.groupIndex((short) meterId);
+ bwpg.addToBwp(bwp);
+
+ //Create cos-1 as referenced above - we only support 1 at the moment
+ Cos cos = new DefaultCos();
+ cos.cosIndex(COS_INDEX_1);
+ cos.name("COS-1");
+ cos.outgoingCosValue(PriorityType.of(DEFAULT_OUTGOING_PRIO));
+ cos.colorAware(true);
+ cos.colorForward(true);
+
+ EvcCosTypeAll8PrioTo1EvcColor ect =
+ new DefaultEvcCosTypeAll8PrioTo1EvcColor();
+ ect.evcAll8ColorTo(CosColorType.of(CosColorTypeEnum.GREEN));
+ profiles.addToBwpGroup(bwpg);
+
+ EvcCosTypeEvcColorId cid = new DefaultEvcCosTypeEvcColorId();
+ cid.evcCosTypeAll8PrioTo1EvcColor(ect);
+ cos.cosTypeChoice(cid);
+ profiles.addToCos(cos);
+ } else if (meterOp.type() == MeterOperation.Type.REMOVE) {
+ BwpGroup bwpg = new DefaultBwpGroup();
+ bwpg.groupIndex((short) meterId);
+
+ profiles.addToBwpGroup(bwpg);
+ }
+
+ MefServices mefServices = new DefaultMefServices();
+ mefServices.profiles(profiles);
+
+ MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
+ mseaUniEvcServiceFilter.mefServices(mefServices);
+
+ NetconfSession session = controller.getDevicesMap().get(deviceId).getSession();
+ try {
+ if (meterOp.type() == MeterOperation.Type.REMOVE) {
+ mseaUniEvcServiceSvc.deleteMseaUniEvcService(mseaUniEvcServiceFilter,
+ session, DatastoreId.RUNNING);
+ } else {
+ mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter,
+ session, DatastoreId.RUNNING);
+ }
+ } catch (NetconfException e) {
+ //This can fail if the BWP Group is deleted before the EVC that is dependent on it
+ //The delete of the EVC will be called on a separate thread to that should proceed
+ //within a few seconds after which we should try again
+ AtomicInteger retry = new AtomicInteger(4);
+ if (meterOp.type() == MeterOperation.Type.REMOVE &&
+ e.getMessage().startsWith("Failed to run edit-config through NETCONF")) {
+ while (retry.getAndDecrement() > 0) {
+ try {
+ Thread.sleep(1000L);
+ log.debug("Retrying deletion of Bandwith Profile Group {}",
+ String.valueOf(meterId));
+ mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter,
+ session, DatastoreId.RUNNING);
+ return; //If it did not throw an exception
+ } catch (InterruptedException e1) {
+ log.debug("Error when deleting BWP profile on EA1000" +
+ " - trying again in 1 sec", e1);
+ } catch (NetconfException e1) {
+ log.debug("NETCONF failed to delete profile - trying again in 1 sec", e1);
+ }
+ }
+ log.error("Error deleting BWPGroup {} from {} after 4 tries: {}",
+ meterId, deviceId, e.getMessage());
+ } else {
+ log.error("Error adding BWPGroup {} from {}: {}",
+ meterId, deviceId, e.getMessage());
+ throw new UnsupportedOperationException(e);
+ }
+ }
+ }
+
+ private static long toBitsPerSec(long rate, Unit unit) {
+ if (unit == Unit.KB_PER_SEC) {
+ return rate * 8;
+ } else {
+ return -1;
+ }
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java
new file mode 100644
index 0000000..308bdff
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000Pipeliner.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.drivers.microsemi.EA1000FlowRuleProgrammable.Ea1000Port;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.NextGroup;
+import org.onosproject.net.behaviour.Pipeliner;
+import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.slf4j.Logger;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
+import com.google.common.cache.RemovalNotification;
+
+/**
+ * Support for FlowObjectives in the EA1000.
+ *
+ * Used with the CarrierEthernet App
+ *
+ */
+public class EA1000Pipeliner extends AbstractHandlerBehaviour implements Pipeliner {
+
+ protected final Logger log = getLogger(getClass());
+ protected ServiceDirectory serviceDirectory;
+ protected FlowRuleService flowRuleService;
+ protected DeviceId deviceId;
+ protected Cache<Integer, NextObjective> pendingNext;
+ protected Integer evcIdBase = 1;
+
+ @Override
+ public void init(DeviceId deviceId, PipelinerContext context) {
+ this.serviceDirectory = context.directory();
+ this.deviceId = deviceId;
+
+ flowRuleService = serviceDirectory.get(FlowRuleService.class);
+
+ pendingNext = CacheBuilder.newBuilder()
+ .expireAfterWrite(20, TimeUnit.SECONDS)
+ .removalListener((RemovalNotification<Integer, NextObjective> notification) -> {
+ if (notification.getCause() == RemovalCause.EXPIRED) {
+ notification.getValue().context()
+ .ifPresent(c -> c.onError(notification.getValue(),
+ ObjectiveError.FLOWINSTALLATIONFAILED));
+ }
+ }).build();
+
+ log.debug("Loaded handler behaviour EA1000Pipeliner for " + handler().data().deviceId().uri());
+ }
+
+ @Override
+ public void filter(FilteringObjective filterObjective) {
+ TrafficTreatment.Builder actions;
+ boolean oppositePort = false;
+ int evcId = -1;
+ switch (filterObjective.type()) {
+ case PERMIT:
+ if (filterObjective.meta() == null) {
+ actions = DefaultTrafficTreatment.builder().add(Instructions.popVlan());
+ } else {
+ oppositePort = true; //Experimental - push happens on the opposite port
+ actions = DefaultTrafficTreatment.builder(filterObjective.meta());
+ if (filterObjective.meta().metered() != null) {
+ actions.meter(filterObjective.meta().metered().meterId());
+ }
+ actions.transition(0);
+ boolean isPush = false;
+ int vid = 0;
+ for (Instruction inst:filterObjective.meta().immediate()) {
+ if (inst.type() == Instruction.Type.L2MODIFICATION) {
+ L2ModificationInstruction l2mod = (L2ModificationInstruction) inst;
+ if (l2mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
+ isPush = true;
+ } else if (l2mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_ID) {
+ vid = ((ModVlanIdInstruction) l2mod).vlanId().id();
+ }
+ }
+ }
+ if (isPush && vid > 0) {
+ evcId = vid;
+ }
+ }
+ break;
+ case DENY:
+ actions = (filterObjective.meta() == null) ?
+ DefaultTrafficTreatment.builder() :
+ DefaultTrafficTreatment.builder(filterObjective.meta());
+ actions.drop();
+ break;
+ default:
+ log.warn("Unknown filter type: {}", filterObjective.type());
+ actions = DefaultTrafficTreatment.builder().drop();
+ }
+
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+
+ for (Criterion c:filterObjective.conditions()) {
+ if (c.type() == Type.VLAN_VID && evcId == -1) {
+ evcId = ((VlanIdCriterion) c).vlanId().id();
+ }
+ selector.add(c);
+ }
+
+ if (filterObjective.key() != null) {
+ if (oppositePort) {
+ //Experimental
+ Ea1000Port port = Ea1000Port.fromNum(((PortCriterion) filterObjective.key()).port().toLong());
+ selector.matchInPort(PortNumber.portNumber(port.opposite().portNum()));
+ } else {
+ selector.add(filterObjective.key());
+ }
+ }
+
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(actions.build())
+ .fromApp(filterObjective.appId())
+ .forTable(evcId)
+ .withPriority(filterObjective.priority());
+
+ if (filterObjective.permanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(filterObjective.timeout());
+ }
+
+ installObjective(ruleBuilder, filterObjective);
+
+ log.debug("filter() of EA1000Pipeliner called for "
+ + handler().data().deviceId().uri()
+ + ". Objective: " + filterObjective);
+ }
+
+ @Override
+ public void forward(ForwardingObjective forwardObjective) {
+ TrafficSelector selector = forwardObjective.selector();
+
+ if (forwardObjective.treatment() != null) {
+ List<Instruction> instructions = forwardObjective.treatment().immediate();
+ if (instructions != null && instructions.size() == 1
+ && instructions.get(0).type() == Instruction.Type.OUTPUT
+ && ((OutputInstruction) instructions.get(0)).port() == PortNumber.CONTROLLER) {
+ Set<Criterion> criteria = forwardObjective.selector().criteria();
+ log.info("EA1000 does not yet implement forwarding to CONTROLLER for flow objective for: "
+ + handler().data().deviceId().uri()
+ + ". "
+ + forwardObjective);
+ return;
+ } else {
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector)
+ .fromApp(forwardObjective.appId())
+ .withPriority(forwardObjective.priority())
+ .withTreatment(forwardObjective.treatment());
+
+ if (forwardObjective.permanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(forwardObjective.timeout());
+ }
+ installObjective(ruleBuilder, forwardObjective);
+ }
+ } else {
+ NextObjective nextObjective = pendingNext.getIfPresent(forwardObjective.nextId());
+ if (nextObjective != null) {
+ pendingNext.invalidate(forwardObjective.nextId());
+ nextObjective.next().forEach(treat -> {
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector)
+ .fromApp(forwardObjective.appId())
+ .withPriority(forwardObjective.priority())
+ .withTreatment(treat);
+
+ if (forwardObjective.permanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(forwardObjective.timeout());
+ }
+ installObjective(ruleBuilder, forwardObjective);
+ });
+ } else {
+ forwardObjective.context().ifPresent(c -> c.onError(forwardObjective,
+ ObjectiveError.GROUPMISSING));
+ }
+ }
+ log.debug("EA1000: Unhandled Forwarding Objective for: "
+ + handler().data().deviceId().uri()
+ + ". "
+ + forwardObjective);
+ }
+
+ @Override
+ public void next(NextObjective nextObjective) {
+ pendingNext.put(nextObjective.id(), nextObjective);
+ nextObjective.context().ifPresent(context -> context.onSuccess(nextObjective));
+
+ log.debug("next() of EA1000Pipeliner called for "
+ + handler().data().deviceId().uri()
+ + ". Objective: " + nextObjective);
+ }
+
+ @Override
+ public List<String> getNextMappings(NextGroup nextGroup) {
+ log.debug("getNextMappings() of EA1000Pipeliner called for "
+ + handler().data().deviceId().uri()
+ + ". Objective: " + nextGroup);
+ return new ArrayList<String>();
+ }
+
+ protected void installObjective(FlowRule.Builder ruleBuilder, Objective objective) {
+ FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
+ switch (objective.op()) {
+
+ case ADD:
+ flowBuilder.add(ruleBuilder.build());
+ break;
+ case REMOVE:
+ flowBuilder.remove(ruleBuilder.build());
+ break;
+ default:
+ log.warn("Unknown operation {}", objective.op());
+ }
+
+ flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ objective.context().ifPresent(context -> context.onSuccess(objective));
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ objective.context()
+ .ifPresent(context -> context.onError(objective, ObjectiveError.FLOWINSTALLATIONFAILED));
+ }
+ }));
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java
new file mode 100644
index 0000000..dfb8480
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/Ea1000DeviceDescription.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onlab.packet.ChassisId;
+import org.onosproject.drivers.microsemi.yang.IetfSystemNetconfService;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DefaultPortDescription;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceDescriptionDiscovery;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfDevice;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.AugmentedSysSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.system.DefaultAugmentedSysSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.AugmentedSysPlatform;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.systemstate.platform.DefaultAugmentedSysPlatform;
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.DateAndTime;
+import org.slf4j.Logger;
+
+public class Ea1000DeviceDescription extends AbstractHandlerBehaviour implements DeviceDescriptionDiscovery {
+
+ private String serialNumber = "unavailable";
+ private String swVersion = "unavailable";
+ private String longitudeStr = null;
+ private String latitudeStr = null;
+ private final Logger log = getLogger(getClass());
+
+ public Ea1000DeviceDescription() {
+ log.info("Loaded handler behaviour Ea1000DeviceDescription.");
+ }
+
+ @Override
+ public DeviceDescription discoverDeviceDetails() {
+ log.info("Adding description for EA1000 device");
+
+ NetconfController controller = checkNotNull(handler().get(NetconfController.class));
+ NetconfDevice ncDevice = controller.getDevicesMap().get(handler().data().deviceId());
+ if (ncDevice == null) {
+ log.error("Internal ONOS Error. Device has been marked as reachable, " +
+ "but deviceID {} is not in Devices Map. Continuing with empty description",
+ handler().data().deviceId());
+ return null;
+ }
+ NetconfSession session = ncDevice.getSession();
+ IetfSystemNetconfService ietfSystemService =
+ (IetfSystemNetconfService) checkNotNull(handler().get(IetfSystemNetconfService.class));
+
+ try {
+ IetfSystem system = ietfSystemService.getIetfSystemInit(session);
+ if (system != null && system.systemState() != null) {
+ swVersion = system.systemState().platform().osRelease();
+ AugmentedSysPlatform augmentedSysPlatform =
+ (AugmentedSysPlatform) system.systemState()
+ .platform().augmentation(DefaultAugmentedSysPlatform.class);
+ serialNumber = augmentedSysPlatform.deviceIdentification().serialNumber();
+ DateAndTime deviceDateAndTime = system.systemState().clock().currentDatetime();
+ OffsetDateTime odt =
+ OffsetDateTime.parse(deviceDateAndTime.string(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ if (odt.getYear() < OffsetDateTime.now(ZoneId.of("UTC")).getYear()) {
+ OffsetDateTime nowUtc = OffsetDateTime.now(ZoneId.of("UTC"));
+ log.warn("Date on device is in the past: {}. Setting it to {}", odt.toString(), nowUtc);
+ ietfSystemService.setCurrentDatetime(nowUtc, session);
+ }
+ }
+
+ if (system != null && system.system() != null) {
+ AugmentedSysSystem augmentedSystem =
+ (AugmentedSysSystem) system.system().augmentation(DefaultAugmentedSysSystem.class);
+ longitudeStr = augmentedSystem.longitude().toPlainString();
+ latitudeStr = augmentedSystem.latitude().toPlainString();
+ }
+ } catch (NetconfException e) {
+ log.error("Unable to retrieve init data from device: " + handler().data().deviceId().toString()
+ + " Error: " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
+ DeviceId deviceId = handler().data().deviceId();
+ Device device = deviceService.getDevice(deviceId);
+ DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder();
+ if (longitudeStr != null && latitudeStr != null) {
+ annotationsBuilder.set(AnnotationKeys.LONGITUDE, longitudeStr)
+ .set(AnnotationKeys.LATITUDE, latitudeStr).build();
+ } else {
+ log.warn("Longitude and latitude could not be retrieved from device " + deviceId);
+ }
+
+ return new DefaultDeviceDescription(device.id().uri(), Device.Type.OTHER, "Microsemi", "EA1000", swVersion,
+ serialNumber, new ChassisId(), annotationsBuilder.build());
+ }
+
+ @Override
+ public List<PortDescription> discoverPortDetails() {
+
+ List<PortDescription> ports = new ArrayList<PortDescription>();
+
+ DefaultAnnotations annotationOptics = DefaultAnnotations.builder().set(AnnotationKeys.PORT_NAME, "Optics")
+ .build();
+ PortDescription optics = new DefaultPortDescription(PortNumber.portNumber(0), true, Port.Type.FIBER, 1000,
+ annotationOptics);
+ ports.add(optics);
+
+ DefaultAnnotations annotationHost = DefaultAnnotations.builder().set(AnnotationKeys.PORT_NAME, "Host").build();
+ PortDescription host = new DefaultPortDescription(PortNumber.portNumber(1), true, Port.Type.COPPER, 1000,
+ annotationHost);
+ ports.add(host);
+
+ return ports;
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java
new file mode 100644
index 0000000..724792e
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/FullMetersAvailable.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import org.onosproject.net.behaviour.MeterQuery;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+
+/**
+ * Driver which always responds that all Meters are available for the Device.
+ */
+public class FullMetersAvailable extends AbstractHandlerBehaviour implements MeterQuery {
+
+ private static final long MAX_METER = 0x00000FFF;
+
+ @Override
+ public long getMaxMeters() {
+ return MAX_METER;
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java
new file mode 100644
index 0000000..b7f0e68
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/MicrosemiDriversLoader.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+
+/**
+ * Loader for Microsemi device drivers.
+ */
+@Component(immediate = true)
+public class MicrosemiDriversLoader extends AbstractDriverLoader {
+
+ public MicrosemiDriversLoader() {
+ super("/microsemi-drivers.xml");
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java
new file mode 100644
index 0000000..53151bb
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/NetconfConfigGetter.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.io.IOException;
+
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.ConfigGetter;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+import org.onosproject.netconf.NetconfController;
+import org.slf4j.Logger;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Used with the onos:device-configuration CLI command.
+ *
+ * This allows the full configuration to be retrieved from the device
+ */
+public class NetconfConfigGetter extends AbstractHandlerBehaviour implements ConfigGetter {
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PacketService packetService;
+
+ private PacketProcessor testProcessor;
+
+ // FIXME the error string should be universal for all implementations of
+ // ConfigGetter
+ public static final String UNABLE_TO_READ_CONFIG = "config retrieval error";
+
+ @Override
+ public String getConfiguration(String type) {
+ DriverHandler handler = handler();
+ NetconfController controller = handler.get(NetconfController.class);
+
+ DeviceId ofDeviceId = handler.data().deviceId();
+ Preconditions.checkNotNull(controller, "Netconf controller is null");
+ if (type == null ||
+ (!type.equalsIgnoreCase("running")
+ && !type.equalsIgnoreCase("candidate")
+ && !type.equalsIgnoreCase("startup"))) {
+ log.error("Configuration type must be either 'running', 'startup' or 'candidate'. '{}' is invalid", type);
+ return UNABLE_TO_READ_CONFIG;
+ }
+ try {
+ return controller.getDevicesMap().get(ofDeviceId).getSession().getConfig(type.replace("cfgType=", ""));
+ } catch (IOException e) {
+ log.error("Configuration could not be retrieved {}", e.getMessage());
+ }
+ return UNABLE_TO_READ_CONFIG;
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java
new file mode 100644
index 0000000..7589ea7
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/RpcResultParser.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi;
+
+public final class RpcResultParser {
+
+ private RpcResultParser() {
+ //Not called
+ }
+
+ public static String parseXml(final String deviceDescriptionResponse, final String keyWord) {
+
+ int end = deviceDescriptionResponse.lastIndexOf(keyWord);
+ end = deviceDescriptionResponse.lastIndexOf('<', end);
+ int start = deviceDescriptionResponse.lastIndexOf('>', end);
+ if (start > 1 && end > start) {
+ return deviceDescriptionResponse.substring(start + 1, end);
+ } else {
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/package-info.java
new file mode 100644
index 0000000..de883d1
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for Microsemi device drivers.
+ */
+package org.onosproject.drivers.microsemi;
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java
new file mode 100644
index 0000000..44c62f6
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/IetfSystemNetconfService.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import java.time.OffsetDateTime;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.systemrestart.SystemRestartInput;
+
+/**
+ * Extension of ietfSystemService to include NETCONF sessions.
+ *
+ * This is manually extended and should be revised if the ietf-system.yang file changes
+ */
+public interface IetfSystemNetconfService {
+ /**
+ * Returns the attribute ietfSystem.
+ *
+ * @param ietfSystem value of ietfSystem
+ * @param session An active NETCONF session
+ * @return ietfSystem
+ * @throws NetconfException if the session has any error
+ */
+ IetfSystem getIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session) throws NetconfException;
+
+ /**
+ * Returns the result of the init query.
+ *
+ * @param session An active NETCONF session
+ * @return ietfSystem
+ * @throws NetconfException if the session has any error
+ */
+ IetfSystem getIetfSystemInit(NetconfSession session) throws NetconfException;
+
+ /**
+ * Sets the value to attribute ietfSystem.
+ *
+ * @param ietfSystem value of ietfSystem
+ * @param session An active NETCONF session
+ * @param ncDs datastore type running, startup or candidate
+ * @return Boolean to indicate success or failure
+ * @throws NetconfException if the session has any error
+ */
+ boolean setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session,
+ DatastoreId ncDs) throws NetconfException;
+
+ /**
+ * Service interface of setCurrentDatetime.
+ *
+ * @param date input of service interface setCurrentDatetime
+ * @param session An active NETCONF session
+ * @throws NetconfException if the session has any error
+ */
+ void setCurrentDatetime(OffsetDateTime date, NetconfSession session) throws NetconfException;
+
+ /**
+ * Service interface of systemRestart.
+ *
+ * @param inputVar input of service interface systemRestart
+ * @param session An active NETCONF session
+ * @throws NetconfException if the session has any error
+ */
+ void systemRestart(SystemRestartInput inputVar, NetconfSession session) throws NetconfException;
+
+ /**
+ * Service interface of systemShutdown.
+ *
+ * @param session An active NETCONF session
+ * @throws NetconfException if the session has any error
+ */
+ void systemShutdown(NetconfSession session) throws NetconfException;
+
+ /**
+ * Service interface of doUpgradeAndReboot.
+ *
+ * @param inputVar input of service interface doUpgradeAndReboot
+ * @param session An active NETCONF session
+ * @return doUpgradeAndRebootOutput output of service interface doUpgradeAndReboot
+ * @throws NetconfException if the session has any error
+ */
+ DoUpgradeAndRebootOutput doUpgradeAndReboot(DoUpgradeAndRebootInput inputVar, NetconfSession session)
+ throws NetconfException;
+
+ /**
+ * Service interface of pullUpdateTarFromTftp.
+ *
+ * @param inputVar input of service interface pullUpdateTarFromTftp
+ * @param session An active NETCONF session
+ * @throws NetconfException if the session has any error
+ */
+ void pullUpdateTarFromTftp(PullUpdateTarFromTftpInput inputVar, NetconfSession session)
+ throws NetconfException;
+
+ /**
+ * Service interface of readFromSyslog.
+ *
+ * @param inputVar input of service interface readFromSyslog
+ * @param session An active NETCONF session
+ * @return readFromSyslogOutput output of service interface readFromSyslog
+ * @throws NetconfException if the session has any error
+ */
+ ReadFromSyslogOutput readFromSyslog(ReadFromSyslogInput inputVar, NetconfSession session)
+ throws NetconfException;
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java
new file mode 100644
index 0000000..6cf8031
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MicrosemiModelRegistrator.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.yang.AbstractYangModelRegistrator;
+import org.onosproject.yang.gen.v1.entitystatetcmib.rev20051122.EntityStateTcMib;
+import org.onosproject.yang.gen.v1.fpgainternal.rev20151130.FpgaInternal;
+import org.onosproject.yang.gen.v1.ianacrypthash.rev20140806.IanaCryptHash;
+import org.onosproject.yang.gen.v1.ianaiftype.rev20140508.IanaIfType;
+import org.onosproject.yang.gen.v1.ieeetypes.rev20080522.IeeeTypes;
+import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.IetfInetTypes;
+import org.onosproject.yang.gen.v1.ietfinterfaces.rev20140508.IetfInterfaces;
+import org.onosproject.yang.gen.v1.ietfnetconf.rev20110601.IetfNetconf;
+import org.onosproject.yang.gen.v1.ietfnetconfacm.rev20120222.IetfNetconfAcm;
+import org.onosproject.yang.gen.v1.ietfnetconfmonitoring.rev20101004.IetfNetconfMonitoring;
+import org.onosproject.yang.gen.v1.ietfnetconfnotifications.rev20120206.IetfNetconfNotifications;
+import org.onosproject.yang.gen.v1.ietfnetconfwithdefaults.rev20100609.IetfNetconfWithDefaults;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.IetfSystemMicrosemi;
+import org.onosproject.yang.gen.v1.ietfsystemtlsauth.rev20140524.IetfSystemTlsAuth;
+import org.onosproject.yang.gen.v1.ietfx509certtoname.rev20130326.IetfX509CertToName;
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.IetfYangTypes;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.MseaSoamFm;
+import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.MseaSoamPm;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.MseaTypes;
+import org.onosproject.yang.gen.v1.mseaunievcinterface.rev20160317.MseaUniEvcInterface;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.ncnotifications.rev20080714.NcNotifications;
+import org.onosproject.yang.gen.v1.netopeercfgnetopeer.rev20130214.NetopeerCfgnetopeer;
+import org.onosproject.yang.gen.v1.notifications.rev20080714.Notifications;
+import org.onosproject.yang.gen.v1.rfc2544.rev20151020.Rfc2544;
+import org.onosproject.yang.gen.v1.svcactivationtypes.rev20151027.SvcActivationTypes;
+import org.onosproject.yang.gen.v1.y1564.rev20151029.Y1564;
+import org.onosproject.yang.model.DefaultYangModuleId;
+import org.onosproject.yang.model.YangModuleId;
+import org.onosproject.yang.runtime.AppModuleInfo;
+import org.onosproject.yang.runtime.DefaultAppModuleInfo;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Representation of Microsemi model registrator which registers Microsemi device
+ * models.
+ */
+@Component(immediate = true)
+public class MicrosemiModelRegistrator extends AbstractYangModelRegistrator {
+
+ public MicrosemiModelRegistrator() {
+ super(IetfSystem.class, getAppInfo());
+ }
+
+ private static Map<YangModuleId, AppModuleInfo> getAppInfo() {
+ Map<YangModuleId, AppModuleInfo> appInfo = new HashMap<>();
+
+ appInfo.put(new DefaultYangModuleId("fpga-internal", "2015-11-30"),
+ new DefaultAppModuleInfo(FpgaInternal.class, null));
+ appInfo.put(new DefaultYangModuleId("iana-if-type", "2014-05-08"),
+ new DefaultAppModuleInfo(IanaIfType.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-yang-types", "2013-07-15"),
+ new DefaultAppModuleInfo(IetfYangTypes.class, null));
+ appInfo.put(new DefaultYangModuleId("msea-sa-filtering", "2016-04-12"),
+ new DefaultAppModuleInfo(MseaSaFiltering.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-x509-cert-to-name", "2013-03-26"),
+ new DefaultAppModuleInfo(IetfX509CertToName.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-system", "2014-08-06"),
+ new DefaultAppModuleInfo(IetfSystem.class, null));
+ appInfo.put(new DefaultYangModuleId("msea-types", "2016-02-29"),
+ new DefaultAppModuleInfo(MseaTypes.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-inet-types", "2013-07-15"),
+ new DefaultAppModuleInfo(IetfInetTypes.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-netconf-with-defaults", "2010-06-09"),
+ new DefaultAppModuleInfo(IetfNetconfWithDefaults.class, null));
+ appInfo.put(new DefaultYangModuleId("msea-uni-evc-service", "2016-03-17"),
+ new DefaultAppModuleInfo(MseaUniEvcService.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-netconf-monitoring", "2010-10-04"),
+ new DefaultAppModuleInfo(IetfNetconfMonitoring.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-netconf-acm", "2012-02-22"),
+ new DefaultAppModuleInfo(IetfNetconfAcm.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-system-tls-auth", "2014-05-24"),
+ new DefaultAppModuleInfo(IetfSystemTlsAuth.class, null));
+ appInfo.put(new DefaultYangModuleId("rfc-2544", "2015-10-20"),
+ new DefaultAppModuleInfo(Rfc2544.class, null));
+ appInfo.put(new DefaultYangModuleId("msea-cfm", "2016-02-29"),
+ new DefaultAppModuleInfo(MseaCfm.class, null));
+ appInfo.put(new DefaultYangModuleId("netopeer-cfgnetopeer", "2013-02-14"),
+ new DefaultAppModuleInfo(NetopeerCfgnetopeer.class, null));
+ appInfo.put(new DefaultYangModuleId("ENTITY-STATE-TC-MIB", "2005-11-22"),
+ new DefaultAppModuleInfo(EntityStateTcMib.class, null));
+ appInfo.put(new DefaultYangModuleId("msea-soam-fm", "2016-02-29"),
+ new DefaultAppModuleInfo(MseaSoamFm.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-netconf-notifications", "2012-02-06"),
+ new DefaultAppModuleInfo(IetfNetconfNotifications.class, null));
+ appInfo.put(new DefaultYangModuleId("nc-notifications", "2008-07-14"),
+ new DefaultAppModuleInfo(NcNotifications.class, null));
+ appInfo.put(new DefaultYangModuleId("iana-crypt-hash", "2014-08-06"),
+ new DefaultAppModuleInfo(IanaCryptHash.class, null));
+ appInfo.put(new DefaultYangModuleId("msea-uni-evc-interface", "2016-03-17"),
+ new DefaultAppModuleInfo(MseaUniEvcInterface.class, null));
+ appInfo.put(new DefaultYangModuleId("msea-soam-pm", "2016-02-29"),
+ new DefaultAppModuleInfo(MseaSoamPm.class, null));
+ appInfo.put(new DefaultYangModuleId("ieee-types", "2008-05-22"),
+ new DefaultAppModuleInfo(IeeeTypes.class, null));
+ appInfo.put(new DefaultYangModuleId("svc-activation-types", "2015-10-27"),
+ new DefaultAppModuleInfo(SvcActivationTypes.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-netconf", "2011-06-01"),
+ new DefaultAppModuleInfo(IetfNetconf.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-system-microsemi", "2016-05-05"),
+ new DefaultAppModuleInfo(IetfSystemMicrosemi.class, null));
+ appInfo.put(new DefaultYangModuleId("notifications", "2008-07-14"),
+ new DefaultAppModuleInfo(Notifications.class, null));
+ appInfo.put(new DefaultYangModuleId("y-1564", "2015-10-29"),
+ new DefaultAppModuleInfo(Y1564.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-interfaces", "2014-05-08"),
+ new DefaultAppModuleInfo(IetfInterfaces.class, null));
+ return ImmutableMap.copyOf(appInfo);
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java
new file mode 100644
index 0000000..cdd3700
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+
+/**
+ * Extension of mseaCfmService to include NETCONF sessions.
+ *
+ * This is manually extended and should be revised if the msea-cfm.yang,
+ * msea-soam-pm.yang or msea-soam-fm.yang files change
+ */
+public interface MseaCfmNetconfService {
+
+ /**
+ * Returns attributes of MEP.
+ *
+ * @param mdName The name of the MD
+ * @param maName The name of the MA
+ * @param mepId The ID of the MEP
+ * @param session An active NETCONF session
+ * @return mseaCfm
+ * @throws NetconfException if the session has any error
+ */
+ MseaCfm getMepEssentials(String mdName, String maName, int mepId,
+ NetconfSession session) throws NetconfException;
+
+
+ /**
+ * Returns attributes of DM.
+ *
+ * @param mdName The name of the MD
+ * @param maName The name of the MA
+ * @param mepId The ID of the MEP
+ * @param dmId The Id of the Delay Measurement
+ * @param session An active NETCONF session
+ * @return mseaCfm
+ * @throws NetconfException if the session has any error
+ */
+ MseaCfm getSoamDm(String mdName, String maName, int mepId,
+ int dmId, NetconfSession session) throws NetconfException;
+
+ /**
+ * Sets the value to attribute mseaCfm.
+ *
+ * @param mseaCfm value of mseaCfm
+ * @param session An active NETCONF session
+ * @param targetDs one of running, candidate or startup
+ * @return Boolean to indicate success or failure
+ * @throws NetconfException if the session has any error
+ */
+ boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException;
+
+ /**
+ * Service interface of transmitLoopback.
+ *
+ * @param inputVar input of service interface transmitLoopback
+ * @param session An active NETCONF session
+ * @throws NetconfException if the session has any error
+ */
+ void transmitLoopback(TransmitLoopbackInput inputVar,
+ NetconfSession session) throws NetconfException;
+
+ /**
+ * Service interface of abortLoopback.
+ *
+ * @param inputVar input of service interface abortLoopback
+ * @param session An active NETCONF session
+ * @throws NetconfException if the session has any error
+ */
+ void abortLoopback(AbortLoopbackInput inputVar,
+ NetconfSession session) throws NetconfException;
+
+ /**
+ * Service interface of transmitLinktrace.
+ *
+ * @param inputVar input of service interface transmitLinktrace
+ * @param session An active NETCONF session
+ * @return transmitLinktraceOutput output of service interface transmitLinktrace
+ * @throws NetconfException if the session has any error
+ */
+ TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar,
+ NetconfSession session) throws NetconfException;
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java
new file mode 100644
index 0000000..f9788f3
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringNetconfService.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi.yang;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
+
+import java.util.List;
+
+/**
+ * Extension of mseaSaFilteringService to include NETCONF sessions.
+ *
+ * This is manually extended and should be revised if the msea-sa-filtering.yang file changes
+ */
+public interface MseaSaFilteringNetconfService {
+ /**
+ * Returns the attribute mseaSaFiltering.
+ *
+ * @param mseaSaFiltering value of mseaSaFiltering
+ * @param session An active NETCONF session
+ * @return mseaSaFiltering
+ * @throws NetconfException if the session has any error
+ */
+ MseaSaFiltering getMseaSaFiltering(
+ MseaSaFilteringOpParam mseaSaFiltering, final NetconfSession session)
+ throws NetconfException;
+
+ /**
+ * Get a filtered subset of the config model.
+ *
+ * @param session An active NETCONF session
+ * @return mseaSaFiltering
+ * @throws NetconfException if the session has any error
+ */
+ public List<SourceAddressRange> getConfigMseaSaFilterIds(NetconfSession session)
+ throws NetconfException;
+
+ /**
+ * Sets the value to attribute mseaSaFiltering.
+ *
+ * @param mseaSaFiltering value of mseaSaFiltering
+ * @param session An active NETCONF session
+ * @param targetDs The NETCONF datastore to edit
+ * @return Boolean to indicate success or failure
+ * @throws NetconfException if the session has any error
+ */
+ boolean setMseaSaFiltering(MseaSaFilteringOpParam mseaSaFiltering,
+ NetconfSession session, DatastoreId targetDs) throws NetconfException;
+
+ /**
+ * Deletes the value to attribute mseaSaFiltering.
+ *
+ * @param mseaSaFiltering value of mseaSaFiltering
+ * @param session An active NETCONF session
+ * @param targetDs The NETCONF datastore to edit
+ * @return Boolean to indicate success or failure
+ * @throws NetconfException if the session has any error
+ */
+ boolean deleteMseaSaFilteringRange(MseaSaFilteringOpParam mseaSaFiltering,
+ NetconfSession session, DatastoreId targetDs) throws NetconfException;
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java
new file mode 100644
index 0000000..a7f85bf
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaUniEvcServiceNetconfService.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.microsemi.yang;
+
+import java.util.List;
+import java.util.Map;
+
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
+
+/**
+ * Extension of mseaUniEvcServiceService to include NETCONF sessions.
+ *
+ * This is manually extended and should be revised if the msea-uni-evc-service.yang
+ * file changes
+ */
+public interface MseaUniEvcServiceNetconfService {
+ /**
+ * Returns the configuration and state attributes of the running mseaUniEvcService.
+ *
+ * @param mseaUniEvcService value of mseaUniEvcService
+ * @param session The NETCONF session
+ * @return mseaUniEvcService
+ * @throws NetconfException if the session has any error
+ */
+ MseaUniEvcService getMseaUniEvcService(
+ MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session)
+ throws NetconfException;
+
+ /**
+ * Returns the configuration only attributes of mseaUniEvcService.
+ *
+ * @param mseaUniEvcService value of mseaUniEvcService
+ * @param session The NETCONF session
+ * @param targetDs one of running, candidate or startup
+ * @return mseaUniEvcService
+ * @throws NetconfException if the session has any error
+ */
+ MseaUniEvcService getConfigMseaUniEvcService(
+ MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException;
+
+ /**
+ * Sets the value to attribute mseaUniEvcService.
+ *
+ * @param mseaUniEvcService value of mseaUniEvcService
+ * @param session The NETCONF session
+ * @param targetDs one of running, candidate or startup
+ * @return Boolean to indicate success or failure
+ * @throws NetconfException if the session has any error
+ */
+ boolean setMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+ NetconfSession session, DatastoreId targetDs)
+ throws NetconfException;
+
+ /**
+ * Deletes the objects in mseaUniEvcService.
+ *
+ * @param mseaUniEvcService value of mseaUniEvcService
+ * @param session The NETCONF session
+ * @param targetDs one of running, candidate or startup
+ * @return Boolean to indicate success or failure
+ * @throws NetconfException if the session has any error
+ */
+ boolean deleteMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+ NetconfSession session, DatastoreId targetDs) throws NetconfException;
+
+ /**
+ * Returns a list of the CeVlanMaps on both sides of the EVC.
+ *
+ * @param session A NETCONF Session
+ * @param ncDs The datastore to affect - running, candidate or startup
+ * @return The Object Model with the VLans
+ * @throws NetconfException if the session has any error
+ */
+ MseaUniEvcService getmseaUniEvcCeVlanMaps(
+ NetconfSession session, DatastoreId ncDs)
+ throws NetconfException;
+
+ /**
+ * Replace ceVlans or delete EVCs from a device.
+ *
+ * It is necessary to have a custom command for this as the YCH cannot
+ * handle the intricacies of putting a replace operation on the
+ * ceVlanMap leaf at present
+ *
+ * @param ceVlanUpdates A Map of CeVlanMap entries to change, as flows are deleted
+ * @param flowVlanIds The IDs of flows that are being removed
+ * @param session A NETCONF Session
+ * @param targetDs The datastore to affect - running, candidate or startup
+ * @param portAssign The port assignment of the device
+ * @throws NetconfException if the session has any error
+ */
+ void removeEvcUniFlowEntries(
+ Map<Integer, String> ceVlanUpdates,
+ Map<Integer, List<Short>> flowVlanIds,
+ NetconfSession session,
+ DatastoreId targetDs,
+ UniSideInterfaceAssignmentEnum portAssign)
+ throws NetconfException;
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java
new file mode 100644
index 0000000..8ced81c
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/UniSide.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang;
+
+/**
+ * An enumeration to describe the side of a UNI - Customer or Network.
+ * For reference see MEF 6.2
+ */
+public enum UniSide {
+ CUSTOMER,
+ NETWORK
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java
new file mode 100644
index 0000000..fbf89be
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnic.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.custom;
+
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.EvcPerUniServiceTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnic;
+
+import java.util.List;
+
+/**
+ * Extend the DefaultEvcPerUnic so that the ceVlanMap can always be initialized at 0.
+ */
+public class CustomEvcPerUnic extends DefaultEvcPerUnic {
+ @Override
+ public ServiceListType ceVlanMap() {
+ if (ceVlanMap == null) {
+ return new ServiceListType("0");
+ }
+ return ceVlanMap;
+ }
+ @Override
+ public Object ingressBwpGroupIndex() {
+ return ingressBwpGroupIndex;
+ }
+
+ @Override
+ public EvcPerUniServiceTypeEnum evcPerUniServiceType() {
+ return evcPerUniServiceType;
+ }
+
+ @Override
+ public TagManipulation tagManipulation() {
+ return tagManipulation;
+ }
+
+ @Override
+ public List<FlowMapping> flowMapping() {
+ return flowMapping;
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java
new file mode 100644
index 0000000..d8712dc
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/CustomEvcPerUnin.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.custom;
+
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.EvcPerUniServiceTypeEnum;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnin;
+
+import java.util.List;
+
+/**
+ * Extend the DefaultEvcPerUnin so that the ceVlanMap can always be initialized at 0.
+ */
+public class CustomEvcPerUnin extends DefaultEvcPerUnin {
+ @Override
+ public ServiceListType ceVlanMap() {
+ if (ceVlanMap == null) {
+ return new ServiceListType("0");
+ }
+ return ceVlanMap;
+ }
+ @Override
+ public Object ingressBwpGroupIndex() {
+ return ingressBwpGroupIndex;
+ }
+
+ @Override
+ public EvcPerUniServiceTypeEnum evcPerUniServiceType() {
+ return evcPerUniServiceType;
+ }
+
+ @Override
+ public TagManipulation tagManipulation() {
+ return tagManipulation;
+ }
+
+ @Override
+ public List<FlowMapping> flowMapping() {
+ return flowMapping;
+ }
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java
new file mode 100644
index 0000000..1a7a471
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/custom/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for Microsemi device drivers support for NETCONF for EA1000.
+ */
+package org.onosproject.drivers.microsemi.yang.custom;
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
new file mode 100644
index 0000000..3867a2f
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.ByteSource;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaContext;
+import org.onosproject.yang.model.SchemaContextProvider;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.CompositeStream;
+import org.onosproject.yang.runtime.DefaultCompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+import org.onosproject.yang.runtime.DefaultYangSerializerContext;
+import org.onosproject.yang.runtime.YangModelRegistry;
+import org.onosproject.yang.runtime.YangSerializer;
+import org.onosproject.yang.runtime.YangSerializerContext;
+import org.onosproject.yang.runtime.YangSerializerRegistry;
+import org.onosproject.yang.serializers.xml.XmlSerializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract class that implements some of the core functions of a YANG model service.
+ *
+ */
+@Component(immediate = true)
+@Service
+public abstract class AbstractYangServiceImpl {
+ public static final String NC_OPERATION = "nc:operation";
+ public static final String OP_DELETE = "delete";
+
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+ protected boolean alreadyLoaded = false;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected YangModelRegistry yangModelRegistry;
+
+// @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+// protected SchemaContextProvider schemaContextProvider;
+
+ protected ApplicationId appId;
+
+ // xSer is not a service and is a class variable. Can be lost on deactivate.
+ // Must be recreated on activate
+ protected XmlSerializer xSer;
+ protected YangSerializerContext yCtx;
+
+ protected static final Pattern REGEX_XML_HEADER =
+ Pattern.compile("(<\\?xml).*(\\?>)", Pattern.DOTALL);
+ protected static final Pattern REGEX_RPC_REPLY =
+ Pattern.compile("(<rpc-reply)[ ]*" +
+ "(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\")[ ]*" +
+ "(message-id=\")[0-9]*(\">)", Pattern.DOTALL);
+ protected static final Pattern REGEX_RPC_REPLY_DATA_NS =
+ Pattern.compile("(<data)[ ]*(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)");
+ protected static final Pattern REGEX_RPC_REPLY_DATA =
+ Pattern.compile("(<data>)");
+ protected static final Pattern REGEX_RPC_REPLY_DATA_CLOSE =
+ Pattern.compile("(</data>)");
+ protected static final Pattern REGEX_RPC_REPLY_DATA_EMPTY =
+ Pattern.compile("(<data/>)");
+ protected static final Pattern REGEX_RPC_REPLY_CLOSE =
+ Pattern.compile("(</rpc-reply>)");
+
+ @Activate
+ public void activate() {
+ Set<YangSerializer> yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers();
+ yangSer.forEach(ser -> {
+ if (ser instanceof XmlSerializer) {
+ xSer = (XmlSerializer) ser;
+ }
+ });
+ SchemaContext context = ((SchemaContextProvider) yangModelRegistry)
+ .getSchemaContext(ResourceId.builder().addBranchPointSchema("/", null).build());
+
+ yCtx = new DefaultYangSerializerContext(context, null);
+ };
+
+ @Deactivate
+ public void deactivate() {
+ alreadyLoaded = false;
+ }
+
+ /**
+ * Internal method to generically make a NETCONF get query from YANG objects.
+ * @param moFilter A YANG object model
+ * @param session A NETCONF session
+ * @return YangObjectModel
+ * @throws NetconfException if the session has any error
+ */
+ protected final ModelObjectData getNetconfObject(
+ ModelObjectData moFilter, NetconfSession session)
+ throws NetconfException {
+
+ return getConfigNetconfObject(moFilter, session, null);
+ }
+
+ /**
+ * Internal method to generically make a NETCONF get-config query from YANG objects.
+ *
+ * @param moFilter A YANG object model
+ * @param session A NETCONF session
+ * @param targetDs - running,candidate or startup
+ * @return YangObjectModel
+ * @throws NetconfException if the session has any error
+ */
+ protected final ModelObjectData getConfigNetconfObject(
+ ModelObjectData moFilter, NetconfSession session, DatastoreId targetDs)
+ throws NetconfException {
+ if (session == null) {
+ throw new NetconfException("Session is null when calling getConfigNetconfObject()");
+ }
+
+ if (moFilter == null) {
+ throw new NetconfException("Query object cannot be null");
+ }
+
+ String xmlQueryStr = encodeMoToXmlStr(moFilter, null);
+
+ log.debug("Sending <get-(config)> query on NETCONF session " + session.getSessionId() +
+ ":\n" + xmlQueryStr);
+ String xmlResult;
+ if (targetDs == null) {
+ xmlResult = session.get(xmlQueryStr, null);
+ } else {
+ xmlResult = session.getConfig(targetDs, xmlQueryStr);
+ }
+ xmlResult = removeRpcReplyData(xmlResult);
+
+ DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+ null, new ByteArrayInputStream(xmlResult.getBytes()));
+ CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+ return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+ }
+
+ /**
+ * Internal method to generically make a NETCONF edit-config call from a set of YANG objects.
+ *
+ * @param moConfig A YANG object model
+ * @param session A NETCONF session
+ * @param targetDs - running,candidate or startup
+ * @param annotations A list of AnnotatedNodeInfos to be added to the DataNodes
+ * @return Boolean value indicating success or failure of command
+ * @throws NetconfException if the session has any error
+ */
+ protected final boolean setNetconfObject(
+ ModelObjectData moConfig, NetconfSession session, DatastoreId targetDs,
+ List<AnnotatedNodeInfo> annotations) throws NetconfException {
+ if (moConfig == null) {
+ throw new NetconfException("Query object cannot be null");
+ } else if (session == null) {
+ throw new NetconfException("Session is null when calling getMseaSaFiltering()");
+ } else if (targetDs == null) {
+ throw new NetconfException("TargetDs is null when calling getMseaSaFiltering()");
+ }
+
+ String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations);
+ log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
+ ":\n" + xmlQueryStr);
+
+ return session.editConfig(targetDs, null, xmlQueryStr);
+ }
+
+ protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter,
+ List<AnnotatedNodeInfo> annotations)
+ throws NetconfException {
+ //Convert the param to XML to use as a filter
+ ResourceData rd = ((ModelConverter) yangModelRegistry).createDataNode(yangObjectOpParamFilter);
+
+ DefaultCompositeData.Builder cdBuilder =
+ DefaultCompositeData.builder().resourceData(rd);
+ if (annotations != null) {
+ for (AnnotatedNodeInfo ani : annotations) {
+ cdBuilder.addAnnotatedNodeInfo(ani);
+ }
+ }
+ CompositeStream cs = xSer.encode(cdBuilder.build(), yCtx);
+ //Convert the param to XML to use as a filter
+
+ try {
+ ByteSource byteSource = new ByteSource() {
+ @Override
+ public InputStream openStream() throws IOException {
+ return cs.resourceData();
+ }
+ };
+
+ return byteSource.asCharSource(Charsets.UTF_8).read();
+ } catch (IOException e) {
+ throw new NetconfException("Error decoding CompositeStream to String", e);
+ }
+ }
+
+ protected static final String removeRpcReplyData(String rpcReplyXml) {
+ rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst("");
+ rpcReplyXml = REGEX_RPC_REPLY.matcher(rpcReplyXml).replaceFirst("");
+ rpcReplyXml = REGEX_RPC_REPLY_DATA_NS.matcher(rpcReplyXml).replaceFirst("");
+ rpcReplyXml = REGEX_RPC_REPLY_DATA.matcher(rpcReplyXml).replaceFirst("");
+ rpcReplyXml = REGEX_RPC_REPLY_DATA_CLOSE.matcher(rpcReplyXml).replaceFirst("");
+ rpcReplyXml = REGEX_RPC_REPLY_DATA_EMPTY.matcher(rpcReplyXml).replaceFirst("");
+ rpcReplyXml = REGEX_RPC_REPLY_CLOSE.matcher(rpcReplyXml).replaceFirst("");
+ rpcReplyXml = rpcReplyXml.replace("\t", "");
+ return rpcReplyXml;
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java
new file mode 100644
index 0000000..3673594
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import java.io.ByteArrayInputStream;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.IetfSystemNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystemState;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.systemrestart.SystemRestartInput;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+/**
+ * Implementation of the IetfService YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class IetfSystemManager extends AbstractYangServiceImpl
+ implements IetfSystemNetconfService {
+
+ protected static final String IETF_SYSTEM = "org.onosproject.drivers.microsemi.yang.ietfsystem";
+
+ @Activate
+ public void activate() {
+ super.activate();
+ appId = coreService.registerApplication(IETF_SYSTEM);
+ log.info("IetfSystemManager Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ super.deactivate();
+ log.info("IetfSystemManager Stopped");
+ }
+
+ /**
+ * Get a filtered subset of the model.
+ * This is meant to filter the current live model
+ * against the attribute(s) given in the argument
+ * and return the filtered model.
+ * @throws NetconfException if the session has any error
+ */
+ @Override
+ public IetfSystem getIetfSystem(IetfSystemOpParam ietfSystemFilter, NetconfSession session)
+ throws NetconfException {
+
+ ModelObjectData moQuery = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) ietfSystemFilter.system())
+ .build();
+
+ ModelObjectData moReply = getNetconfObject(moQuery, session);
+
+ IetfSystemOpParam ietfSystem = new IetfSystemOpParam();
+ for (ModelObject mo:moReply.modelObjects()) {
+ if (mo instanceof DefaultSystem) {
+ ietfSystem.system((DefaultSystem) mo);
+ } else if (mo instanceof DefaultSystemState) {
+ ietfSystem.systemState((DefaultSystemState) mo);
+ }
+ }
+
+ return ietfSystem;
+ }
+
+ @Override
+ public IetfSystem getIetfSystemInit(NetconfSession session) throws NetconfException {
+ if (session == null) {
+ throw new NetconfException("Session is null when calling getIetfSystemInit()");
+ }
+
+ String xmlResult = session.get(getInitRequestBuilder(), null);
+
+ xmlResult = removeRpcReplyData(xmlResult);
+ DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+ null, new ByteArrayInputStream(xmlResult.getBytes()));
+ CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+ ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+ IetfSystemOpParam ietfSystem = new IetfSystemOpParam();
+ for (ModelObject mo:mod.modelObjects()) {
+ if (mo instanceof DefaultSystem) {
+ ietfSystem.system((DefaultSystem) mo);
+ } else if (mo instanceof DefaultSystemState) {
+ ietfSystem.systemState((DefaultSystemState) mo);
+ }
+ }
+
+ return ietfSystem;
+ }
+
+ /**
+ * Call NETCONF edit-config with a configuration.
+ */
+ @Override
+ public boolean setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session,
+ DatastoreId ncDs) throws NetconfException {
+ ModelObjectData mo = DefaultModelObjectData.builder()
+ .addModelObject(ietfSystem).build();
+ return setNetconfObject(mo, session, ncDs, null);
+ }
+
+ @Override
+ public void setCurrentDatetime(OffsetDateTime date, NetconfSession session)
+ throws NetconfException {
+ String xmlQueryStr = getSetCurrentDatetimeBuilder(date);
+ log.info("Sending <get> query on NETCONF session " + session.getSessionId() +
+ ":\n" + xmlQueryStr);
+
+ String xmlResult = session.doWrappedRpc(xmlQueryStr);
+ log.info("Result from NETCONF RPC <set-current-datetime>: {}", xmlResult);
+ }
+
+ @Override
+ public void systemRestart(SystemRestartInput inputVar, NetconfSession session) {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ public void systemShutdown(NetconfSession session) {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ public DoUpgradeAndRebootOutput doUpgradeAndReboot(DoUpgradeAndRebootInput inputVar, NetconfSession session)
+ throws NetconfException {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ public void pullUpdateTarFromTftp(PullUpdateTarFromTftpInput inputVar, NetconfSession session)
+ throws NetconfException {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ public ReadFromSyslogOutput readFromSyslog(ReadFromSyslogInput inputVar, NetconfSession session)
+ throws NetconfException {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+
+ /**
+ * Builds a request crafted to get the configuration required to create
+ * details descriptions for the device.
+ *
+ * @return The request string.
+ */
+ private static String getInitRequestBuilder() {
+ StringBuilder rpc = new StringBuilder();
+ rpc.append("<system-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\" ");
+ rpc.append("xmlns:sysms=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">");
+ rpc.append("<platform>");
+ rpc.append("<os-release/>");
+ rpc.append("<sysms:device-identification>");
+ rpc.append("<sysms:serial-number/>");
+ rpc.append("</sysms:device-identification>");
+ rpc.append("</platform>");
+ rpc.append("<clock>");
+ rpc.append("<current-datetime/>");
+ rpc.append("</clock>");
+ rpc.append("</system-state>");
+ rpc.append("<system xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\" ");
+ rpc.append("xmlns:sysms=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">");
+ rpc.append("<sysms:longitude/>");
+ rpc.append("<sysms:latitude/>");
+ rpc.append("</system>");
+ return rpc.toString();
+ }
+
+ private static String getSetCurrentDatetimeBuilder(OffsetDateTime date) {
+ StringBuilder rpc = new StringBuilder();
+ rpc.append("<set-current-datetime xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\">");
+ rpc.append("<current-datetime>");
+ rpc.append(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxxx")));
+ rpc.append("</current-datetime>");
+ rpc.append("</set-current-datetime>");
+
+ return rpc.toString();
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
new file mode 100644
index 0000000..36f48c4
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+import java.io.ByteArrayInputStream;
+
+/**
+ * Implementation of the MseaCfmServiceNetconf YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaCfmManager extends AbstractYangServiceImpl
+ implements MseaCfmNetconfService {
+
+ public static final String MSEA_CFM = "org.onosproject.drivers.microsemi.yang.mseacfmservice";
+
+ @Activate
+ public void activate() {
+ super.activate();
+ appId = coreService.registerApplication(MSEA_CFM);
+ log.info("MseaCfmService Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ super.deactivate();
+ log.info("MseaCfmService Stopped");
+ }
+
+ @Override
+ public MseaCfm getMepEssentials(String mdName, String maName, int mepId,
+ NetconfSession session) throws NetconfException {
+ if (session == null) {
+ throw new NetconfException("Session is null when calling getMepEssentials()");
+ }
+
+ String xmlQueryStr = buildMepQueryString(mdName, maName, mepId);
+ log.debug("Sending <get> for " +
+ " query on NETCONF session " + session.getSessionId() +
+ ":\n" + xmlQueryStr);
+
+ String xmlResult = session.get(xmlQueryStr, null);
+
+ xmlResult = removeRpcReplyData(xmlResult);
+ DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+ null, new ByteArrayInputStream(xmlResult.getBytes()));
+ CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+ ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+ MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+ for (ModelObject mo:mod.modelObjects()) {
+ if (mo instanceof DefaultMefCfm) {
+ mseaCfm.mefCfm((DefaultMefCfm) mo);
+ }
+ }
+
+ return mseaCfm;
+ }
+
+ @Override
+ public MseaCfm getSoamDm(String mdName, String maName, int mepId,
+ int dmId, NetconfSession session) throws NetconfException {
+ String xmlQueryStr = buildDmQueryString(mdName, maName, mepId, dmId);
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ public boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException {
+ ModelObjectData moEdit = DefaultModelObjectData.builder()
+ .addModelObject(mseaCfm).build();
+
+ return setNetconfObject(moEdit, session, targetDs, null);
+ }
+
+ /**
+ * Call RPCs on the device through NETCONF.
+ */
+ @Override
+ public void transmitLoopback(TransmitLoopbackInput inputVar, NetconfSession session) throws NetconfException {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ public void abortLoopback(AbortLoopbackInput inputVar, NetconfSession session) throws NetconfException {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ public TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar, NetconfSession session)
+ throws NetconfException {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ private String buildMepQueryString(String mdName, String maName, int mepId) {
+ StringBuilder rpc = new StringBuilder();
+
+ rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
+ rpc.append(" xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" ");
+ rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
+ rpc.append("<maintenance-domain>\n");
+ rpc.append("<id/>\n");
+ rpc.append("<name>" + mdName + "</name>\n");
+ rpc.append("<md-level/>\n");
+ rpc.append("<maintenance-association>\n");
+ rpc.append("<id/>\n");
+ rpc.append("<name>" + maName + "</name>\n");
+ rpc.append("<ccm-interval>10ms</ccm-interval>\n");
+ rpc.append("<remote-meps/>\n");
+ rpc.append("<component-list/>\n");
+ rpc.append("<maintenance-association-end-point>\n");
+ rpc.append("<mep-identifier>" + mepId + "</mep-identifier>\n");
+ rpc.append("<interface/>\n");
+ rpc.append("<primary-vid/>\n");
+ rpc.append("<administrative-state/>\n");
+ rpc.append("<ccm-ltm-priority/>\n");
+ rpc.append("<continuity-check/>\n");
+ rpc.append("<mac-address/>\n");
+ rpc.append("<msea-soam-fm:port-status/>\n");
+ rpc.append("<msea-soam-fm:interface-status/>\n");
+ rpc.append("<msea-soam-fm:last-defect-sent/>\n");
+ rpc.append("<msea-soam-fm:rdi-transmit-status/>\n");
+ rpc.append("<loopback/>\n");
+ rpc.append("<remote-mep-database/>\n");
+ rpc.append("<linktrace/>\n");
+ rpc.append("</maintenance-association-end-point>\n");
+ rpc.append("</maintenance-association>\n");
+ rpc.append("</maintenance-domain>\n");
+ rpc.append("</mef-cfm>");
+
+ return rpc.toString();
+ }
+
+
+ private String buildDmQueryString(String mdName, String maName, int mepId, int dmId) {
+ StringBuilder rpc = new StringBuilder();
+
+ rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
+ rpc.append(" xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" ");
+ rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
+ rpc.append("<maintenance-domain>\n");
+ rpc.append("<id/>\n");
+ rpc.append("<name>" + mdName + "</name>\n");
+ rpc.append("<md-level/>\n");
+ rpc.append("<maintenance-association>\n");
+ rpc.append("<id/>\n");
+ rpc.append("<name>" + maName + "</name>\n");
+ rpc.append("<ccm-interval>10ms</ccm-interval>\n");
+ rpc.append("<maintenance-association-end-point>\n");
+ rpc.append("<mep-identifier>" + mepId + "</mep-identifier>\n");
+ rpc.append("<msea-soam-pm:delay-measurements>");
+ rpc.append("<msea-soam-pm:delay-measurement>");
+ rpc.append("<msea-soam-pm:dm-id>" + dmId + "</msea-soam-pm:dm-id>");
+ rpc.append("</msea-soam-pm:delay-measurement>");
+ rpc.append("</msea-soam-pm:delay-measurements>");
+ rpc.append("</maintenance-association-end-point>\n");
+ rpc.append("</maintenance-association>\n");
+ rpc.append("</maintenance-domain>\n");
+ rpc.append("</mef-cfm>");
+
+ return rpc.toString();
+ }
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
new file mode 100644
index 0000000..01af138
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
+import org.onosproject.yang.runtime.DefaultAnnotation;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of the MseaSaFiltering YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaSaFilteringManager extends AbstractYangServiceImpl
+ implements MseaSaFilteringNetconfService {
+ public static final String MSEA_SA_FILTERING =
+ "org.onosproject.drivers.microsemi.yang.mseasafiltering";
+ public static final String MSEA_SA_FILTERING_NS =
+ "http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering";
+
+ @Activate
+ public void activate() {
+ super.activate();
+ appId = coreService.registerApplication(MSEA_SA_FILTERING);
+ log.info("MseaSaFilteringManager Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ super.deactivate();
+ log.info("MseaSaFilteringManager Stopped");
+ }
+
+ /**
+ * Get a filtered subset of the model.
+ * This is meant to filter the current live model
+ * against the attribute(s) given in the argument
+ * and return the filtered model.
+ */
+ @Override
+ public MseaSaFiltering getMseaSaFiltering(
+ MseaSaFilteringOpParam mseaSaFilteringFilter, NetconfSession session)
+ throws NetconfException {
+ ModelObjectData moQuery = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaSaFilteringFilter
+ .sourceIpaddressFiltering())
+ .build();
+
+
+ ModelObjectData moReply = getNetconfObject(moQuery, session);
+
+ MseaSaFiltering reply = new MseaSaFilteringOpParam();
+ for (ModelObject mo:moReply.modelObjects()) {
+ if (mo instanceof SourceIpaddressFiltering) {
+ reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo);
+ }
+ }
+ return reply;
+ }
+
+ /**
+ * Get a filtered subset of the config model (from running)
+ * This is meant to filter the current live model
+ * against the attribute(s) given in the argument
+ * and return the filtered model.
+ */
+ @Override
+ public List<SourceAddressRange> getConfigMseaSaFilterIds(NetconfSession session)
+ throws NetconfException {
+
+ String xmlResult = session.getConfig(DatastoreId.RUNNING, saFilterQuery());
+ xmlResult = removeRpcReplyData(xmlResult);
+
+ DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+ null, new ByteArrayInputStream(xmlResult.getBytes()));
+ CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+ ModelObjectData moReply = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+ MseaSaFiltering reply = new MseaSaFilteringOpParam();
+ for (ModelObject mo:moReply.modelObjects()) {
+ if (mo instanceof SourceIpaddressFiltering) {
+ reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo);
+ }
+ }
+ if (reply != null && reply.sourceIpaddressFiltering() != null &&
+ reply.sourceIpaddressFiltering().interfaceEth0() != null) {
+ return reply.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
+ } else {
+ return new ArrayList<SourceAddressRange>();
+ }
+ }
+
+ /**
+ * Call NETCONF edit-config with a configuration.
+ */
+ @Override
+ public boolean setMseaSaFiltering(MseaSaFilteringOpParam mseaSaFiltering,
+ NetconfSession session, DatastoreId ncDs) throws NetconfException {
+
+ ModelObjectData moQuery = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaSaFiltering
+ .sourceIpaddressFiltering()).build();
+
+ return setNetconfObject(moQuery, session, ncDs, null);
+ }
+
+ @Override
+ public boolean deleteMseaSaFilteringRange(MseaSaFilteringOpParam mseaSaFiltering,
+ NetconfSession session, DatastoreId ncDs) throws NetconfException {
+
+ ModelObjectData moQuery = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaSaFiltering
+ .sourceIpaddressFiltering()).build();
+
+ ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
+ if (mseaSaFiltering.sourceIpaddressFiltering().interfaceEth0() != null &&
+ mseaSaFiltering.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange() != null) {
+
+ for (SourceAddressRange sar:mseaSaFiltering.sourceIpaddressFiltering()
+ .interfaceEth0().sourceAddressRange()) {
+ String sarRangeIdStr = String.valueOf(sar.rangeId());
+
+ ResourceId.Builder ridBuilder = ResourceId.builder()
+ .addBranchPointSchema("/", null)
+ .addBranchPointSchema("source-ipaddress-filtering", MSEA_SA_FILTERING_NS)
+ .addBranchPointSchema("interface-eth0", MSEA_SA_FILTERING_NS)
+ .addBranchPointSchema("source-address-range", MSEA_SA_FILTERING_NS)
+ .addKeyLeaf("range-id", MSEA_SA_FILTERING_NS, sarRangeIdStr);
+
+ AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+ .resourceId(ridBuilder.build())
+ .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+ .build();
+
+ anis.add(ani);
+ }
+ } else {
+ //Delete all
+ ResourceId.Builder ridBuilder = ResourceId.builder()
+ .addBranchPointSchema("/", null)
+ .addBranchPointSchema("source-ipaddress-filtering", MSEA_SA_FILTERING_NS);
+ AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+ .resourceId(ridBuilder.build())
+ .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+ .build();
+ anis.add(ani);
+ }
+
+ return setNetconfObject(moQuery, session, ncDs, anis);
+ }
+
+
+ private static String saFilterQuery() {
+ StringBuilder sb = new StringBuilder("<source-ipaddress-filtering " +
+ "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering\">");
+ sb.append("<interface-eth0>");
+ sb.append("<filter-admin-state>blacklist</filter-admin-state>");
+ sb.append("<source-address-range>");
+ sb.append("<range-id/>");
+ sb.append("</source-address-range>");
+ sb.append("</interface-eth0>");
+ sb.append("</source-ipaddress-filtering>");
+ return sb.toString();
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
new file mode 100644
index 0000000..f965541
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
+import org.onosproject.yang.runtime.DefaultAnnotation;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+/**
+ * Implementation of the MseaUniEvcServiceService YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaUniEvcServiceManager extends AbstractYangServiceImpl
+ implements MseaUniEvcServiceNetconfService {
+ public static final String MSEA_UNI_EVC_SVC =
+ "org.onosproject.drivers.microsemi.yang.mseaunievcservice";
+ public static final String MSEA_UNI_EVC_SVC_NS =
+ "http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service";
+
+ @Activate
+ public void activate() {
+ super.activate();
+ appId = coreService.registerApplication(MSEA_UNI_EVC_SVC);
+ log.info("MseaUniEvcServiceManager Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ super.deactivate();
+ log.info("MseaUniEvcServiceManager Stopped");
+ }
+
+ @Override
+ public MseaUniEvcService getMseaUniEvcService(
+ MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session)
+ throws NetconfException {
+
+ return getConfigMseaUniEvcService(mseaUniEvcService, session, null);
+ }
+
+ @Override
+ public MseaUniEvcService getConfigMseaUniEvcService(
+ MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException {
+
+ ModelObjectData moFilter = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+ ModelObjectData moReply = getConfigNetconfObject(moFilter, session, targetDs);
+
+ MseaUniEvcService reply = new MseaUniEvcServiceOpParam();
+ for (ModelObject mo:moReply.modelObjects()) {
+ if (mo instanceof MefServices) {
+ reply.mefServices((MefServices) mo);
+ }
+ }
+ return reply;
+ }
+
+ /**
+ * Modify the configuration.
+ */
+ @Override
+ public boolean setMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+ NetconfSession session, DatastoreId ncDs) throws NetconfException {
+ ModelObjectData moEdit = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+ return setNetconfObject(moEdit, session, ncDs, null);
+ }
+
+ /**
+ * Delete the configuration.
+ */
+ @Override
+ public boolean deleteMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+ NetconfSession session, DatastoreId ncDs) throws NetconfException {
+ ModelObjectData moEdit = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+ ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
+ for (BwpGroup bwpGrp:mseaUniEvcService.mefServices().profiles().bwpGroup()) {
+ String bwpGroupIndex = String.valueOf(bwpGrp.groupIndex());
+
+ ResourceId.Builder ridBuilder = ResourceId.builder()
+ .addBranchPointSchema("/", null)
+ .addBranchPointSchema("mef-services", MSEA_UNI_EVC_SVC_NS)
+ .addBranchPointSchema("profiles", MSEA_UNI_EVC_SVC_NS)
+ .addBranchPointSchema("bwp-group", MSEA_UNI_EVC_SVC_NS)
+ .addKeyLeaf("group-index", MSEA_UNI_EVC_SVC_NS, bwpGroupIndex);
+
+ AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+ .resourceId(ridBuilder.build())
+ .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+ .build();
+
+ anis.add(ani);
+ }
+
+
+ return setNetconfObject(moEdit, session, ncDs, anis);
+ }
+
+
+ @Override
+ public MseaUniEvcService getmseaUniEvcCeVlanMaps(
+ NetconfSession session, DatastoreId ncDs)
+ throws NetconfException {
+ if (session == null) {
+ throw new NetconfException("Session is null when calling getMseaSaFiltering()");
+ }
+
+ String xmlResult = session.getConfig(ncDs, evcFilterQuery());
+ xmlResult = removeRpcReplyData(xmlResult);
+
+ DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+ null, new ByteArrayInputStream(xmlResult.getBytes()));
+ CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+ ModelObjectData moReply = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+ MseaUniEvcService reply = new MseaUniEvcServiceOpParam();
+ for (ModelObject mo:moReply.modelObjects()) {
+ if (mo instanceof MefServices) {
+ reply.mefServices((MefServices) mo);
+ }
+ }
+ return reply;
+ }
+
+ @Override
+ public void removeEvcUniFlowEntries(
+ Map<Integer, String> ceVlanUpdates,
+ Map<Integer, List<Short>> flowVlanIds,
+ NetconfSession session, DatastoreId targetDs,
+ UniSideInterfaceAssignmentEnum portAssign) throws NetconfException {
+
+ List<Integer> evcAlreadyHandled = new ArrayList<>();
+ StringBuilder xmlEvcUpdate = new StringBuilder(evcUniOpener());
+ for (Integer evcKey:ceVlanUpdates.keySet()) {
+ int evcId = (evcKey & ((1 << 8) - 100)) >> 2;
+ if (evcAlreadyHandled.contains(new Integer(evcId))) {
+ continue;
+ }
+ evcAlreadyHandled.add(evcId);
+ int port = (evcKey & 3);
+ String ceVlanMapThis = ceVlanUpdates.get(evcKey);
+ String ceVlanMapOpposite = ceVlanUpdates.get(evcKey ^ 1);
+
+ if ((ceVlanMapThis == null || ceVlanMapThis.isEmpty()) &&
+ (ceVlanMapOpposite == null || ceVlanMapOpposite.isEmpty())) {
+ xmlEvcUpdate.append("<evc nc:operation=\"delete\">\n<evc-index>");
+ xmlEvcUpdate.append(Integer.toString(evcId));
+ xmlEvcUpdate.append("</evc-index>\n</evc>\n");
+ } else {
+ xmlEvcUpdate.append("<evc>\n<evc-index>");
+ xmlEvcUpdate.append(Integer.toString(evcId));
+ xmlEvcUpdate.append("</evc-index>\n<evc-per-uni>\n");
+ if (port == 0 && portAssign == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS ||
+ port == 1 && portAssign == UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST) {
+ if (ceVlanMapThis != null) {
+ xmlEvcUpdate.append("<evc-per-uni-c>\n<ce-vlan-map nc:operation=\"replace\">");
+ xmlEvcUpdate.append(ceVlanMapThis);
+ xmlEvcUpdate.append("</ce-vlan-map>\n");
+ xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey)));
+ xmlEvcUpdate.append("</evc-per-uni-c>\n");
+ }
+ if (ceVlanMapOpposite != null) {
+ xmlEvcUpdate.append("<evc-per-uni-n>\n<ce-vlan-map nc:operation=\"replace\">");
+ xmlEvcUpdate.append(ceVlanMapOpposite);
+ xmlEvcUpdate.append("</ce-vlan-map>\n");
+ xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey ^ 1)));
+ xmlEvcUpdate.append("</evc-per-uni-n>\n");
+ }
+ } else {
+ if (ceVlanMapThis != null) {
+ xmlEvcUpdate.append("<evc-per-uni-n>\n<ce-vlan-map nc:operation=\"replace\">");
+ xmlEvcUpdate.append(ceVlanMapThis);
+ xmlEvcUpdate.append("</ce-vlan-map>\n");
+ xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey)));
+ xmlEvcUpdate.append("</evc-per-uni-n>\n");
+ }
+ if (ceVlanMapOpposite != null) {
+ xmlEvcUpdate.append("<evc-per-uni-c>\n<ce-vlan-map nc:operation=\"replace\">");
+ xmlEvcUpdate.append(ceVlanMapOpposite);
+ xmlEvcUpdate.append("</ce-vlan-map>\n");
+ xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey ^ 1)));
+ xmlEvcUpdate.append("</evc-per-uni-c>\n");
+ }
+ }
+
+ xmlEvcUpdate.append("</evc-per-uni>\n</evc>\n");
+ }
+ }
+ xmlEvcUpdate.append("</uni>\n</mef-services>");
+
+ log.info("Sending XML <edit-config> on NETCONF session " + session.getSessionId() +
+ ":\n" + xmlEvcUpdate.toString());
+
+
+ session.editConfig(targetDs, null, xmlEvcUpdate.toString());
+ }
+
+
+ private static String deleteFlowMapping(List<Short> vlanIds) {
+ if (vlanIds == null || vlanIds.size() == 0) {
+ return "";
+ }
+ StringBuilder fmXmlBuilder = new StringBuilder();
+ for (long vlanId:vlanIds) {
+ fmXmlBuilder.append("<flow-mapping nc:operation=\"delete\">\n");
+ fmXmlBuilder.append("<ce-vlan-id>");
+ fmXmlBuilder.append(String.valueOf(vlanId));
+ fmXmlBuilder.append("</ce-vlan-id>\n");
+ fmXmlBuilder.append("</flow-mapping>\n");
+ }
+
+ return fmXmlBuilder.toString();
+ }
+
+ private String evcFilterQuery() {
+ StringBuilder sb = new StringBuilder("<mef-services "
+ + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">");
+ sb.append("<uni>");
+ sb.append("<evc>");
+ sb.append("<evc-index/>");
+ sb.append("<evc-per-uni>");
+ sb.append("<evc-per-uni-c>");
+ sb.append("<ce-vlan-map/>");
+ sb.append("<flow-mapping/>");
+ sb.append("<ingress-bwp-group-index/>");
+ sb.append("</evc-per-uni-c>");
+ sb.append("<evc-per-uni-n>");
+ sb.append("<ce-vlan-map/>");
+ sb.append("<flow-mapping/>");
+ sb.append("<ingress-bwp-group-index/>");
+ sb.append("</evc-per-uni-n>");
+ sb.append("</evc-per-uni>");
+ sb.append("</evc>");
+ sb.append("</uni>");
+ sb.append("</mef-services>");
+
+ return sb.toString();
+ }
+
+ private String evcUniOpener() {
+ StringBuilder sb = new StringBuilder("<mef-services ");
+ sb.append("xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">\n");
+ sb.append("<uni>\n");
+
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java
new file mode 100644
index 0000000..ccf0dd2
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for Microsemi device drivers support for NETCONF for EA1000.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java
new file mode 100644
index 0000000..d886c69
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for Microsemi device drivers support for NETCONF for EA1000.
+ */
+package org.onosproject.drivers.microsemi.yang;
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
new file mode 100644
index 0000000..52ede6d
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.lang.ArrayUtils;
+
+/**
+ * A set of static utilities that allow a ce-vlan-map to be decomposed.
+ *
+ * This is an implementation specific to Microsemi that encodes ce-vlan-map
+ * in a similar way to Section 7.9 in the MEF 10.2 specification. That specification
+ * suggests comma delimited lists of VIDs - this implementation adds on colons to
+ * specify a contiguous range of IDs
+ */
+public final class CeVlanMapUtils {
+
+ private CeVlanMapUtils() {
+ //Do not allow this utility class to be instantiated
+ }
+
+ /**
+ * Calculate the ceVlanMap in to a Set of values.
+ *
+ * From Yang description
+ * "This object indicates the CE-VLANs associated with the specific
+ * EVC on a UNI. CE-VLAN IDs have value of 0 to 4095. The CE-VLAN ID
+ * list can be a single value or multiple values separated by a delimiter.
+ * Some valid values are: '100', '1:10', '10,20,30', '1:4095'. In the
+ * first example only CE-VLAN ID 100 is associated with the VLAN map.
+ * In the second example the CE-VLAN map includes CE-VLAN IDs 1 through
+ * 10 (range of values). The third example indicates three separate values
+ * that make up the CE-VLAN map. The last example indicates all CE-VLAN IDs
+ * are included in the map (range of values). ";
+ * reference
+ * "[MEF 6.1] 6.1; [MEF 7.2] 6.2.1.3";
+ * @param ceVlanMap A list of vlan id's in the format described above
+ * @return A set of vlan ids
+ */
+ public static Short[] getVlanSet(String ceVlanMap) {
+ if (ceVlanMap == null || ceVlanMap.isEmpty()) {
+ return new Short[0];
+ }
+ Set<Short> ceVlanSet = new TreeSet<Short>();
+
+ String[] ceVlanMapCommas = ceVlanMap.split(",");
+ for (String ceVlanMapComma:ceVlanMapCommas) {
+ String[] ceVlanMapColon = ceVlanMapComma.split(":");
+ if (ceVlanMapColon.length == 1) {
+ ceVlanSet.add(Short.decode(ceVlanMapColon[0]));
+ } else {
+ short start = Short.decode(ceVlanMapColon[0]);
+ short end = Short.decode(ceVlanMapColon[1]);
+ if ((start < 0 || end > 4095)) {
+ return null;
+ } else {
+ for (short i = start; i <= end; i++) {
+ ceVlanSet.add(i);
+ }
+ }
+ }
+ }
+
+ return ceVlanSet.toArray(new Short[ceVlanSet.size()]);
+ }
+
+ /**
+ * Convert an array of vlan ids in to a string representation.
+ * @param vlanArray An array of vlan ids
+ * @return A string representation delimited by commas and colons
+ */
+ public static String vlanListAsString(Short[] vlanArray) {
+ boolean colonPending = false;
+ StringBuilder ceVlanMapBuilder = new StringBuilder();
+ if (vlanArray.length == 0) {
+ return "";
+ } else if (vlanArray.length == 1 && vlanArray[0] == 0) {
+ return "0";
+ }
+
+ //To ensure that there are no repeated or out-of-order elements we must convert to TreeSet
+ TreeSet<Short> vlanSet = new TreeSet<>(Arrays.asList(vlanArray));
+
+ if (vlanSet.first() == 0) {
+ vlanSet.remove(vlanSet.first());
+ }
+ short prev = vlanSet.first();
+ for (short s:vlanSet) {
+ if (s == prev) {
+ ceVlanMapBuilder.append(Short.valueOf(s));
+ continue;
+ } else if (prev == (s - 1)) {
+ colonPending = true;
+ } else {
+ if (colonPending) {
+ ceVlanMapBuilder.append(":" + Short.valueOf(prev));
+ colonPending = false;
+ }
+ ceVlanMapBuilder.append("," + Short.valueOf(s));
+ }
+ prev = s;
+ }
+ if (colonPending) {
+ ceVlanMapBuilder.append(":" + Short.valueOf(prev));
+ }
+
+ return ceVlanMapBuilder.toString();
+ }
+
+ /**
+ * Add an additional vlan id to an existing string representation.
+ * @param existingMap An array of vlan ids
+ * @param newVlan The new vlan ID to add
+ * @return A string representation delimited by commas and colons
+ */
+ public static String addtoCeVlanMap(String existingMap, Short newVlan) {
+ Short[] vlanArray = getVlanSet(existingMap);
+ TreeSet<Short> vlanSet = new TreeSet<>();
+ for (Short vlan:vlanArray) {
+ vlanSet.add(vlan);
+ }
+
+ vlanSet.add(newVlan);
+
+ return vlanListAsString(vlanSet.toArray(new Short[vlanSet.size()]));
+ }
+
+ /**
+ * If a string representation contains a '0' then remove it.
+ *
+ * Zero is an invalid VLAN id, and is used here as a place holder for null. Null can't
+ * be used in the EA1000 device. Once any other vlan ids are added then the zero should
+ * be removed. It is safe to call this method even if no zero is present - the method will
+ * make no change in that case.
+ *
+ * @param existingMap An string representation of vlan ids, possibly containing a zero
+ * @return A string representation delimited by commas and colons without zero
+ */
+ public static String removeZeroIfPossible(String existingMap) {
+ if (existingMap == null || existingMap.isEmpty()) {
+ return "0";
+ } else if (existingMap == "0") {
+ return existingMap;
+ }
+ return removeFromCeVlanMap(existingMap, (short) 0);
+ }
+
+ /**
+ * Remove a vlan id from an existing string representation.
+ * @param existingMap An array of vlan ids
+ * @param vlanRemove The vlan ID to remove
+ * @return A string representation delimited by commas and colons
+ */
+ public static String removeFromCeVlanMap(String existingMap, Short vlanRemove) {
+ Short[] vlanArray = getVlanSet(existingMap);
+ TreeSet<Short> vlanSet = new TreeSet<>();
+ for (Short vlan:vlanArray) {
+ if (vlan.shortValue() != vlanRemove.shortValue()) {
+ vlanSet.add(vlan);
+ }
+ }
+
+ return vlanListAsString(vlanSet.toArray(new Short[vlanSet.size()]));
+ }
+
+ /**
+ * Combine vlan ids from two existing string representations.
+ *
+ * If there are overlapping elements and ranges, these are consolidated in to one.
+ *
+ * @param set1 A string containing a set of vlan ids
+ * @param set2 A string containing a set of vlan ids
+ * @return A string representation delimited by commas and colons
+ */
+ public static String combineVlanSets(String set1, String set2) {
+ Short[] set1Array = getVlanSet(set1);
+ Short[] set2Array = getVlanSet(set2);
+ return vlanListAsString((Short[]) ArrayUtils.addAll(set1Array, set2Array));
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java
new file mode 100644
index 0000000..275dc25
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/IetfYangTypesUtils.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
+
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.DateAndTime;
+
+/**
+ * A utility class to change various YANG types to general purpose classes.
+ */
+public final class IetfYangTypesUtils {
+ private IetfYangTypesUtils() {
+ //Hiding the public constructor for this utility class
+ }
+
+ /**
+ * Convert from Date and Time in a ietf-yang-types format to the Java Time API.
+ * @param dateAndTime A date and time from a YANG object
+ * @return A Date and Time with a Time Zone offset
+ */
+ public static OffsetDateTime fromYangDateTime(DateAndTime dateAndTime) {
+ return OffsetDateTime.parse(dateAndTime.toString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ }
+
+ /**
+ * Convert a from Date and Time in a ietf-yang-types format to the Java Time API and rezone to a given Time Zone.
+ * @param dateAndTime A date and time from a YANG object
+ * @param zoneId The time zone to rezone the time and date to
+ * @return The rezoned time and date
+ */
+ public static ZonedDateTime fromYangDateTimeZoned(DateAndTime dateAndTime, ZoneId zoneId) {
+ return OffsetDateTime.parse(dateAndTime.toString(),
+ DateTimeFormatter.ISO_OFFSET_DATE_TIME).atZoneSameInstant(zoneId);
+ }
+
+ /**
+ * Convert a from Date and Time in a ietf-yang-types format to the Java Time API rezoned to the local Time Zone.
+ * @param dateAndTime A date and time from a YANG object
+ * @return The date and time in the zone of this local machine
+ */
+ public static LocalDateTime fromYangDateTimeToLocal(DateAndTime dateAndTime) {
+ OffsetDateTime odt = OffsetDateTime.parse(dateAndTime.toString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+
+ return LocalDateTime.ofInstant(odt.toInstant(), ZoneId.systemDefault());
+ }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java
new file mode 100644
index 0000000..0c03c46
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for general utilities and helpers.
+ */
+package org.onosproject.drivers.microsemi.yang.utils;
\ No newline at end of file