Separating creating BW profiles from applying BW profiles and some other fixes
- Adding new createBandwidthProfiles() method in CarrierEthernetProvisioner, called before forwarding establishment
- Adding meter instruction in FilterTreatment so that it can be used if needed
- Do not explicitly apply meters to NETCONF devices (assuming it has already been done during forwarding establishment)
- Improving completers for addition/removal of UNIs/LTPs
- Remove UNIs/LTPs from removedUniSet/removedLtpSet when they are added after having first been removed
- Refactoring applyBandwidthProfileResources() to apply meter on installed flowRule which pushes the FC vlanId on UNI port
- Some Javadoc corrections
- Fixing potential NPE in addEcNi() of CarrierEthernetUni.java
- Fixes based on Patchset 1 comments
Change-Id: I824482d9469e8f30df866602c882ff7ec12117f9
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetEnni.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetEnni.java
index 68886f5..f9d99ac 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetEnni.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetEnni.java
@@ -30,8 +30,8 @@
/**
* Representation of a Carrier Ethernet ENNI.
* Class can be used in different two ways:
- * 1. As a global ENNI descriptor containing one or more BW profiles
- * 2. As a service-specific ENNI descriptor containing a single S-VLAN tag and including a type (e.g. hub, spoke)
+ * 1. As a global ENNI descriptor containing one or more S-VLAN tags
+ * 2. As a service-specific ENNI descriptor containing a single S-VLAN tag and including a role (e.g. hub, spoke)
*/
public class CarrierEthernetEnni extends CarrierEthernetNetworkInterface <CarrierEthernetEnni> {
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetInni.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetInni.java
index 64c8f4f..68e2caa 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetInni.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetInni.java
@@ -31,8 +31,8 @@
/**
* Representation of a Carrier Ethernet INNI.
* Class can be used in different two ways:
- * 1. As a global INNI descriptor containing one or more BW profiles
- * 2. As a service-specific INNI descriptor containing a single S-VLAN tag and including a type (e.g. hub, spoke)
+ * 1. As a global INNI descriptor containing one or more S-VLAN tags
+ * 2. As a service-specific INNI descriptor containing a single S-VLAN tag and including a role (e.g. hub, spoke)
*/
public class CarrierEthernetInni extends CarrierEthernetNetworkInterface <CarrierEthernetInni> {
@@ -68,6 +68,7 @@
Bandwidth usedCapacity) {
super(connectPoint, Type.INNI, uniCfgId);
+
// TODO: Check for null
this.role = role;
this.sVlanIdSet = Sets.newConcurrentHashSet();
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetLogicalTerminationPoint.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetLogicalTerminationPoint.java
index cd4ccef..ca2f54e 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetLogicalTerminationPoint.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetLogicalTerminationPoint.java
@@ -175,9 +175,9 @@
}
/**
- * Returns LTP role - applicable only to EVC- or FC-specific LTPs.
+ * Sets LTP role - applicable only to EVC- or FC-specific LTPs.
*
- * @param role he LTP role to set
+ * @param role the LTP role to set
*/
public void setRole(Role role) {
this.role = role;
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetManager.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetManager.java
index a304fd0..a44e78c 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetManager.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetManager.java
@@ -707,9 +707,13 @@
return null;
}
+ // Create BW profiles first so that they will be available if needed during the connectivity phase
+ ceProvisioner.createBandwidthProfiles(fc);
+
ceProvisioner.setupConnectivity(fc);
// If connectivity was not successful, then do not register the FC and do not apply BW profiles
+ // If not, the BW profiles that were created earlier need to be removed
if (fc.state().equals(CarrierEthernetForwardingConstruct.State.ACTIVE)) {
// Apply BWP-related resources (e.g. Meters) to the packet switches
ceProvisioner.applyBandwidthProfiles(fc);
@@ -719,6 +723,8 @@
// Increment the global LTP and corresponding NI refCount
fc.ltpSet().forEach(ltp -> ltpMap.get(ltp.id()).refCount().incrementAndGet());
fcMap.put(fc.id(), fc);
+ } else {
+ ceProvisioner.removeBandwidthProfiles(fc);
}
return fc;
@@ -941,9 +947,11 @@
/**
* Returns all potential UNIs from the topology.
*
+ * @param excludeAdded indicates that UNIs already added in the UNI map should not be in the returned set
+ * @param includeRemoved indicates that UNIs explicitly removed from the UNI map should be in the returned set
* @return set of all potential UNIs in the topology
* */
- public Set<CarrierEthernetUni> getUnisFromTopo() {
+ public Set<CarrierEthernetUni> getUnisFromTopo(boolean excludeAdded, boolean includeRemoved) {
CarrierEthernetUni uni;
Set<CarrierEthernetUni> uniSet = new HashSet<>();
@@ -954,8 +962,10 @@
String cpString = device.id().toString() + "/" + port.number();
ConnectPoint cp = ConnectPoint.deviceConnectPoint(cpString);
uni = generateUni(cp);
- // Check if LTP was generated and whether it's currently removed
- if (uni != null && !removedUniSet.contains(uni.id())) {
+ // Check if UNI was generated and whether it's currently removed
+ if (uni != null
+ && (includeRemoved || !removedUniSet.contains(uni.id()))
+ && (!excludeAdded || !uniMap.containsKey(uni.id()))) {
uniSet.add(uni);
}
}
@@ -1018,8 +1028,12 @@
// FIXME: Assumes LTP and UNI id are the same
if (!ltpMap.containsKey(uni.id())) {
ltpMap.put(uni.id(), new CarrierEthernetLogicalTerminationPoint(uni.id(), uni));
+ // Remove LTP from deleted set
+ removedLtpSet.remove(uni.id());
}
uniMap.put(uni.id(), uni);
+ // Remove UNI from deleted set
+ removedUniSet.remove(uni.id());
return uni;
} else {
return null;
@@ -1028,10 +1042,11 @@
/**
* Returns all potential LTPs from the topology.
- *
+ * @param excludeAdded indicates that LTPs already added in the LTP map should not be in the returned set
+ * @param includeRemoved indicates that LTPs explicitly removed from the LTP map should be in the returned set
* @return set of all potential LTPs in the topology
* */
- public Set<CarrierEthernetLogicalTerminationPoint> getLtpsFromTopo() {
+ public Set<CarrierEthernetLogicalTerminationPoint> getLtpsFromTopo(boolean excludeAdded, boolean includeRemoved) {
CarrierEthernetLogicalTerminationPoint ltp;
Set<CarrierEthernetLogicalTerminationPoint> ltpSet = new HashSet<>();
@@ -1043,7 +1058,9 @@
ConnectPoint cp = ConnectPoint.deviceConnectPoint(cpString);
ltp = generateLtp(cp, null);
// Check if LTP was generated and whether it's currently removed
- if (ltp != null && !removedLtpSet.contains(ltp.id())) {
+ if (ltp != null
+ && (includeRemoved || !removedLtpSet.contains(ltp.id()))
+ && (!excludeAdded || !ltpMap.containsKey(ltp.id()))) {
// Check additionally if associated UNI is currently removed
if (!(ltp.ni() instanceof CarrierEthernetUni) || !removedUniSet.contains(ltp.ni().id())) {
ltpSet.add(ltp);
@@ -1148,9 +1165,12 @@
* */
public CarrierEthernetLogicalTerminationPoint addGlobalLtp(CarrierEthernetLogicalTerminationPoint ltp) {
// If LTP contains a UNI, add it only if it's not already there, else point to the existing UNI
+ // FIXME: Assumes LTP and UNI id are the same
if (ltp.ni() != null && ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
if (!uniMap.containsKey(ltp.ni().id())) {
uniMap.put(ltp.ni().id(), (CarrierEthernetUni) ltp.ni());
+ // Remove UNI from deleted set
+ removedUniSet.remove(ltp.id());
} else {
ltp.setNi(uniMap.get(ltp.ni().id()));
}
@@ -1172,6 +1192,8 @@
}
}
ltpMap.put(ltp.id(), ltp);
+ // Remove LTP from deleted set
+ removedLtpSet.remove(ltp.id());
return ltp;
} else {
return null;
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetOpenFlowPacketNodeManager.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetOpenFlowPacketNodeManager.java
deleted file mode 100644
index 285fe5f..0000000
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetOpenFlowPacketNodeManager.java
+++ /dev/null
@@ -1,479 +0,0 @@
-package org.onosproject.ecord.carrierethernet.app;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-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.FlowRuleService;
-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.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.flowobjective.*;
-import org.onosproject.net.meter.Meter;
-import org.onosproject.net.meter.MeterId;
-import org.onosproject.net.meter.MeterRequest;
-import org.onosproject.net.meter.Band;
-import org.onosproject.net.meter.DefaultBand;
-import org.onosproject.net.meter.MeterService;
-import org.onosproject.net.meter.DefaultMeterRequest;
-import org.onosproject.openflow.controller.Dpid;
-import org.onosproject.openflow.controller.OpenFlowController;
-import org.onosproject.openflow.controller.OpenFlowSwitch;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.Iterator;
-import java.util.ListIterator;
-
-import org.apache.commons.lang3.tuple.Pair;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Class used to control Carrier Ethernet nodes according to the OpenFlow (1.3 and above) protocol.
- */
-@Component(immediate = true)
-@Service (value = CarrierEthernetOpenFlowPacketNodeManager.class)
-public class CarrierEthernetOpenFlowPacketNodeManager extends CarrierEthernetPacketNodeManager {
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected FlowRuleService flowRuleService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected MeterService meterService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected FlowObjectiveService flowObjectiveService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected OpenFlowController controller;
-
- private final Logger log = getLogger(getClass());
-
- private static ApplicationId appId;
-
- private static final int PRIORITY = 50000;
-
- // TODO: Below maps to be replaced by the meter ids and flow objectives associated with each CE Intent
-
- // FIXME: Replace with Pair<DeviceId, MeterId>
- private final Map<String, Set<DeviceMeterId>> deviceMeterIdMap = new HashMap<>();
- private final Map<String, LinkedList<Pair<DeviceId, Objective>>> flowObjectiveMap = new HashMap();
-
- @Activate
- protected void activate() {
- appId = coreService.registerApplication("org.onosproject.ecord.carrierethernet");
- }
-
- @Deactivate
- protected void deactivate() {}
-
- @Override
- public void setNodeForwarding(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface ingressNi,
- Set<CarrierEthernetNetworkInterface> egressNiSet) {
-
- if (ingressNi == null || egressNiSet.isEmpty()) {
- log.error("There needs to be at least one ingress and one egress NI to set forwarding.");
- return;
- }
-
- flowObjectiveMap.putIfAbsent(fc.id(), new LinkedList<>());
-
- // TODO: Get created FlowObjectives from this method
- createFlowObjectives(fc, ingressNi, egressNiSet);
- }
-
- /**
- * Creates and submits FlowObjectives depending on role of the device in the FC and ingress/egress NI types.
- *
- * @param fc the FC representation
- * @param ingressNi the ingress NI (UNI, INNI, ENNI or GENERIC) of the EVC for this forwarding segment
- * @param egressNiSet the set of egress NIs (UNI, INNI, ENNI or GENERIC) of the EVC for this forwarding segment
- */
- private void createFlowObjectives(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface ingressNi,
- Set<CarrierEthernetNetworkInterface> egressNiSet) {
-
- /////////////////////////////////////////
- // Prepare and submit filtering objective
- /////////////////////////////////////////
-
- FilteringObjective.Builder filteringObjectiveBuilder = DefaultFilteringObjective.builder()
- .permit().fromApp(appId)
- .withPriority(PRIORITY)
- .withKey(Criteria.matchInPort(ingressNi.cp().port()));
-
- TrafficTreatment.Builder filterTreatmentBuilder = DefaultTrafficTreatment.builder();
-
- // In general, nodes would match on the VLAN tag assigned to the EVC/FC
- Criterion filterVlanIdCriterion = Criteria.matchVlanId(fc.vlanId());
-
- if ((ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.INNI))
- || (ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.ENNI)) ) {
- // TODO: Check TPID? Also: Is is possible to receive untagged pkts at an INNI/ENNI?
- // Source node of an FC should match on S-TAG if it's an INNI/ENNI
- filterVlanIdCriterion = Criteria.matchVlanId(ingressNi.sVlanId());
- // Translate S-TAG to the one used in the current FC
- filterTreatmentBuilder.setVlanId(fc.vlanId());
- } else if (ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- // Source node of an FC should match on CE-VLAN ID (if present) if it's a UNI
- filterVlanIdCriterion = Criteria.matchVlanId(ingressNi.ceVlanId());
- // Push S-TAG of current FC on top of existing CE-VLAN ID
- filterTreatmentBuilder.pushVlan().setVlanId(fc.vlanId());
- }
-
- filteringObjectiveBuilder.addCondition(filterVlanIdCriterion);
-
- // Do not add meta if there are no instructions (i.e. if not first)
- if (!(ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.GENERIC))) {
- filteringObjectiveBuilder.withMeta(filterTreatmentBuilder.build());
- }
-
- flowObjectiveService.filter(ingressNi.cp().deviceId(), filteringObjectiveBuilder.add());
- flowObjectiveMap.get(fc.id()).addFirst(Pair.of(ingressNi.cp().deviceId(), filteringObjectiveBuilder.add()));
-
- ////////////////////////////////////////////////////
- // Prepare and submit next and forwarding objectives
- ////////////////////////////////////////////////////
-
- TrafficSelector fwdSelector = DefaultTrafficSelector.builder()
- .matchVlanId(fc.vlanId())
- .matchInPort(ingressNi.cp().port())
- .matchEthType(Ethernet.TYPE_IPV4)
- .build();
-
- Integer nextId = flowObjectiveService.allocateNextId();
-
- // Setting higher priority to fwd/next objectives to bypass filter in case of match conflict in OVS switches
- NextObjective.Builder nextObjectiveBuider = DefaultNextObjective.builder()
- .fromApp(appId)
- .makePermanent()
- .withType(NextObjective.Type.BROADCAST)
- .withPriority(PRIORITY + 1)
- .withMeta(fwdSelector)
- .withId(nextId);
-
- egressNiSet.forEach(egressNi -> {
- // TODO: Check if ingressNi and egressNi are on the same device?
- TrafficTreatment.Builder nextTreatmentBuilder = DefaultTrafficTreatment.builder();
- // If last NI in FC is not UNI, keep the existing S-TAG - it will be translated at the entrance of the next FC
- if (egressNi.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- nextTreatmentBuilder.popVlan();
- }
- Instruction outInstruction = Instructions.createOutput(egressNi.cp().port());
- nextTreatmentBuilder.add(outInstruction);
- nextObjectiveBuider.addTreatment(nextTreatmentBuilder.build());
- });
-
- NextObjective nextObjective = nextObjectiveBuider.add();
-
- // Setting higher priority to fwd/next objectives to bypass filter in case of match conflict in OVS switches
- ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
- .fromApp(appId)
- .makePermanent()
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .withPriority(PRIORITY + 1)
- .withSelector(fwdSelector)
- .nextStep(nextId)
- .add();
-
- flowObjectiveService.next(ingressNi.cp().deviceId(), nextObjective);
- // Add all NextObjectives at the end of the list so that they will be removed last
- flowObjectiveMap.get(fc.id()).addLast(Pair.of(ingressNi.cp().deviceId(), nextObjective));
-
- flowObjectiveService.forward(ingressNi.cp().deviceId(), forwardingObjective);
- flowObjectiveMap.get(fc.id()).addFirst(Pair.of(ingressNi.cp().deviceId(), forwardingObjective));
- }
-
- @Override
- void applyBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni) {
-
- Dpid dpid = Dpid.dpid(uni.cp().deviceId().uri());
- OpenFlowSwitch sw = controller.getSwitch(dpid);
-
- // Do not apply meters to OFDPA 2.0 switches since they are not currently supported
- if (sw.softwareDescription().equals("OF-DPA 2.0")) {
- return;
- }
-
- // Create meters and add them to global MeterId map
- Set<DeviceMeterId> deviceMeterIdSet = deviceMeterIdMap.get(fc.id());
- if (deviceMeterIdSet == null) {
- deviceMeterIdSet = new HashSet<>();
- }
- deviceMeterIdSet.addAll(createMeters(uni));
- deviceMeterIdMap.put(fc.id(), deviceMeterIdSet);
-
- // Apply meters to already installed flows
-
- Set<FlowRule> newFlowRuleSet = new HashSet<>();
-
- // Get flow rules belonging to service and having as in_port the UNI connect point
-
- // FIXME: Check for flow rules associated with evcId
- for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
- PortCriterion portCriterion = (PortCriterion) flowRule.selector().getCriterion(Criterion.Type.IN_PORT);
- VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) flowRule.selector()
- .getCriterion(Criterion.Type.VLAN_VID);
- if (portCriterion == null || vlanIdCriterion == null) {
- continue;
- }
- PortNumber inPort = portCriterion.port();
- VlanId flowInVlanId = vlanIdCriterion.vlanId();
- if (inPort == null || flowInVlanId == null) {
- continue;
- }
- ConnectPoint flowInCp = new ConnectPoint(flowRule.deviceId(), inPort);
- // FIXME: Maybe check also if there is a group action?
- // TODO: Check the vlanIds of all FCs comprising the EVC????
- if (uni.cp().equals(flowInCp) && fc.vlanId().equals(flowInVlanId)) {
- // Need to add to the flow the meters associated with the same device
- Set<DeviceMeterId> tmpDeviceMeterIdSet = new HashSet<>();
- deviceMeterIdMap.get(fc.id()).forEach(deviceMeterId -> {
- if (deviceMeterId.deviceId().equals(flowRule.deviceId())) {
- tmpDeviceMeterIdSet.add(deviceMeterId);
- }
- });
- // Modify and submit flow rule only if there are meters to add
- if (!tmpDeviceMeterIdSet.isEmpty()) {
- FlowRule newFlowRule = addMetersToFlowRule(flowRule, tmpDeviceMeterIdSet);
- flowRuleService.applyFlowRules(newFlowRule);
- newFlowRuleSet.add(newFlowRule);
- } else {
- newFlowRuleSet.add(flowRule);
- }
- } else {
- newFlowRuleSet.add(flowRule);
- }
- }
- }
-
- /**
- * Creates and submits a meter with the required bands for a UNI.
- *
- * @param uni the UNI descriptor
- * @return set of meter ids of the meters created
- */
- private Set<DeviceMeterId> createMeters(CarrierEthernetUni uni) {
-
- // TODO: Check if meter already exists before adding it?
-
- Set<DeviceMeterId> deviceMeterIdSet = new HashSet<>();
-
- long longCir = (long) (uni.bwp().cir().bps() / 8000);
- long longEir = (long) (uni.bwp().eir().bps() / 8000);
-
- MeterRequest.Builder meterRequestBuilder;
- Meter meter;
- Band.Builder bandBuilder;
-
- Set<Band> bandSet = new HashSet<>();
-
- // If EIR is zero do not create the REMARK meter
- if (longEir != 0) {
- // Mark frames that exceed CIR as Best Effort
- bandBuilder = DefaultBand.builder()
- .ofType(Band.Type.REMARK)
- .withRate(longCir)
- .dropPrecedence((short) 0);
-
- if (uni.bwp().cbs() != 0) {
- bandBuilder.burstSize(uni.bwp().cbs());
- }
-
- bandSet.add(bandBuilder.build());
- }
-
- // If CIR is zero do not create the DROP meter
- if (longCir != 0) {
- // Drop all frames that exceed CIR + EIR
- bandBuilder = DefaultBand.builder()
- .ofType(Band.Type.DROP)
- .withRate(longCir + longEir);
-
- if (uni.bwp().cbs() != 0 || uni.bwp().ebs() != 0) {
- // FIXME: Use CBS and EBS correctly according to MEF specs
- bandBuilder.burstSize(uni.bwp().cbs() + uni.bwp().ebs());
- }
-
- bandSet.add(bandBuilder.build());
- }
-
- // Create meter only if at least one band was created
- if (!bandSet.isEmpty()) {
- meterRequestBuilder = DefaultMeterRequest.builder()
- .forDevice(uni.cp().deviceId())
- .fromApp(appId)
- .withUnit(Meter.Unit.KB_PER_SEC)
- .withBands(bandSet);
-
- if (uni.bwp().cbs() != 0 || uni.bwp().ebs() != 0) {
- meterRequestBuilder.burst();
- }
-
- meter = meterService.submit(meterRequestBuilder.add());
- deviceMeterIdSet.add(new DeviceMeterId(uni.cp().deviceId(), meter.id()));
- }
-
- return deviceMeterIdSet;
- }
-
- private FlowRule addMetersToFlowRule(FlowRule flowRule, Set<DeviceMeterId> deviceMeterIdSet) {
-
- // FIXME: Refactor to use only single meter
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
- .builder(flowRule.treatment());
-
- deviceMeterIdSet.forEach(deviceMeterId -> {
- tBuilder.meter(deviceMeterId.meterId());
- });
-
- return createFlowRule(flowRule.deviceId(), flowRule.priority(),
- flowRule.selector(), tBuilder.build(), flowRule.tableId());
- }
-
- @Override
- void removeBandwidthProfileResources(String fcId, CarrierEthernetUni uni) {
- removeMeters(fcId, uni);
- }
-
- /**
- * Removes the meters associated with a specific UNI of an FC.
- *
- * @param fcId the EVC ID
- * @param uni the UNI descriptor
- * */
- private void removeMeters(String fcId, CarrierEthernetUni uni) {
-
- Set<DeviceMeterId> newDeviceMeterIdSet = deviceMeterIdMap.get(fcId);
- DeviceMeterId tmpDeviceMeterId;
-
- Collection<Meter> meters = meterService.getMeters(uni.cp().deviceId());
-
- Iterator<Meter> it = meters.iterator();
- while (it.hasNext()) {
- Meter meter = it.next();
- tmpDeviceMeterId = new DeviceMeterId(uni.cp().deviceId(), meter.id());
- if (meter.appId().equals(appId) &&
- deviceMeterIdMap.get(fcId).contains(tmpDeviceMeterId)) {
- MeterRequest.Builder mBuilder;
- mBuilder = DefaultMeterRequest.builder()
- .fromApp(meter.appId())
- .forDevice(meter.deviceId())
- .withUnit(meter.unit())
- .withBands(meter.bands());
- if (uni.bwp().cbs() != 0 || uni.bwp().ebs() != 0) {
- mBuilder.burst();
- }
- meterService.withdraw(mBuilder.remove(), meter.id());
- newDeviceMeterIdSet.remove(tmpDeviceMeterId);
- }
- }
-
- deviceMeterIdMap.put(fcId, newDeviceMeterIdSet);
- }
-
- @Override
- void removeAllForwardingResources(CarrierEthernetForwardingConstruct fc) {
- removeFlowObjectives(fc.id());
- }
-
- /**
- * Removes all flow objectives installed by the application which are associated with a specific FC.
- *
- * @param fcId the FC id
- * */
- private void removeFlowObjectives(String fcId) {
- // Note: A Flow Rule cannot be shared by multiple FCs due to different VLAN or CE-VLAN ID match.
- List<Pair<DeviceId, Objective>> flowObjectiveList = flowObjectiveMap.remove(fcId);
- // NextObjectives will be removed after all other Objectives
- ListIterator<Pair<DeviceId, Objective>> objIter = flowObjectiveList.listIterator();
- while (objIter.hasNext()) {
- Pair<DeviceId, Objective> deviceObjectivePair = objIter.next();
- flowObjectiveService.apply(deviceObjectivePair.getLeft(), deviceObjectivePair.getRight().copy().remove());
- }
-
- }
-
- // FIXME: Replace with Pair<DeviceId, MeterId>
- /**
- * Utility class to compensate for the fact that MeterIds are not unique system-wide.
- * */
- class DeviceMeterId {
- private DeviceId deviceId;
- private MeterId meterId;
-
- DeviceMeterId(DeviceId deviceId, MeterId meterId) {
- this.deviceId = deviceId;
- this.meterId = meterId;
- }
-
- public DeviceId deviceId() {
- return deviceId;
- }
-
- public MeterId meterId() {
- return meterId;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(deviceId, meterId);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj instanceof DeviceMeterId) {
- DeviceMeterId other = (DeviceMeterId) obj;
- if (this.deviceId().equals(other.deviceId()) && this.meterId().equals(other.meterId())) {
- return true;
- }
- }
- return false;
- }
- }
-
- private FlowRule createFlowRule(DeviceId deviceId, int priority,
- TrafficSelector selector, TrafficTreatment treatment, int tableId) {
- return DefaultFlowRule.builder()
- .fromApp(appId)
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(priority)
- .withSelector(selector)
- .withTreatment(treatment)
- .forTable(tableId)
- .build();
- }
-
-}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetPacketNodeManager.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetPacketNodeManager.java
index b34d12a..f03b912 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetPacketNodeManager.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetPacketNodeManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Open Networking Laboratory
+ * 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.
@@ -15,20 +15,505 @@
*/
package org.onosproject.ecord.carrierethernet.app;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+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.FlowRuleService;
+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.PortCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flowobjective.*;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.net.meter.MeterRequest;
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.DefaultBand;
+import org.onosproject.net.meter.MeterService;
+import org.onosproject.net.meter.DefaultMeterRequest;
+import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.OpenFlowController;
+import org.onosproject.openflow.controller.OpenFlowSwitch;
+import org.slf4j.Logger;
+
+import java.util.Collection;
+import java.util.Objects;
import java.util.Set;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import org.apache.commons.lang3.tuple.Pair;
+import static org.slf4j.LoggerFactory.getLogger;
/**
- * Abstraction of a class used to control Carrier Ethernet nodes according to their control protocol.
+ * Class used to control Carrier Ethernet nodes according to the OpenFlow (1.3 and above) protocol.
*/
-public abstract class CarrierEthernetPacketNodeManager {
+@Component(immediate = true)
+@Service (value = CarrierEthernetPacketNodeService.class)
+public class CarrierEthernetPacketNodeManager implements CarrierEthernetPacketNodeService {
- abstract void setNodeForwarding(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface srcNi,
- Set<CarrierEthernetNetworkInterface> dstNiSet);
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
- abstract void applyBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni);
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowRuleService flowRuleService;
- abstract void removeBandwidthProfileResources(String fcId, CarrierEthernetUni uni);
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MeterService meterService;
- abstract void removeAllForwardingResources(CarrierEthernetForwardingConstruct fc);
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenFlowController controller;
+
+ private final Logger log = getLogger(getClass());
+
+ private static ApplicationId appId;
+
+ private static final int PRIORITY = 50000;
+
+ // TODO: Below maps to be replaced by the meter ids and flow objectives associated with each CE Intent
+
+ // FIXME: Replace with Pair<DeviceId, MeterId>
+ private final Map<String, Set<DeviceMeterId>> deviceMeterIdMap = new HashMap<>();
+ private final Map<String, LinkedList<Pair<DeviceId, Objective>>> flowObjectiveMap = new HashMap();
+
+ @Activate
+ protected void activate() {
+ appId = coreService.registerApplication("org.onosproject.ecord.carrierethernet");
+ }
+
+ @Deactivate
+ protected void deactivate() {}
+
+ @Override
+ public void setNodeForwarding(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface ingressNi,
+ Set<CarrierEthernetNetworkInterface> egressNiSet) {
+
+ if (ingressNi == null || egressNiSet.isEmpty()) {
+ log.error("There needs to be at least one ingress and one egress NI to set forwarding.");
+ return;
+ }
+
+ flowObjectiveMap.putIfAbsent(fc.id(), new LinkedList<>());
+
+ // TODO: Get created FlowObjectives from this method
+ createFlowObjectives(fc, ingressNi, egressNiSet);
+ }
+
+ /**
+ * Creates and submits FlowObjectives depending on role of the device in the FC and ingress/egress NI types.
+ *
+ * @param fc the FC representation
+ * @param ingressNi the ingress NI (UNI, INNI, ENNI or GENERIC) of the EVC for this forwarding segment
+ * @param egressNiSet the set of egress NIs (UNI, INNI, ENNI or GENERIC) of the EVC for this forwarding segment
+ */
+ private void createFlowObjectives(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface ingressNi,
+ Set<CarrierEthernetNetworkInterface> egressNiSet) {
+
+ /////////////////////////////////////////
+ // Prepare and submit filtering objective
+ /////////////////////////////////////////
+
+ FilteringObjective.Builder filteringObjectiveBuilder = DefaultFilteringObjective.builder()
+ .permit().fromApp(appId)
+ .withPriority(PRIORITY)
+ .withKey(Criteria.matchInPort(ingressNi.cp().port()));
+
+ TrafficTreatment.Builder filterTreatmentBuilder = DefaultTrafficTreatment.builder();
+
+ // In general, nodes would match on the VLAN tag assigned to the EVC/FC
+ Criterion filterVlanIdCriterion = Criteria.matchVlanId(fc.vlanId());
+
+ if ((ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.INNI))
+ || (ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.ENNI)) ) {
+ // TODO: Check TPID? Also: Is is possible to receive untagged pkts at an INNI/ENNI?
+ // Source node of an FC should match on S-TAG if it's an INNI/ENNI
+ filterVlanIdCriterion = Criteria.matchVlanId(ingressNi.sVlanId());
+ // Translate S-TAG to the one used in the current FC
+ filterTreatmentBuilder.setVlanId(fc.vlanId());
+ } else if (ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ // Source node of an FC should match on CE-VLAN ID (if present) if it's a UNI
+ filterVlanIdCriterion = Criteria.matchVlanId(ingressNi.ceVlanId());
+ // Obtain related Meter (if it exists) and add it in the treatment in case it may be used
+ deviceMeterIdMap.get(fc.id()).forEach(deviceMeterId -> {
+ if (deviceMeterId.deviceId().equals(ingressNi.cp().deviceId())) {
+ filterTreatmentBuilder.meter(deviceMeterId.meterId());
+ }
+ });
+ // Push S-TAG of current FC on top of existing CE-VLAN ID
+ filterTreatmentBuilder.pushVlan().setVlanId(fc.vlanId());
+ }
+
+ filteringObjectiveBuilder.addCondition(filterVlanIdCriterion);
+
+ // Do not add meta if there are no instructions (i.e. if not first)
+ if (!(ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.GENERIC))) {
+ filteringObjectiveBuilder.withMeta(filterTreatmentBuilder.build());
+ }
+
+ flowObjectiveService.filter(ingressNi.cp().deviceId(), filteringObjectiveBuilder.add());
+ flowObjectiveMap.get(fc.id()).addFirst(Pair.of(ingressNi.cp().deviceId(), filteringObjectiveBuilder.add()));
+
+ ////////////////////////////////////////////////////
+ // Prepare and submit next and forwarding objectives
+ ////////////////////////////////////////////////////
+
+ TrafficSelector fwdSelector = DefaultTrafficSelector.builder()
+ .matchVlanId(fc.vlanId())
+ .matchInPort(ingressNi.cp().port())
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .build();
+
+ Integer nextId = flowObjectiveService.allocateNextId();
+
+ // Setting higher priority to fwd/next objectives to bypass filter in case of match conflict in OVS switches
+ NextObjective.Builder nextObjectiveBuider = DefaultNextObjective.builder()
+ .fromApp(appId)
+ .makePermanent()
+ .withType(NextObjective.Type.BROADCAST)
+ .withPriority(PRIORITY + 1)
+ .withMeta(fwdSelector)
+ .withId(nextId);
+
+ egressNiSet.forEach(egressNi -> {
+ // TODO: Check if ingressNi and egressNi are on the same device?
+ TrafficTreatment.Builder nextTreatmentBuilder = DefaultTrafficTreatment.builder();
+ // If last NI in FC is not UNI, keep the existing S-TAG - it will be translated at the entrance of the next FC
+ if (egressNi.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ nextTreatmentBuilder.popVlan();
+ }
+ Instruction outInstruction = Instructions.createOutput(egressNi.cp().port());
+ nextTreatmentBuilder.add(outInstruction);
+ nextObjectiveBuider.addTreatment(nextTreatmentBuilder.build());
+ });
+
+ NextObjective nextObjective = nextObjectiveBuider.add();
+
+ // Setting higher priority to fwd/next objectives to bypass filter in case of match conflict in OVS switches
+ ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
+ .fromApp(appId)
+ .makePermanent()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(PRIORITY + 1)
+ .withSelector(fwdSelector)
+ .nextStep(nextId)
+ .add();
+
+ flowObjectiveService.next(ingressNi.cp().deviceId(), nextObjective);
+ // Add all NextObjectives at the end of the list so that they will be removed last
+ flowObjectiveMap.get(fc.id()).addLast(Pair.of(ingressNi.cp().deviceId(), nextObjective));
+
+ flowObjectiveService.forward(ingressNi.cp().deviceId(), forwardingObjective);
+ flowObjectiveMap.get(fc.id()).addFirst(Pair.of(ingressNi.cp().deviceId(), forwardingObjective));
+ }
+
+ @Override
+ public void createBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni) {
+ // Create meters and add them to global MeterId map
+ Set<DeviceMeterId> deviceMeterIdSet = deviceMeterIdMap.get(fc.id());
+ if (deviceMeterIdSet == null) {
+ deviceMeterIdSet = new HashSet<>();
+ }
+ deviceMeterIdSet.addAll(createMeters(uni));
+ deviceMeterIdMap.put(fc.id(), deviceMeterIdSet);
+ }
+
+ @Override
+ public void applyBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni) {
+
+ DeviceId deviceId = uni.cp().deviceId();
+
+ // Do not apply meters to NETCONF-controlled switches here since they should have been applied in the pipeline
+ // FIXME: Is there a better way to check this?
+ if (deviceId.uri().getScheme().equals("netconf")) {
+ return;
+ }
+
+ Dpid dpid = Dpid.dpid(deviceId.uri());
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
+
+ // Do not apply meters to OFDPA 2.0 switches since they are not currently supported
+ if (sw.softwareDescription().equals("OF-DPA 2.0")) {
+ return;
+ }
+
+ // Get installed flows with the same appId/deviceId with IN_PORT = UNI port which push the FC vlanId
+ List<FlowRule> flowRuleList =
+ StreamSupport.stream(flowRuleService.getFlowEntries(deviceId).spliterator(), false)
+ .filter(flowRule -> flowRule.appId() == appId.id()
+ && getPushedVlanFromTreatment(flowRule.treatment()).equals(fc.vlanId())
+ && getInPortNumberFromSelector(flowRule.selector()).equals(uni.cp().port()))
+ .collect(Collectors.toList());
+
+ // Apply meters to flows
+ for (FlowRule flowRule : flowRuleList) {
+ // Need to add to the flow the meters associated with the same device
+ Set<DeviceMeterId> tmpDeviceMeterIdSet = new HashSet<>();
+ deviceMeterIdMap.get(fc.id()).forEach(deviceMeterId -> {
+ if (deviceMeterId.deviceId().equals(flowRule.deviceId())) {
+ tmpDeviceMeterIdSet.add(deviceMeterId);
+ }
+ });
+ // Modify and submit flow rule only if there are meters to add
+ if (!tmpDeviceMeterIdSet.isEmpty()) {
+ FlowRule newFlowRule = addMetersToFlowRule(flowRule, tmpDeviceMeterIdSet);
+ flowRuleService.applyFlowRules(newFlowRule);
+ }
+ }
+ }
+
+ private VlanId getPushedVlanFromTreatment(TrafficTreatment treatment) {
+ boolean pushVlan = false;
+ VlanId pushedVlan = null;
+ for (Instruction instruction : treatment.allInstructions()) {
+ if (instruction.type().equals(Instruction.Type.L2MODIFICATION)) {
+ L2ModificationInstruction l2ModInstr = (L2ModificationInstruction) instruction;
+ if (l2ModInstr.subtype().equals(L2ModificationInstruction.L2SubType.VLAN_PUSH)) {
+ pushVlan = true;
+ } else if (l2ModInstr.subtype().equals(L2ModificationInstruction.L2SubType.VLAN_ID) && pushVlan) {
+ pushedVlan = ((L2ModificationInstruction.ModVlanIdInstruction) instruction).vlanId();
+ }
+ }
+ }
+ return pushedVlan != null ? pushedVlan : VlanId.NONE;
+ }
+
+ private PortNumber getInPortNumberFromSelector(TrafficSelector selector) {
+ for (Criterion criterion : selector.criteria()) {
+ if (criterion.type().equals(Criterion.Type.IN_PORT)) {
+ return ((PortCriterion) criterion).port();
+ }
+ }
+ return PortNumber.portNumber("-1");
+ }
+
+ /**
+ * Creates and submits a meter with the required bands for a UNI.
+ *
+ * @param uni the UNI descriptor
+ * @return set of meter ids of the meters created
+ */
+ private Set<DeviceMeterId> createMeters(CarrierEthernetUni uni) {
+
+ // TODO: Check if meter already exists before adding it?
+
+ Set<DeviceMeterId> deviceMeterIdSet = new HashSet<>();
+
+ long longCir = (long) (uni.bwp().cir().bps() / 8000);
+ long longEir = (long) (uni.bwp().eir().bps() / 8000);
+
+ MeterRequest.Builder meterRequestBuilder;
+ Meter meter;
+ Band.Builder bandBuilder;
+
+ Set<Band> bandSet = new HashSet<>();
+
+ // If EIR is zero do not create the REMARK meter
+ if (longEir != 0) {
+ // Mark frames that exceed CIR as Best Effort
+ bandBuilder = DefaultBand.builder()
+ .ofType(Band.Type.REMARK)
+ .withRate(longCir)
+ .dropPrecedence((short) 0);
+
+ if (uni.bwp().cbs() != 0) {
+ bandBuilder.burstSize(uni.bwp().cbs());
+ }
+
+ bandSet.add(bandBuilder.build());
+ }
+
+ // If CIR is zero do not create the DROP meter
+ if (longCir != 0) {
+ // Drop all frames that exceed CIR + EIR
+ bandBuilder = DefaultBand.builder()
+ .ofType(Band.Type.DROP)
+ .withRate(longCir + longEir);
+
+ if (uni.bwp().cbs() != 0 || uni.bwp().ebs() != 0) {
+ // FIXME: Use CBS and EBS correctly according to MEF specs
+ bandBuilder.burstSize(uni.bwp().cbs() + uni.bwp().ebs());
+ }
+
+ bandSet.add(bandBuilder.build());
+ }
+
+ // Create meter only if at least one band was created
+ if (!bandSet.isEmpty()) {
+ meterRequestBuilder = DefaultMeterRequest.builder()
+ .forDevice(uni.cp().deviceId())
+ .fromApp(appId)
+ .withUnit(Meter.Unit.KB_PER_SEC)
+ .withBands(bandSet);
+
+ if (uni.bwp().cbs() != 0 || uni.bwp().ebs() != 0) {
+ meterRequestBuilder.burst();
+ }
+
+ meter = meterService.submit(meterRequestBuilder.add());
+ deviceMeterIdSet.add(new DeviceMeterId(uni.cp().deviceId(), meter.id()));
+ }
+
+ return deviceMeterIdSet;
+ }
+
+ private FlowRule addMetersToFlowRule(FlowRule flowRule, Set<DeviceMeterId> deviceMeterIdSet) {
+
+ // FIXME: Refactor to use only single meter
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
+ .builder(flowRule.treatment());
+
+ deviceMeterIdSet.forEach(deviceMeterId -> {
+ tBuilder.meter(deviceMeterId.meterId()).
+ transition(flowRule.treatment().tableTransition().tableId());
+ });
+
+ return createFlowRule(flowRule.deviceId(), flowRule.priority(),
+ flowRule.selector(), tBuilder.build(), flowRule.tableId());
+ }
+
+ @Override
+ public void removeBandwidthProfileResources(String fcId, CarrierEthernetUni uni) {
+ removeMeters(fcId, uni);
+ }
+
+ /**
+ * Removes the meters associated with a specific UNI of an FC.
+ *
+ * @param fcId the EVC ID
+ * @param uni the UNI descriptor
+ * */
+ private void removeMeters(String fcId, CarrierEthernetUni uni) {
+
+ Set<DeviceMeterId> newDeviceMeterIdSet = deviceMeterIdMap.get(fcId);
+ DeviceMeterId tmpDeviceMeterId;
+
+ Collection<Meter> meters = meterService.getMeters(uni.cp().deviceId());
+
+ Iterator<Meter> it = meters.iterator();
+ while (it.hasNext()) {
+ Meter meter = it.next();
+ tmpDeviceMeterId = new DeviceMeterId(uni.cp().deviceId(), meter.id());
+ if (meter.appId().equals(appId) &&
+ deviceMeterIdMap.get(fcId).contains(tmpDeviceMeterId)) {
+ MeterRequest.Builder mBuilder;
+ mBuilder = DefaultMeterRequest.builder()
+ .fromApp(meter.appId())
+ .forDevice(meter.deviceId())
+ .withUnit(meter.unit())
+ .withBands(meter.bands());
+ if (uni.bwp().cbs() != 0 || uni.bwp().ebs() != 0) {
+ mBuilder.burst();
+ }
+ meterService.withdraw(mBuilder.remove(), meter.id());
+ newDeviceMeterIdSet.remove(tmpDeviceMeterId);
+ }
+ }
+
+ deviceMeterIdMap.put(fcId, newDeviceMeterIdSet);
+ }
+
+ @Override
+ public void removeAllForwardingResources(CarrierEthernetForwardingConstruct fc) {
+ removeFlowObjectives(fc.id());
+ }
+
+ /**
+ * Removes all flow objectives installed by the application which are associated with a specific FC.
+ *
+ * @param fcId the FC id
+ * */
+ private void removeFlowObjectives(String fcId) {
+ // Note: A Flow Rule cannot be shared by multiple FCs due to different VLAN or CE-VLAN ID match.
+ List<Pair<DeviceId, Objective>> flowObjectiveList = flowObjectiveMap.remove(fcId);
+ // NextObjectives will be removed after all other Objectives
+ ListIterator<Pair<DeviceId, Objective>> objIter = flowObjectiveList.listIterator();
+ while (objIter.hasNext()) {
+ Pair<DeviceId, Objective> deviceObjectivePair = objIter.next();
+ flowObjectiveService.apply(deviceObjectivePair.getLeft(), deviceObjectivePair.getRight().copy().remove());
+ }
+
+ }
+
+ // FIXME: Replace with Pair<DeviceId, MeterId>
+ /**
+ * Utility class to compensate for the fact that MeterIds are not unique system-wide.
+ * */
+ class DeviceMeterId {
+ private DeviceId deviceId;
+ private MeterId meterId;
+
+ DeviceMeterId(DeviceId deviceId, MeterId meterId) {
+ this.deviceId = deviceId;
+ this.meterId = meterId;
+ }
+
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ public MeterId meterId() {
+ return meterId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deviceId, meterId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DeviceMeterId) {
+ DeviceMeterId other = (DeviceMeterId) obj;
+ if (this.deviceId().equals(other.deviceId()) && this.meterId().equals(other.meterId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ private FlowRule createFlowRule(DeviceId deviceId, int priority,
+ TrafficSelector selector, TrafficTreatment treatment, int tableId) {
+ return DefaultFlowRule.builder()
+ .fromApp(appId)
+ .forDevice(deviceId)
+ .makePermanent()
+ .withPriority(priority)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .forTable(tableId)
+ .build();
+ }
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetPacketNodeService.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetPacketNodeService.java
new file mode 100644
index 0000000..081acde
--- /dev/null
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetPacketNodeService.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.ecord.carrierethernet.app;
+
+import java.util.Set;
+
+/**
+ * Abstraction of a class used to control Carrier Ethernet nodes according to their control protocol.
+ */
+public interface CarrierEthernetPacketNodeService {
+
+ void setNodeForwarding(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface srcNi,
+ Set<CarrierEthernetNetworkInterface> dstNiSet);
+
+ void createBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni);
+
+ void applyBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni);
+
+ void removeBandwidthProfileResources(String fcId, CarrierEthernetUni uni);
+
+ void removeAllForwardingResources(CarrierEthernetForwardingConstruct fc);
+
+}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetProvisioner.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetProvisioner.java
index bbbecad..b0c6d8c 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetProvisioner.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetProvisioner.java
@@ -77,7 +77,7 @@
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CarrierEthernetOpenFlowPacketNodeManager ceOfPktNodeManager;
+ protected CarrierEthernetPacketNodeService cePktNodeService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OpticalPathService opticalPathService;
@@ -239,7 +239,7 @@
ingressEgressNiMap.keySet().forEach(srcNi -> {
// Set forwarding only on packet switches
if (deviceService.getDevice(srcNi.cp().deviceId()).type().equals(Device.Type.SWITCH)) {
- ceOfPktNodeManager.setNodeForwarding(fc, srcNi, ingressEgressNiMap.get(srcNi));
+ cePktNodeService.setNodeForwarding(fc, srcNi, ingressEgressNiMap.get(srcNi));
}
});
@@ -379,18 +379,28 @@
public void removeConnectivity(CarrierEthernetForwardingConstruct fc) {
// TODO: Add here the same call for all node manager types
- ceOfPktNodeManager.removeAllForwardingResources(fc);
+ cePktNodeService.removeAllForwardingResources(fc);
removeOpticalConnectivity(fc.metroConnectivity().id());
}
/**
+ * Creates bandwidth profiles at the UNIs of an FC.
+ *
+ * @param fc the FC representation
+ */
+ public void createBandwidthProfiles(CarrierEthernetForwardingConstruct fc) {
+ // TODO: Select node manager depending on device protocol
+ fc.uniSet().forEach(uni -> cePktNodeService.createBandwidthProfileResources(fc, uni));
+ }
+
+ /**
* Applies bandwidth profiles to the UNIs of an FC.
*
* @param fc the FC representation
*/
public void applyBandwidthProfiles(CarrierEthernetForwardingConstruct fc) {
// TODO: Select node manager depending on device protocol
- fc.uniSet().forEach(uni -> ceOfPktNodeManager.applyBandwidthProfileResources(fc, uni));
+ fc.uniSet().forEach(uni -> cePktNodeService.applyBandwidthProfileResources(fc, uni));
}
/**
@@ -402,7 +412,7 @@
// TODO: Select node manager depending on device protocol
fc.ltpSet().forEach((ltp -> {
if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- ceOfPktNodeManager.removeBandwidthProfileResources(fc.id(), (CarrierEthernetUni) ltp.ni());
+ cePktNodeService.removeBandwidthProfileResources(fc.id(), (CarrierEthernetUni) ltp.ni());
}
}));
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetUni.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetUni.java
index 75ac1b6..6303108 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetUni.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetUni.java
@@ -71,6 +71,7 @@
public CarrierEthernetUni(ConnectPoint cp, String uniCfgId, Role role, VlanId ceVlanId,
CarrierEthernetBandwidthProfile bwp) {
super(cp, Type.UNI, uniCfgId);
+
this.role = role;
// FIXME: Set the NI scope directly instead?
this.scope = (role == null ? Scope.GLOBAL : Scope.SERVICE);
@@ -137,11 +138,13 @@
// Add UNI BWP
CarrierEthernetBandwidthProfile bwp = uni.bwp();
- Map<String, CarrierEthernetBandwidthProfile> subBwpMap = this.bwpMap.get(bwp.type());
- subBwpMap.put(bwp.id(), bwp);
- this.bwpMap.put(bwp.type(), subBwpMap);
- // Used capacity cannot be more than UNI capacity (redundant check - should be avoided by check in validateBwp)
- this.usedCapacity = Bandwidth.bps(Math.min(this.usedCapacity.bps() + bwp.cir().bps(), this.capacity.bps()));
+ if (bwp != null) {
+ Map<String, CarrierEthernetBandwidthProfile> subBwpMap = this.bwpMap.get(bwp.type());
+ subBwpMap.put(bwp.id(), bwp);
+ this.bwpMap.put(bwp.type(), subBwpMap);
+ // Used capacity cannot be more than UNI capacity (redundant check - should be avoided by check in validateBwp)
+ this.usedCapacity = Bandwidth.bps(Math.min(this.usedCapacity.bps() + bwp.cir().bps(), this.capacity.bps()));
+ }
}
/**
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateEvcCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateEvcCommand.java
index b95236b..a92fae6 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateEvcCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateEvcCommand.java
@@ -23,7 +23,6 @@
import org.onlab.util.Bandwidth;
import org.onosproject.ecord.carrierethernet.app.CarrierEthernetBandwidthProfile;
import org.onosproject.ecord.carrierethernet.app.CarrierEthernetManager;
-import org.onosproject.ecord.carrierethernet.app.CarrierEthernetNetworkInterface;
import org.onosproject.ecord.carrierethernet.app.CarrierEthernetVirtualConnection;
import org.onosproject.ecord.carrierethernet.app.CarrierEthernetUni;
import org.onosproject.cli.AbstractShellCommand;
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateFcCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateFcCommand.java
index ee7f058..0a2e6f3 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateFcCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateFcCommand.java
@@ -139,7 +139,7 @@
CarrierEthernetManager ceManager = get(CarrierEthernetManager.class);
// Update list of global LTPs in the network
- ceManager.getLtpsFromTopo().forEach(ltp -> ceManager.addGlobalLtp(ltp));
+ ceManager.getLtpsFromTopo(true, false).forEach(ltp -> ceManager.addGlobalLtp(ltp));
Set<CarrierEthernetLogicalTerminationPoint> ltpSet = new HashSet<>();
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetListLtpsCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetListLtpsCommand.java
index 0188437..588d40d 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetListLtpsCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetListLtpsCommand.java
@@ -33,7 +33,7 @@
protected void execute() {
CarrierEthernetManager evcManager = get(CarrierEthernetManager.class);
// Populate global LTP map
- evcManager.getLtpsFromTopo().forEach(ltp -> evcManager.addGlobalLtp(ltp));
+ evcManager.getLtpsFromTopo(false, false).forEach(ltp -> evcManager.addGlobalLtp(ltp));
printLtps(evcManager.ltpMap().values());
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetListUnisCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetListUnisCommand.java
index 98e600f..ce635f2 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetListUnisCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetListUnisCommand.java
@@ -33,7 +33,7 @@
protected void execute() {
CarrierEthernetManager ceManager = get(CarrierEthernetManager.class);
// Populate global UNI map
- ceManager.getUnisFromTopo().forEach(uni -> ceManager.addGlobalUni(uni));
+ ceManager.getUnisFromTopo(false, false).forEach(uni -> ceManager.addGlobalUni(uni));
printUnis(ceManager.getUniMap().values());
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetLtpCompleter.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetLtpCompleter.java
index 79d5de5..e72c431 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetLtpCompleter.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetLtpCompleter.java
@@ -24,7 +24,7 @@
import java.util.SortedSet;
/**
- * LTP ID completer.
+ * LTP id completer, including only LTPs that have been added to the LTP map.
*/
public class CarrierEthernetLtpCompleter extends AbstractCompleter {
@Override
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetPotentialLtpCompleter.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetPotentialLtpCompleter.java
index 3e1b62f..29c5179 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetPotentialLtpCompleter.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetPotentialLtpCompleter.java
@@ -24,7 +24,7 @@
import java.util.SortedSet;
/**
- * Potential LTP ConnectPoint completer.
+ * LTP id completer, excluding LTPs already added and including LTPs that have been removed.
*/
public class CarrierEthernetPotentialLtpCompleter extends AbstractCompleter {
@Override
@@ -34,9 +34,8 @@
SortedSet<String> strings = delegate.getStrings();
CarrierEthernetManager ceManager = AbstractShellCommand.get(CarrierEthernetManager.class);
- ceManager.getLtpsFromTopo().forEach(ltp -> strings.add(ltp.id()));
+ ceManager.getLtpsFromTopo(true, true).forEach(ltp -> strings.add(ltp.id()));
return delegate.complete(buffer, cursor, candidates);
}
-
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetPotentialUniCompleter.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetPotentialUniCompleter.java
index 7a1e3e1..c0bdbfe 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetPotentialUniCompleter.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetPotentialUniCompleter.java
@@ -24,7 +24,7 @@
import java.util.SortedSet;
/**
- * Potential UNI ConnectPoint completer.
+ * UNI id completer, excluding UNIs that have already been added and including UNIs that have been removed.
*/
public class CarrierEthernetPotentialUniCompleter extends AbstractCompleter {
@@ -35,9 +35,8 @@
SortedSet<String> strings = delegate.getStrings();
CarrierEthernetManager ceManager = AbstractShellCommand.get(CarrierEthernetManager.class);
- ceManager.getUnisFromTopo().forEach(uni -> strings.add(uni.id()));
+ ceManager.getUnisFromTopo(true, true).forEach(uni -> strings.add(uni.id()));
return delegate.complete(buffer, cursor, candidates);
}
-
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetUniCompleter.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetUniCompleter.java
index 15f446c..ef00759 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetUniCompleter.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetUniCompleter.java
@@ -24,7 +24,7 @@
import java.util.SortedSet;
/**
- * UNI ID completer.
+ * UNI id completer, including only UNIs that have been added to the UNI map.
*/
public class CarrierEthernetUniCompleter extends AbstractCompleter {
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetValidLtpCompleter.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetValidLtpCompleter.java
new file mode 100644
index 0000000..da9335d
--- /dev/null
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetValidLtpCompleter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.ecord.carrierethernet.cli.completers;
+
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetManager;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * LTP id completer, not including LTPs that have been removed.
+ */
+public class CarrierEthernetValidLtpCompleter extends AbstractCompleter {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+
+ StringsCompleter delegate = new UniqueStringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+
+ CarrierEthernetManager ceManager = AbstractShellCommand.get(CarrierEthernetManager.class);
+ ceManager.getLtpsFromTopo(false, false).forEach(ltp -> strings.add(ltp.id()));
+
+ return delegate.complete(buffer, cursor, candidates);
+ }
+}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetValidUniCompleter.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetValidUniCompleter.java
new file mode 100644
index 0000000..d0f49de
--- /dev/null
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/completers/CarrierEthernetValidUniCompleter.java
@@ -0,0 +1,42 @@
+/*
+ * 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.ecord.carrierethernet.cli.completers;
+
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetManager;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * UNI id completer, not including UNIs that have been removed.
+ */
+public class CarrierEthernetValidUniCompleter extends AbstractCompleter {
+
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+
+ StringsCompleter delegate = new UniqueStringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+
+ CarrierEthernetManager ceManager = AbstractShellCommand.get(CarrierEthernetManager.class);
+ ceManager.getUnisFromTopo(false, false).forEach(uni -> strings.add(uni.id()));
+
+ return delegate.complete(buffer, cursor, candidates);
+ }
+}
\ No newline at end of file
diff --git a/ecord/carrierethernet/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/ecord/carrierethernet/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 1643486..117e7c1 100644
--- a/ecord/carrierethernet/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/ecord/carrierethernet/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -21,8 +21,8 @@
<completers>
<ref component-id="placeholderCompleter"/>
<ref component-id="carrierEthernetEvcTypeCompleter"/>
- <ref component-id="carrierEthernetPotentialUniCompleter"/>
- <ref component-id="carrierEthernetPotentialUniCompleter"/>
+ <ref component-id="carrierEthernetValidUniCompleter"/>
+ <ref component-id="carrierEthernetValidUniCompleter"/>
</completers>
</command>
</command-bundle>
@@ -33,8 +33,8 @@
<completers>
<ref component-id="placeholderCompleter"/>
<ref component-id="carrierEthernetEvcTypeCompleter"/>
- <ref component-id="carrierEthernetPotentialLtpCompleter"/>
- <ref component-id="carrierEthernetPotentialLtpCompleter"/>
+ <ref component-id="carrierEthernetValidLtpCompleter"/>
+ <ref component-id="carrierEthernetValidLtpCompleter"/>
</completers>
</command>
</command-bundle>
@@ -98,7 +98,7 @@
<action class="org.onosproject.ecord.carrierethernet.cli.commands.CarrierEthernetCreateLtpCommand"/>
<completers>
<ref component-id="carrierEthernetLtpTypeCompleter"/>
- <ref component-id="carrierEthernetConnectPointCompleter"/>
+ <ref component-id="carrierEthernetPotentialLtpCompleter"/>
</completers>
</command>
</command-bundle>
@@ -107,7 +107,7 @@
<command>
<action class="org.onosproject.ecord.carrierethernet.cli.commands.CarrierEthernetCreateUniCommand"/>
<completers>
- <ref component-id="carrierEthernetConnectPointCompleter"/>
+ <ref component-id="carrierEthernetPotentialUniCompleter"/>
</completers>
</command>
</command-bundle>
@@ -150,6 +150,8 @@
<bean id="carrierEthernetLtpTypeCompleter" class="org.onosproject.ecord.carrierethernet.cli.completers.CarrierEthernetLtpTypeCompleter"/>
<bean id="carrierEthernetUniCompleter" class="org.onosproject.ecord.carrierethernet.cli.completers.CarrierEthernetUniCompleter"/>
<bean id="carrierEthernetLtpCompleter" class="org.onosproject.ecord.carrierethernet.cli.completers.CarrierEthernetLtpCompleter"/>
+ <bean id="carrierEthernetValidUniCompleter" class="org.onosproject.ecord.carrierethernet.cli.completers.CarrierEthernetValidUniCompleter"/>
+ <bean id="carrierEthernetValidLtpCompleter" class="org.onosproject.ecord.carrierethernet.cli.completers.CarrierEthernetValidLtpCompleter"/>
<bean id="carrierEthernetBooleanCompleter" class="org.onosproject.ecord.carrierethernet.cli.completers.CarrierEthernetBooleanCompleter"/>