Major refactoring to always link EVCs to FCs + adding EVC-to-FC fragmentation
- Making EVCs to always be composed of FCs
- Subclassing EVCs and FCs from abstract CarrierEthernetConnection class
- Refactored CarrierEthernetProvisioner to only work with FCs
- Adding basing orchestration functionality in CarrierEthernetManager to create set of FCs out of an EVC based on LTPs in topology
- Automatically assign vlanIds to FCs and corresponding S-TAGs to INNIs of neighboring FCs
- Allowing setting forwarding for single-device FCs
- Making sure that INNIs always appear in pairs
- Minor modifications in some CLI commands
- Getting rid of the ActiveState enum in CarrierEthernetConnection.java and doing some relevant refactoring
- Renaming addNi/removeNi/validateNi methods in CarrierEthernetNetworkInterface.java
Change-Id: I3e4972bd792585a05912943cabb45becfe2e82a4
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetConnection.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetConnection.java
new file mode 100644
index 0000000..c847480
--- /dev/null
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetConnection.java
@@ -0,0 +1,193 @@
+/*
+ * 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.time.Duration;
+
+/**
+ * Representation of an abstract CE connection (meant to be extended by the EVC and FC classes).
+ */
+public abstract class CarrierEthernetConnection {
+
+ public enum Type {
+
+ POINT_TO_POINT("Point_To_Point"),
+ MULTIPOINT_TO_MULTIPOINT("Multipoint_To_Multipoint"),
+ ROOT_MULTIPOINT("Root_Multipoint");
+
+ private String value;
+
+ Type(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ public static Type fromString(String value) {
+ if (value != null) {
+ for (Type b : Type.values()) {
+ if (value.equals(b.value)) {
+ return b;
+ }
+ }
+ }
+ throw new IllegalArgumentException("Type " + value + " is not valid");
+ }
+ }
+
+ public enum State {
+
+ ACTIVE("Active"),
+ INACTIVE("Inactive"),
+ PARTIAL("Partial");
+
+ private String value;
+
+ State(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ public static State fromString(String value) {
+ if (value != null) {
+ for (State b : State.values()) {
+ if (value.equals(b.value)) {
+ return b;
+ }
+ }
+ }
+ throw new IllegalArgumentException("State " + value + " is not valid");
+ }
+ }
+
+ // TODO: Use the ONOS built-in identifier??
+ protected String id;
+ protected String cfgId;
+ protected Type type;
+ protected State state;
+ protected Duration maxLatency;
+
+ private static final Duration DEFAULT_MAX_LATENCY = Duration.ofMillis(50);
+
+ // Note: id should be provided only when updating an existing connection
+ public CarrierEthernetConnection(String id, String cfgId, Type type, Duration maxLatency) {
+ this.id = id;
+ this.cfgId = cfgId;
+ this.type = type;
+ this.state = State.INACTIVE;
+ this.maxLatency = maxLatency == null? DEFAULT_MAX_LATENCY: maxLatency;
+ }
+
+ /**
+ * Returns connection identifier.
+ *
+ * @return connection identifier
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * Returns connection config identifier.
+ *
+ * @return connection config identifier
+ */
+ public String cfgId() {
+ return cfgId;
+ }
+
+ /**
+ * Returns type of connection.
+ *
+ * @return type of connection
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns connectivity state of the connection.
+ *
+ * @return connectivity state
+ */
+ public State state() { return state; }
+
+ /**
+ * Indicates whether the connection is active or partially active.
+ *
+ * @return connectivity state
+ */
+ public boolean isActive() {
+ return !state.equals(State.INACTIVE);
+ }
+
+ /**
+ * Returns maximum latency constraint.
+ *
+ * @return maximum latency constraint
+ */
+ public Duration maxLatency() {
+ return maxLatency;
+ }
+
+ /**
+ * Sets connection identifier.
+ *
+ * @param id the connection identifier to set
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets connection config identifier.
+ *
+ * @param cfgId connection config identifier
+ */
+ public void setCfgId(String cfgId) {
+ this.cfgId = cfgId;
+ }
+
+ /**
+ * Sets the connectivity state of the connection.
+ *
+ * @param state the connectivity state to set
+ */
+ public void setState(State state) { this.state = state; }
+
+ /**
+ * Sets the type of connection.
+ *
+ * @param type type of connection to set
+ */
+ public void setType(Type type) { this.type = type; }
+
+ /**
+ * Sets maximum latency constraint.
+ *
+ * @param maxLatency the maximum latency constraint to set
+ */
+ public void setMaxLatency(Duration maxLatency) {
+ this.maxLatency = maxLatency;
+ }
+}
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 d7b4d95..68886f5 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
@@ -33,14 +33,17 @@
* 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)
*/
-public class CarrierEthernetEnni extends CarrierEthernetNetworkInterface {
+public class CarrierEthernetEnni extends CarrierEthernetNetworkInterface <CarrierEthernetEnni> {
private final Logger log = getLogger(getClass());
public enum Role {
HUB("Hub"),
- SPOKE("Spoke");
+ SPOKE("Spoke"),
+ // FIXME: Remove these after LTP-NI role mapping is fixed
+ ROOT("Root"),
+ LEAF("Leaf");
private String value;
@@ -76,13 +79,12 @@
}
/**
- * Adds the resources associated with an EVC-specific ENNI to a global ENNI.
+ * Adds the resources associated with an FC-specific ENNI to a global ENNI.
*
- * @param enni the EVC ENNI to be added
+ * @param enni the FC-specific ENNI to be added
*/
- // TODO: Make these methods abstract
- public void addEvcEnni(CarrierEthernetEnni enni) {
-
+ @Override
+ public void addEcNi(CarrierEthernetEnni enni) {
// Add S-VLAN ID
if (enni.sVlanId() != VlanId.NONE) {
this.sVlanIdSet.add(enni.sVlanId());
@@ -92,26 +94,26 @@
}
/**
- * Removes the resources associated with a service-specific ENNI from a global ENNI.
+ * Removes the resources associated with an FC-specific ENNI from a global ENNI.
*
- * @param enni the service ENNI to be added
+ * @param enni the FC-specific ENNI to be removed
*/
- public void removeEvcEnni(CarrierEthernetEnni enni) {
-
+ @Override
+ public void removeEcNi(CarrierEthernetEnni enni) {
// Remove UNI CE-VLAN ID
sVlanIdSet.remove(enni.sVlanId());
-
// Redundant check - should be avoided by check in validateBwp
this.usedCapacity = Bandwidth.bps(Math.max(this.usedCapacity.bps() - enni.usedCapacity().bps(), 0));
}
/**
- * Validates whether an EVC-specific ENNI is compatible with a global ENNI.
+ * Validates whether an FC-specific ENNI is compatible with the corresponding global ENNI.
*
- * @param enni the EVC-specific UNI
- * @return boolean value indicating whether the UNIs are compatible
+ * @param enni the FC-specific ENNI
+ * @return boolean value indicating whether the ENNIs are compatible
*/
- public boolean validateEvcEnni(CarrierEthernetEnni enni) {
+ @Override
+ public boolean validateEcNi(CarrierEthernetEnni enni) {
// Check if the S-VLAN ID of the ENNI is already included in global ENNI
if (enni.sVlanId() != VlanId.NONE) {
@@ -180,6 +182,16 @@
return sVlanIdSet;
}
+ // FIXME: Find a better way to implement this method
+ /**
+ * Sets the S-VLAN id associated with an FC INNI.
+ *
+ * @param sVlanId S-VLAN id to set
+ */
+ public void setSVlanId(VlanId sVlanId) {
+ sVlanIdSet.add(sVlanId);
+ }
+
@Override
public String toString() {
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetForwardingConstruct.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetForwardingConstruct.java
index 55ce9cb..c884bf9 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetForwardingConstruct.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetForwardingConstruct.java
@@ -15,133 +15,73 @@
*/
package org.onosproject.ecord.carrierethernet.app;
+import com.google.common.annotations.Beta;
+import org.onlab.packet.VlanId;
+import org.onosproject.newoptical.api.OpticalConnectivityId;
import org.onosproject.newoptical.api.OpticalPathEvent;
-import org.slf4j.Logger;
import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
import static com.google.common.base.MoreObjects.toStringHelper;
-import static org.slf4j.LoggerFactory.getLogger;
/**
* Representation of a CE Forwarding Construct.
*/
-public class CarrierEthernetForwardingConstruct {
+public class CarrierEthernetForwardingConstruct extends CarrierEthernetConnection {
- private final Logger log = getLogger(getClass());
-
- public enum State {
-
- ACTIVE("Active"),
- INACTIVE("Inactive");
-
- private String value;
-
- State(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- public static State fromString(String value) {
- if (value != null) {
- for (State b : State.values()) {
- if (value.equals(b.value)) {
- return b;
- }
- }
- }
- throw new IllegalArgumentException("State " + value + " is not valid");
- }
- }
-
- public enum ActiveState {
-
- FULL("Full"),
- PARTIAL("Partial");
-
- private String value;
-
- ActiveState(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return value;
- }
- }
-
- protected String fcId;
- protected String fcCfgId;
- protected String evcId;
- protected CarrierEthernetVirtualConnection.Type evcType;
- protected Set<CarrierEthernetLogicalTerminationPoint> ltpSet;
- protected CarrierEthernetForwardingConstruct.State state;
- protected CarrierEthernetForwardingConstruct.ActiveState activeState;
- protected Duration latency;
- protected CarrierEthernetMetroConnectivity metroConnectivity;
- protected boolean congruentPaths;
-
- // FIXME: Find a better way
- protected CarrierEthernetVirtualConnection evcLite;
+ private Set<CarrierEthernetLogicalTerminationPoint> ltpSet;
+ private VlanId vlanId;
+ private VlanId transportVlanId;
+ private CarrierEthernetMetroConnectivity metroConnectivity;
+ private boolean congruentPaths;
+ protected AtomicInteger refCount;
// Set to true if both directions should use the same path
private static final boolean CONGRUENT_PATHS = true;
- private static final Duration DEFAULT_LATENCY = Duration.ofMillis(50);
-
- // TODO: Maybe fcCfgId and evcId are not needed?
// Note: fcId should be provided only when updating an existing FC
- public CarrierEthernetForwardingConstruct(String fcId, String fcCfgId,
- String evcId, CarrierEthernetVirtualConnection.Type evcType,
- Set<CarrierEthernetLogicalTerminationPoint> ltpSet) {
- this.fcId = fcId;
- this.fcCfgId = (fcCfgId == null? fcId : fcCfgId);
- this.evcId = evcId;
- this.evcType = evcType;
- this.state = State.INACTIVE;
+ public CarrierEthernetForwardingConstruct(String id, String cfgId, Type type,
+ Set<CarrierEthernetLogicalTerminationPoint> ltpSet,
+ Duration maxLatency) {
+ super(id, cfgId, type, maxLatency);
this.ltpSet = new HashSet<>(ltpSet);
- this.congruentPaths = CONGRUENT_PATHS;
- this.latency = DEFAULT_LATENCY;
+ this.vlanId = null;
+ this.transportVlanId = null;
this.metroConnectivity = new CarrierEthernetMetroConnectivity(null, OpticalPathEvent.Type.PATH_REMOVED);
-
- // FIXME: This is (probably) just a temporary solution
- // Create a lightweight EVC out of the FC which can be used with existing methods
- Set<CarrierEthernetNetworkInterface> niSet = new HashSet<>();
- ltpSet.forEach(ltp -> {
- if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- niSet.add(ltp.ni());
- }
- });
- this.evcLite = new CarrierEthernetVirtualConnection(fcId, fcCfgId, evcType, null, niSet);
- }
-
- // TODO: Create constructor using the End-to-End service and a set of LTPs
-
- public String toString() {
-
- return toStringHelper(this)
- .add("id", fcId)
- .add("cfgId", fcCfgId)
- .add("evcId", evcId)
- .add("evcType", evcType)
- .add("metroConnectId", (metroConnectivity.id() == null ? "null" : metroConnectivity.id().id()))
- .add("LTPs", ltpSet).toString();
+ this.congruentPaths = CONGRUENT_PATHS;
+ this.refCount = new AtomicInteger();
}
/**
- * Returns the id of the FC.
+ * Returns Vlan id.
*
- * @return id of the FC
+ * @return Vlan id
*/
- public String id() {
- return fcId;
+ public VlanId vlanId() {
+ return vlanId;
+ }
+
+ /**
+ * Returns Transport Vlan ID.
+ *
+ * @return Transport Vlan ID.
+ */
+ @Beta
+ public VlanId transportVlanId() {
+ return transportVlanId;
+ }
+
+ /**
+ * Gets metro connectivity id.
+ *
+ * @return the metro connectivity of the service
+ */
+ public CarrierEthernetMetroConnectivity metroConnectivity() {
+ return this.metroConnectivity;
}
/**
@@ -154,46 +94,53 @@
}
/**
- * Returns the type of the EVC associated with the FC.
+ * Returns the set of UNIs associated with the FC.
*
- * @return type of associated EVC
+ * @return set of UNIs associated with the FC
*/
- public CarrierEthernetVirtualConnection.Type evcType() {
- return evcType;
+ public Set<CarrierEthernetUni> uniSet() {
+ // FIXME: Find a more efficient way to get the FC UNIs
+ return ltpSet
+ .stream()
+ .filter(ltp -> ltp.type().equals(CarrierEthernetNetworkInterface.Type.UNI))
+ .map(ltp -> (CarrierEthernetUni) ltp.ni()).collect(Collectors.toSet());
}
/**
- * Returns connectivity state of the FC.
+ * Returns true if FC requires congruent paths.
*
- * @return connectivity state
+ * @return true if congruent paths required
*/
- public State state() {
- return state;
+ public boolean congruentPaths() {
+ return congruentPaths;
}
/**
- * Returns active connectivity state of the FC.
+ * Returns counter with the number of references (from EVCs) to the particular FC.
*
- * @return active connectivity state
+ * @return number of references counter
*/
- public ActiveState activeState() {
- return activeState;
+ public AtomicInteger refCount() {
+ return refCount;
}
/**
- * Returns the "EVC" associated with FC.
+ * Sets the vlanId to be used by the FC.
*
- * @return the "EVC" associated with FC
+ * @param vlanId the vlanId to set
*/
- public CarrierEthernetVirtualConnection evcLite() { return evcLite; }
+ public void setVlanId(VlanId vlanId) {
+ this.vlanId = vlanId;
+ }
/**
- * Sets the id of the FC.
+ * Sets the vlanId to be used by the transport part of the FC.
*
- * @param id the id to set to the FC
+ * @param vlan the vlanId to set
*/
- public void setId(String id) {
- this.fcId = id;
+ @Beta
+ public void setTransportVlanId(VlanId vlan) {
+ this.transportVlanId = vlan;
}
/**
@@ -206,17 +153,33 @@
}
/**
- * Sets the connectivity state of the FC.
+ * Sets metro connectivity id.
*
- * @param state the connectivity state to set
+ * @param id the metro connectivity identifier to set
*/
- public void setState(State state) { this.state = state; }
+ public void setMetroConnectivityId(OpticalConnectivityId id) {
+ this.metroConnectivity.setId(id);
+ }
/**
- * Sets the active connectivity state of the FC.
+ * Sets metro connectivity status.
*
- * @param activeState the active connectivity state to set
+ * @param status the metro connectivity status
*/
- public void setActiveState(ActiveState activeState) { this.activeState = activeState; }
+ public void setMetroConnectivityStatus(OpticalPathEvent.Type status) {
+ this.metroConnectivity.setStatus(status);
+ }
+ public String toString() {
+
+ return toStringHelper(this)
+ .add("id", id)
+ .add("cfgId", cfgId)
+ .add("type", type)
+ .add("vlanId", vlanId)
+ .add("transportVlanId", transportVlanId)
+ .add("metroConnectId", (metroConnectivity.id() == null ? "null" : metroConnectivity.id().id()))
+ .add("refCount", refCount)
+ .add("LTPs", ltpSet).toString();
+ }
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetGenericNi.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetGenericNi.java
index 2ddba2e..0795e01 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetGenericNi.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetGenericNi.java
@@ -30,9 +30,9 @@
/**
* Representation of a Generic Carrier Ethernet NI.
- * Class is only mean to be used for establishing forwarding in CarrierEthernetPacketNodeManagers
+ * Class is only meant to be used for establishing forwarding in CarrierEthernetPacketNodeManagers
*/
-public class CarrierEthernetGenericNi extends CarrierEthernetNetworkInterface {
+public class CarrierEthernetGenericNi extends CarrierEthernetNetworkInterface <CarrierEthernetGenericNi> {
public enum Role {
@@ -78,6 +78,31 @@
return null;
}
+ /**
+ * Dummy implementation of abstract method (for generic NI type there is no concept of EVC vs. global NIs).
+ *
+ * @param gni a generic NI
+ */
+ @Override
+ public void addEcNi(CarrierEthernetGenericNi gni) {}
+
+ /**
+ * Dummy implementation of abstract method (for generic NI type there is no concept of EVC vs. global NIs).
+ *
+ * @param gni a generic NI
+ */
+ @Override
+ public void removeEcNi(CarrierEthernetGenericNi gni) {}
+
+ /**
+ * Dummy implementation of abstract method (for generic NI type there is no concept of EVC vs. global NIs).
+ *
+ * @param gni a generic NI
+ * @return true
+ */
+ @Override
+ public boolean validateEcNi(CarrierEthernetGenericNi gni) { return true; }
+
@Override
public String toString() {
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 c876244..64c8f4f 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
@@ -34,7 +34,7 @@
* 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)
*/
-public class CarrierEthernetInni extends CarrierEthernetNetworkInterface {
+public class CarrierEthernetInni extends CarrierEthernetNetworkInterface <CarrierEthernetInni> {
private final Logger log = getLogger(getClass());
@@ -43,7 +43,10 @@
HUB("Hub"),
// FIXME: Remove that after hackathon?
TRUNK("Trunk"),
- SPOKE("Spoke");
+ SPOKE("Spoke"),
+ // FIXME: Remove these after LTP-NI role mapping is fixed
+ ROOT("Root"),
+ LEAF("Leaf");
private String value;
@@ -79,13 +82,12 @@
}
/**
- * Adds the resources associated with an EVC-specific INNI to a global INNI.
+ * Adds the resources associated with an FC-specific INNI to a global INNI.
*
- * @param inni the EVC INNI to be added
+ * @param inni the FC-specific INNI to be added
*/
- // TODO: Make these methods abstract
- public void addEvcInni(CarrierEthernetInni inni) {
-
+ @Override
+ public void addEcNi(CarrierEthernetInni inni) {
// Add S-VLAN ID
if (inni.sVlanId() != VlanId.NONE) {
this.sVlanIdSet.add(inni.sVlanId());
@@ -96,26 +98,26 @@
}
/**
- * Removes the resources associated with a service-specific INNI from a global INNI.
+ * Removes the resources associated with an FC-specific INNI from a global INNI.
*
- * @param inni the service INNI to be added
+ * @param inni the FC-specific INNI to be removed
*/
- public void removeEvcInni(CarrierEthernetInni inni) {
-
+ @Override
+ public void removeEcNi(CarrierEthernetInni inni) {
// Remove UNI CE-VLAN ID
sVlanIdSet.remove(inni.sVlanId());
-
// Redundant check - should be avoided by check in validateBwp
this.usedCapacity = Bandwidth.bps(Math.max(this.usedCapacity.bps() - inni.usedCapacity().bps(), 0));
}
/**
- * Validates whether an EVC-specific INNI is compatible with a global INNI.
+ * Validates whether an FC-specific INNI is compatible with the corresponding global INNI.
*
- * @param inni the EVC-specific UNI
- * @return boolean value indicating whether the UNIs are compatible
+ * @param inni the FC-specific INNI
+ * @return boolean value indicating whether the INNIs are compatible
*/
- public boolean validateEvcInni(CarrierEthernetInni inni) {
+ @Override
+ public boolean validateEcNi(CarrierEthernetInni inni) {
// Check if the S-VLAN ID of the INNI is already included in global INNI
if (inni.sVlanId() != null) {
@@ -175,6 +177,16 @@
return ImmutableSet.copyOf(sVlanIdSet);
}
+ // FIXME: Find a better way to implement this method
+ /**
+ * Sets the S-VLAN id associated with an FC INNI.
+ *
+ * @param sVlanId S-VLAN id to set
+ */
+ public void setSVlanId(VlanId sVlanId) {
+ sVlanIdSet.add(sVlanId);
+ }
+
/**
* Returns INNI tpid - applicable only to service-specific INNIs.
*
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 ba564d4..cd4ccef 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
@@ -74,16 +74,22 @@
}
public CarrierEthernetLogicalTerminationPoint(ConnectPoint cp, String ltpCfgId,
- CarrierEthernetNetworkInterface.Type niType) {
+ CarrierEthernetNetworkInterface.Type niType,
+ CarrierEthernetLogicalTerminationPoint.Role role) {
this.ltpId = cp.deviceId().toString() + "/" + cp.port().toString();
this.ltpCfgId = (ltpCfgId == null ? this.ltpId : ltpCfgId);
- // NOTE: Role is expected to be null for service-specific LTPs/NIs
+ this.role = role;
+ // NOTE: Role is expected to be null for global LTPs/NIs
+ // FIXME: Provide appropriate mapping between LTP and NI roles (e.g. ROOT -> HUB, LEAF -> SPOKE)
if (niType.equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- this.ni = new CarrierEthernetUni(cp, ltpId, null, null, null);
+ CarrierEthernetUni.Role uniRole = (role == null) ? null : CarrierEthernetUni.Role.valueOf(role.name());
+ this.ni = new CarrierEthernetUni(cp, ltpId, uniRole, null, null);
} else if (niType.equals(CarrierEthernetNetworkInterface.Type.INNI)) {
- this.ni = new CarrierEthernetInni(cp, ltpId, null, null, null, null);
+ CarrierEthernetInni.Role inniRole = (role == null) ? null : CarrierEthernetInni.Role.valueOf(role.name());
+ this.ni = new CarrierEthernetInni(cp, ltpId, inniRole, null, null, null);
} else if (niType.equals(CarrierEthernetNetworkInterface.Type.ENNI)) {
- this.ni = new CarrierEthernetEnni(cp, ltpId, null, null, null, null);
+ CarrierEthernetEnni.Role enniRole = (role == null) ? null : CarrierEthernetEnni.Role.valueOf(role.name());
+ this.ni = new CarrierEthernetEnni(cp, ltpId, enniRole, null, null, null);
}
}
@@ -168,6 +174,15 @@
this.ni = ni;
}
+ /**
+ * Returns LTP role - applicable only to EVC- or FC-specific LTPs.
+ *
+ * @param role he LTP role to set
+ */
+ public void setRole(Role role) {
+ this.role = role;
+ }
+
public String toString() {
return toStringHelper(this)
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 d22e8c6..a304fd0 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
@@ -16,6 +16,7 @@
package org.onosproject.ecord.carrierethernet.app;
import com.google.common.collect.Sets;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
@@ -26,11 +27,18 @@
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.link.LinkService;
+import org.onosproject.net.topology.PathService;
+import org.onosproject.net.topology.TopologyService;
import org.slf4j.Logger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -39,6 +47,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
+import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
import static org.slf4j.LoggerFactory.getLogger;
@Component(immediate = true)
@@ -54,11 +63,23 @@
protected DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PathService pathService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TopologyService topologyService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CarrierEthernetProvisioner ceProvisioner;
// Keeps track of the next S-VLAN tag the app will try to use
private static short nextVlanId = 1;
+ // Keeps track of the next EVC id the app will try to use
+ // TODO: Use Identifier class instead
+ private static short nextEvcShortId = 1;
+
+ private boolean evcFragmentationEnabled = true;
+
// TODO: Implement distributed store for EVCs
// The installed EVCs
private final Map<String, CarrierEthernetVirtualConnection> evcMap = new ConcurrentHashMap<>();
@@ -70,7 +91,7 @@
// TODO: Implement distributed store for CE UNIs
// The installed CE UNIs
private final Map<String, CarrierEthernetUni> uniMap = new ConcurrentHashMap<>();
- private final Set<String> removedUniSet = Sets.newConcurrentHashSet();;
+ private final Set<String> removedUniSet = Sets.newConcurrentHashSet();
// TODO: Implement distributed store for CE LTPs
// The installed CE LTPs
@@ -163,26 +184,23 @@
// Make a copy of the provided EVC, since it may be modified
CarrierEthernetVirtualConnection evc = originalEvc;
- // Try to set a unique VLAN id for the EVC unless the EVC is being updated
- // TODO: Add different connectivity types
- if (evc.vlanId() == null) {
- evc.setVlanId(generateVlanId());
- if (evc.vlanId() == null) {
- log.error("No available VLAN id found.");
- return null;
- }
+ // Try to set a unique numerical id for the EVC unless the EVC is being updated
+ // FIXME: Check again the EVC update case
+ evc.setShortId(generateEvcShortId());
+ if (evc.shortId() == null) {
+ log.error("No available EVC id found.");
+ return null;
}
+ // Generate and set unique FC id
+ evc.setId(generateEvcId(evc));
+
// Verify that CE-VLAN ID is provided to either all UNIs or none and set the virtualEvc flag accordingly
// Note: Checking also that all NIs are UNIs
boolean isVirtual = false;
- Iterator<CarrierEthernetNetworkInterface> it = evc.niSet().iterator();
+ Iterator<CarrierEthernetUni> it = evc.uniSet().iterator();
while (it.hasNext()) {
- CarrierEthernetNetworkInterface ni = it.next();
- if (!ni.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- log.error("All EVC NIs have to be of type UNI.");
- return null;
- }
+ CarrierEthernetUni ni = it.next();
if (ni.ceVlanId() == VlanId.NONE && isVirtual) {
log.error("Could not validate the virtual status of the EVC.");
return null;
@@ -197,12 +215,15 @@
evc.setId(generateEvcId(evc));
}
- Set<CarrierEthernetNetworkInterface> validatedUniSet = new HashSet<>();
+ Set<CarrierEthernetUni> validatedUniSet = new HashSet<>();
+
+ // TODO: Refactor according to the validateFc method
+ // Note: Cannot use the validateFc method here, because FCs can also be standalone
// Check the UNIs of the EVC, possibly removing UNIs that are incompatible with existing global ones
- it = evc.niSet().iterator();
+ it = evc.uniSet().iterator();
while (it.hasNext()) {
- CarrierEthernetUni uni = (CarrierEthernetUni) it.next();
+ CarrierEthernetUni uni = it.next();
// Change the name of the UNI's BWP to the EVC name if it is an EVC BWP
if (uni.bwp().type().equals(CarrierEthernetBandwidthProfile.Type.EVC)) {
uni.bwp().setId(evc.id());
@@ -211,7 +232,7 @@
if (uniMap.keySet().contains(uni.id())) {
CarrierEthernetUni existingUni = uniMap.get(uni.id());
// Check if the EVC-specific UNI is compatible with the global one
- if (!(existingUni.validateEvcUni(uni))) {
+ if (!(existingUni.validateEcNi(uni))) {
// If EVC is of ROOT_MULTIPOINT type and we have removed the root, return null
if (evc.type() == CarrierEthernetVirtualConnection.Type.ROOT_MULTIPOINT &&
uni.role() == CarrierEthernetUni.Role.ROOT) {
@@ -231,21 +252,23 @@
}
// Update the EVC UNI set, based on the validated UNIs
- evc.setNiSet(validatedUniSet);
+ evc.setUniSet(validatedUniSet);
- if (evc.niSet().size() > evc.maxNumUni()) {
+ // TODO: Check that an ROOT_MULTIPOINT EVC has at most one ROOT
+
+ if (evc.uniSet().size() > evc.maxNumUni()) {
log.error("{} EVC can have at most {} UNIs.", evc.maxNumUni());
return null;
}
if ((evc.type().equals(CarrierEthernetVirtualConnection.Type.ROOT_MULTIPOINT)
|| evc.type().equals(CarrierEthernetVirtualConnection.Type.MULTIPOINT_TO_MULTIPOINT))
- && (evc.niSet().size() < 2)) {
+ && (evc.uniSet().size() < 2)) {
log.error("{} EVC requires at least two UNIs.", evc.type().name());
return null;
}
- if (evc.type().equals(CarrierEthernetVirtualConnection.Type.POINT_TO_POINT) && (evc.niSet().size() != 2)) {
+ if (evc.type().equals(CarrierEthernetVirtualConnection.Type.POINT_TO_POINT) && (evc.uniSet().size() != 2)) {
log.error("{} EVC requires exactly two UNIs.", evc.type().name());
return null;
}
@@ -253,97 +276,322 @@
return evc;
}
- // TODO: Refactor so that EVCs are always made of FCs
/**
* Establish connectivity according to the EVC type (E-Line, E-Tree, E-LAN) and the EVC parameters.
*
* @param evc the EVC representation
- * @return the (potentially modified) EVC that was installed or null if EVC connectivity could not be established
+ * @return the (potentially modified) EVC that was installed or null in case of failure
*/
- public CarrierEthernetVirtualConnection establishConnectivity(CarrierEthernetVirtualConnection evc) {
+ public CarrierEthernetVirtualConnection installEvc(CarrierEthernetVirtualConnection evc) {
// If EVC already exists, remove it and reestablish with new parameters
if (evc.id() != null && evcMap.containsKey(evc.id())) {
return updateEvc(evc);
} else {
+ // id will be generated during validation below
evc.setId(null);
}
- evc = validateEvc(evc);
-
- if (evc == null) {
+ if (validateEvc(evc) == null) {
log.error("EVC could not be installed, please check log for details.");
return null;
}
- ceProvisioner.setupConnectivity(evc.niSet(), evc);
+ //////////////////////////////////////////////////////////////////////////////////////////////////
+ // This is the "orchestration" part of the CE app
+ //////////////////////////////////////////////////////////////////////////////////////////////////
- // If no pair was connected, do not register the EVC
- if (evc.state().equals(CarrierEthernetVirtualConnection.State.ACTIVE)) {
- // Apply BWP-related resources (e.g. Meters) to the packet switches
- ceProvisioner.applyBandwidthProfiles(evc);
- // Apply the BWPs of the EVC UNI to the global UNIs, creating them if needed
- applyBandwidthProfiles(evc.niSet());
- // Increment the global UNI reference count
- // FIXME: Remove this as soon as EVCs are made of FCs
- evc.niSet().forEach(uni -> uniMap.get(uni.id()).refCount().incrementAndGet());
+ // TODO: Add configurable parameter to determine if fragmentation will take place
+ if (evcFragmentationEnabled) {
+ evc.setFcSet(fragmentEvc(evc));
+ } else {
+ evc.setFcSet(Collections.singleton(fcFromEvc(evc)));
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // Assign VLAN ids to FCs
+ // FIXME: This was supposed to be done in the validateFc method
+ // FIXME: but we need a vlanId here already, so that S-TAGs can be assigned below among paired INNIs/ENNIs
+ // TODO: If network configuration is present, get FC vlanIds from corresponding ports
+ List<VlanId> tmpVlanIdList = new ArrayList<>();
+ evc.fcSet().forEach(fc -> {
+ fc.setVlanId(generateVlanId(tmpVlanIdList));
+ tmpVlanIdList.add(fc.vlanId());
+ });
+
+ // For each INNI/ENNI of each FC, find the paired INNI/ENNI and assign S-TAG according to the other FC's vlanId
+ for (CarrierEthernetForwardingConstruct fc : evc.fcSet()) {
+ for (CarrierEthernetLogicalTerminationPoint ltp : fc.ltpSet()) {
+ if (!ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ // Find the cp at the other end of the link
+ Link link = linkService.getEgressLinks(ltp.ni().cp()).iterator().next();
+ String ltpId = link.dst().deviceId().toString() + "/" + link.dst().port().toString();
+ // Find the corresponding FC - assuming LTP ids are the same as connect point ids
+ CarrierEthernetForwardingConstruct neighborFc = getFcFromLtpId(ltpId, evc.fcSet());
+ if (neighborFc != null) {
+ if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.INNI)) {
+ ((CarrierEthernetInni) ltp.ni()).setSVlanId(neighborFc.vlanId());
+ } else if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.ENNI)) {
+ ((CarrierEthernetEnni) ltp.ni()).setSVlanId(neighborFc.vlanId());
+ }
+ }
+ }
+ }
+ }
+
+ // Install the constituent FCs
+ evc.fcSet().forEach(fc -> {
+ // Increment the FC refCount
+ fc.refCount().incrementAndGet();
+ installFc(fc);
+ });
+
+ // Update the EVC UNI set based on the LTPs used during FC connectivity
+ Set<CarrierEthernetUni> usedUniSet = new HashSet<>();
+ evc.fcSet().forEach(fc -> usedUniSet.addAll(fc.uniSet()));
+ evc.setUniSet(usedUniSet);
+
+ // Determine EVC state based on the state of the constituent FCs
+ evc.setState(CarrierEthernetVirtualConnection.State.ACTIVE);
+ Iterator<CarrierEthernetForwardingConstruct> fcIt = evc.fcSet().iterator();
+ while (fcIt.hasNext()) {
+ CarrierEthernetForwardingConstruct fc = fcIt.next();
+ evc.setState(CarrierEthernetVirtualConnection.State.valueOf(fc.state().name()));
+ if (!evc.isActive()) {
+ break;
+ }
+ }
+
+ if (evc.isActive()) {
+ // If EVC installation was successful, then register the EVC
evcMap.put(evc.id(), evc);
+ } else {
+ // If EVC installation was not successful, then do not register the EVC and rollback FC installations
+ evc.fcSet().forEach(fc -> {
+ // Decrement the FC refCount to make removal possible
+ fc.refCount().decrementAndGet();
+ removeFc(fc.id());
+ });
}
return evc;
}
/**
- * Reestablish connectivity for an existing EVC.
+ * Creates a single FC out of an EVC.
*
- * @param originalEvc the updated EVC definition
- * @return the (potentially modified) EVC that was installed or null if EVC connectivity could not be established
+ * @param evc the EVC representation
+ * @return the equivalent FC
*/
- public CarrierEthernetVirtualConnection updateEvc(CarrierEthernetVirtualConnection originalEvc) {
- // Just checking again
- if (evcMap.containsKey(originalEvc.id())) {
- log.info("Updating existing EVC {}", originalEvc.id());
- // Keep the VLAN ID of the original EVC
- originalEvc.setVlanId(evcMap.get(originalEvc.id()).vlanId());
- removeEvc(originalEvc.id());
- }
- return establishConnectivity(originalEvc);
+ CarrierEthernetForwardingConstruct fcFromEvc(CarrierEthernetVirtualConnection evc) {
+ Set<CarrierEthernetLogicalTerminationPoint> ltpSet = new HashSet<>();
+ evc.uniSet().forEach(uni -> ltpSet.add(new CarrierEthernetLogicalTerminationPoint(null, uni)));
+ return new CarrierEthernetForwardingConstruct(null, null, evc.type(), ltpSet, null);
}
/**
- * Applies bandwidth profiles to the UNIs of an EVC and if needed adds the UNIs to the global UNI map.
+ * Fragments an EVC into multiple FCs.
*
- * @param niSet set of UNIs that are included in the EVC
+ * @param evc the EVC representation
+ * @return the set of FCs constituting the EVC
*/
- private void applyBandwidthProfiles(Set<CarrierEthernetNetworkInterface> niSet) {
+ Set<CarrierEthernetForwardingConstruct> fragmentEvc(CarrierEthernetVirtualConnection evc) {
- niSet.forEach(uni -> {
- if (!(uniMap.keySet().contains(uni.id()))) {
- // Just add the UNI as it appears at the EVC
- uniMap.put(uni.id(), (CarrierEthernetUni) uni);
+ Set<CarrierEthernetForwardingConstruct> fcSet = new HashSet<>();
+
+ // Each LTP can only belong to a single FC, hence using LTP_id -> LTP_set map
+ Map<String, Set<CarrierEthernetLogicalTerminationPoint>> ltpSetMap = new HashMap<>();
+
+ // Temporary set to browse through all EVC UNI pairs
+ Set<CarrierEthernetUni> tempUniSet = new HashSet<>(evc.uniSet());
+
+ Iterator<CarrierEthernetUni> uniIt1 = tempUniSet.iterator();
+ while (uniIt1.hasNext()) {
+
+ CarrierEthernetUni uni1 = uniIt1.next();
+
+ // Iterate through all the remaining NIs
+ Iterator<CarrierEthernetUni> uniIt2 = tempUniSet.iterator();
+ while (uniIt2.hasNext()) {
+
+ CarrierEthernetUni uni2 = uniIt2.next();
+
+ // Skip equals
+ if (uni1.equals(uni2)) {
+ continue;
+ }
+
+ // Do not establish connectivity between leaf NIs (applies to Rooted_Multipoint)
+ if (uni1.role().equals(CarrierEthernetUni.Role.LEAF)
+ && uni2.role().equals(CarrierEthernetUni.Role.LEAF)) {
+ continue;
+ }
+
+ // Calculate path assuming return paths are the same
+ // TODO: Handle the congruent paths case?
+ // TODO: Handle the case where uni1 and uni2 are on the same device
+ Set<Path> paths;
+ if (evc.type().equals(CarrierEthernetVirtualConnection.Type.POINT_TO_POINT)) {
+ // For point-to-point connectivity use the pre-calculated paths
+ // to make sure the shortest paths are chosen
+ paths = pathService.getPaths(uni1.cp().deviceId(), uni2.cp().deviceId());
+ } else {
+ // Recalculate path so that it's over the pre-calculated spanning tree
+ // FIXME: Find a more efficient way (avoid recalculating paths)
+ paths = pathService.getPaths(uni1.cp().deviceId(), uni2.cp().deviceId(),
+ new CarrierEthernetSpanningTreeWeight(topologyService));
+ }
+
+ // Just select any of the returned paths
+ // TODO: Select path in more sophisticated way and return null if any of the constraints cannot be met
+ Path path = paths.iterator().hasNext() ? paths.iterator().next() : null;
+
+ if (path == null) {
+ return null;
+ }
+
+ List<Link> links = new ArrayList<>();
+ links.add(createEdgeLink(uni1.cp(), true));
+ links.addAll(path.links());
+ links.add(createEdgeLink(uni2.cp(), false));
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // Get LTP pairs of ingress/egress NIs along the link path (non-LTP connect points are ignored)
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ // Note: INNIs should always appear in pairs
+ List<Pair<CarrierEthernetLogicalTerminationPoint, CarrierEthernetLogicalTerminationPoint>> ltpPairList
+ = new ArrayList<>();
+ CarrierEthernetLogicalTerminationPoint srcLtp = null, dstLtp = null;
+ // These are the roles that will be used for all pairs found below
+ CarrierEthernetLogicalTerminationPoint.Role srcLtpRole, dstLtpRole;
+ // The source in any pair will always have the same role as the LTP from which the paths starts
+ srcLtpRole = CarrierEthernetLogicalTerminationPoint.Role.valueOf((uni1).role().name());
+ // The destination in any pair will always have the same role as the LTP at which the path ends
+ dstLtpRole = CarrierEthernetLogicalTerminationPoint.Role.valueOf((uni2).role().name());
+ for (int i = 0 ; i < links.size() ; i++) {
+ // Try to get the destination LTP of a pair
+ if (srcLtp != null && i != 0) {
+ // If this is the last, use existing EVC UNI, else create a new FC LTP and set Role
+ dstLtp = (i == links.size() - 1) ?
+ new CarrierEthernetLogicalTerminationPoint(null, uni2) :
+ fcLtpFromCp(links.get(i).src(), dstLtpRole);
+ }
+ if (dstLtp != null) {
+ // Create a new LTP pair and null the srcLtp so that we can continue searching for a new pair
+ ltpPairList.add(Pair.of(srcLtp, dstLtp));
+ srcLtp = null;
+ }
+ // Try to get the source LTP of a pair
+ if (srcLtp == null && i != links.size() - 1) {
+ // If this is the first, use existing EVC UNI, else create a new FC LTP and set Role
+ srcLtp = (i == 0) ?
+ new CarrierEthernetLogicalTerminationPoint(null, uni1) :
+ fcLtpFromCp(links.get(i).dst(), srcLtpRole);
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Go through all the LTP pairs found and map each LTP to a set of LTPs (create it if it doesn't exist)
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // Note: Each LTP can only belong to a single set, so each set will eventually correspond to an FC
+
+ ltpPairList.forEach(ltpPair -> {
+ CarrierEthernetLogicalTerminationPoint ltp1 = ltpPair.getLeft();
+ CarrierEthernetLogicalTerminationPoint ltp2 = ltpPair.getRight();
+ if (ltpSetMap.containsKey(ltp1.id()) && !ltpSetMap.containsKey(ltp2.id())) {
+ // If one of the LTPs is already contained in a set, add the other one as well in that set
+ ltpSetMap.get(ltp1.id()).add(ltp2);
+ ltpSetMap.put(ltp2.id(), ltpSetMap.get(ltp1.id()));
+ } else if (ltpSetMap.containsKey(ltp2.id()) & !ltpSetMap.containsKey(ltp1.id())) {
+ // If one of the LTPs is already contained in a set, add the other one as well in that set
+ ltpSetMap.get(ltp2.id()).add(ltp1);
+ ltpSetMap.put(ltp1.id(), ltpSetMap.get(ltp2.id()));
+ } else if (!ltpSetMap.containsKey(ltp1.id()) && !ltpSetMap.containsKey(ltp2.id())){
+ // Create a new LTP set containing the two LTPs and map both to it
+ ltpSetMap.put(ltp1.id(), Sets.newHashSet(ltp1, ltp2));
+ ltpSetMap.put(ltp2.id(), ltpSetMap.get(ltp1.id()));
+ }
+ });
+ }
+ // Remove UNI from temporary set so that each pair is visited only once
+ uniIt1.remove();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Go through all unique LTP sets generated above and create the corresponding FCs
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ltpSetMap.values().stream().collect(Collectors.toSet()).forEach(ltpSet -> {
+ // Type is determined by number and type of LTPs in each set
+ CarrierEthernetVirtualConnection.Type fcType =
+ ltpSet.size() == 2 ? CarrierEthernetVirtualConnection.Type.POINT_TO_POINT
+ : CarrierEthernetConnection.Type.MULTIPOINT_TO_MULTIPOINT;
+ CarrierEthernetForwardingConstruct fc =
+ new CarrierEthernetForwardingConstruct(null, null, null, ltpSet, null);
+ // If one of the LTPs is LEAF, indicate FC as ROOT_MULTIPOINT
+ for (CarrierEthernetLogicalTerminationPoint ltp : fc.ltpSet()) {
+ if (ltp.role().equals(CarrierEthernetLogicalTerminationPoint.Role.LEAF)) {
+ fcType = CarrierEthernetConnection.Type.ROOT_MULTIPOINT;
+ break;
+ }
+ }
+ fc.setType(fcType);
+ fcSet.add(fc);
+ log.info("Created ForwardingConstruct comprising LogicalTerminationPoints {}",
+ ltpSet.stream().map(ltp -> ltp.id()).collect(Collectors.toList()));
+ });
+
+ return fcSet;
+ }
+
+ /**
+ * Reestablish connectivity for an existing EVC.
+ *
+ * @param evc the updated EVC definition
+ * @return the (potentially modified) EVC that was installed or null if EVC connectivity could not be established
+ */
+ public CarrierEthernetVirtualConnection updateEvc(CarrierEthernetVirtualConnection evc) {
+ // Just checking again
+ if (evcMap.containsKey(evc.id())) {
+ log.info("Updating existing EVC {}", evc.id());
+ removeEvc(evc.id());
+ }
+ return installEvc(evc);
+ }
+
+ /**
+ * Applies FC- specific LTP attributes to global LTPs or adds them to the global LTP map if not there.
+ *
+ * @param ltpSet set of FC-specific LTPs the attributes of which will be applied to the global LTPs
+ */
+ private void applyFcToGlobalLtps(Set<CarrierEthernetLogicalTerminationPoint> ltpSet) {
+ ltpSet.forEach(ltp -> {
+ if (!(ltpMap.keySet().contains(ltp.id()))) {
+ // Just add the LTP as it appears at the FC
+ addGlobalLtp(ltp);
} else {
- // Add UNI resources (BWP, CE-VLAN ID) to existing global UNI
- uniMap.get(uni.id()).addEvcUni((CarrierEthernetUni) uni);
+ // Add LTP resources (BWP, CE-VLAN ID, S-TAG) to existing global LTP
+ ltpMap.get(ltp.id()).ni().addEcNi(ltp.ni());
// Update config identifier
- uniMap.get(uni.id()).setCfgId(uni.cfgId());
+ ltpMap.get(ltp.id()).ni().setCfgId(ltp.ni().cfgId());
}
});
}
/**
- * Removes bandwidth profiles from the UNIs of an EVC and removes them if needed from the global UNI map.
+ * Removes bandwidth profiles from the UNIs of an FC.
*
- * @param evcId the EVC id
+ * @param fc the FC representation
*/
- private void removeBandwidthProfiles(String evcId) {
-
- evcMap.get(evcId).niSet().forEach(uni -> {
- // TODO: Check if the bandwidth profile really needs to be removed (e.g. may be CoS)
- ceProvisioner.removeBandwidthProfiles(evcMap.get(evcId));
-
- // Remove UNI resources (BWP, CE-VLAN ID) from global UNI
- uniMap.get(uni.id()).removeEvcUni((CarrierEthernetUni) uni);
- });
+ // TODO: Remove LTPs if needed from the global LTP/UNI map
+ private void removeFcFromGlobalLtps(CarrierEthernetForwardingConstruct fc) {
+ // TODO: Check if the bandwidth profile really needs to be removed (e.g. may be CoS)
+ ceProvisioner.removeBandwidthProfiles(fc);
+ // Remove LTP resources (BWP, CE-VLAN ID, S-TAG) from corresponding global LTPs
+ fc.ltpSet().forEach(ltp -> ltpMap.get(ltp.id()).ni().removeEcNi(ltp.ni()));
}
/**
@@ -352,18 +600,7 @@
* This will be called either from the deactivate method or as a response to a CLI/REST command.
* */
public void removeAllEvcs() {
- evcMap.keySet().forEach(evcId -> {
- CarrierEthernetVirtualConnection evc = evcMap.get(evcId);
- ceProvisioner.removeConnectivity(evc);
- ceProvisioner.removeBandwidthProfiles(evc);
- removeBandwidthProfiles(evcId);
- // Avoid excessively incrementing VLAN ids
- nextVlanId = (evc.vlanId().toShort() < nextVlanId ? evc.vlanId().toShort() : nextVlanId);
- // Decrement the global UNI and corresponding NI refCount
- // FIXME: Remove this as soon as EVCs are always made of FCs
- evc.niSet().forEach(uni -> uniMap.get(uni.id()).refCount().decrementAndGet());
- });
- evcMap.clear();
+ evcMap.keySet().forEach(evcId -> removeEvc(evcId));
}
/**
@@ -374,14 +611,13 @@
public void removeEvc(String evcId) {
if (evcMap.containsKey(evcId)) {
CarrierEthernetVirtualConnection evc = evcMap.get(evcId);
- ceProvisioner.removeConnectivity(evc);
- ceProvisioner.removeBandwidthProfiles(evc);
- removeBandwidthProfiles(evcId);
- // Avoid excessively incrementing VLAN ids
- nextVlanId = (evc.vlanId().toShort() < nextVlanId ? evc.vlanId().toShort() : nextVlanId);
- // Decrement the global UNI and corresponding NI refCount
- // FIXME: Remove this as soon as EVCs are always made of FCs
- evc.niSet().forEach(uni -> uniMap.get(uni.id()).refCount().decrementAndGet());
+ evc.fcSet().forEach(fc -> {
+ // Decrement the FC refCount to make removal possible
+ fc.refCount().decrementAndGet();
+ removeFc(fc.id());
+ });
+ // Avoid excessively incrementing EVC ids
+ nextEvcShortId = evc.shortId() < nextEvcShortId ? evc.shortId() : nextEvcShortId;
evcMap.remove(evcId);
}
}
@@ -396,76 +632,56 @@
// Try to set a unique VLAN id for the FC unless the EVC is being updated
// TODO: Add different connectivity types
- fc.evcLite().setVlanId(generateVlanId());
- if (fc.evcLite().vlanId() == null) {
+ // FIXME: This is an extra check to be able to generate/set VLAN id for FC before calling installFc
+ if (fc.vlanId() == null) {
+ fc.setVlanId(generateVlanId(null));
+ }
+ if (fc.vlanId() == null) {
log.error("No available VLAN id found.");
return null;
}
- // Verify that CE-VLAN ID is provided to either all UNIs or none and set the virtualEvc flag accordingly
- boolean isVirtual = false;
- Iterator<CarrierEthernetNetworkInterface> it = fc.evcLite().niSet().iterator();
- while (it.hasNext()) {
- CarrierEthernetUni uni = (CarrierEthernetUni) it.next();
- if (uni.ceVlanId() == null && isVirtual) {
- log.error("Could not validate the virtual status of the EVC.");
- return null;
- } else if (uni.ceVlanId() != null){
- isVirtual = true;
- }
- }
- fc.evcLite().setIsVirtual(isVirtual);
-
// Generate and set unique FC id
- fc.setId(generateEvcId(fc.evcLite()));
- fc.evcLite().setId(fc.id());
+ fc.setId(generateFcId(fc));
- Set<CarrierEthernetUni> validatedUniSet = new HashSet<>();
-
- // Check the UNIs of the EVC, possibly removing UNIs that are incompatible with existing ones
- it = fc.evcLite().niSet().iterator();
- while (it.hasNext()) {
- CarrierEthernetUni uni = (CarrierEthernetUni) it.next();
- // Change the name of the UNI's BWP to the EVC name if it is an EVC BWP
- if (uni.bwp().type().equals(CarrierEthernetBandwidthProfile.Type.EVC)) {
- uni.bwp().setId(fc.evcLite().id());
- }
- // Check first if UNI already exists by checking against the global UNI Map
- if (uniMap.keySet().contains(uni.id())) {
- CarrierEthernetUni existingUni = uniMap.get(uni.id());
- // Check if the EVC-specific UNI is compatible with the global one
- if (!(existingUni.validateEvcUni(uni))) {
- // If EVC is of ROOT_MULTIPOINT type and we have removed the root, return null
- if (fc.evcLite().type() == CarrierEthernetVirtualConnection.Type.ROOT_MULTIPOINT &&
- uni.role() == CarrierEthernetUni.Role.ROOT) {
- log.error("Root UNI could not be added to %s EVC.", fc.evcLite().type().name());
- return null;
- }
- log.warn("UNI {} could not be added to EVC.", uni.id());
- continue;
- } else {
- // Add UNI to evc description
- validatedUniSet.add(uni);
- }
- } else {
- // Add UNI to EVC description
- validatedUniSet.add(uni);
- }
- }
-
- // TODO: Add validation for INNIs/ENNIs as well
-
- // Update the FC LTP set, based on the UNIs actually used
Set<CarrierEthernetLogicalTerminationPoint> validatedLtpSet = new HashSet<>();
+
+ // Check the NIs of the FC, possibly removing NIs that are incompatible with existing ones
Iterator<CarrierEthernetLogicalTerminationPoint> ltpIt = fc.ltpSet().iterator();
- while(ltpIt.hasNext()) {
+ while (ltpIt.hasNext()) {
CarrierEthernetLogicalTerminationPoint ltp = ltpIt.next();
- if ((ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI))
- && (!validatedUniSet.contains(ltp.ni()))) {
- continue;
+ boolean ltpValidated = true;
+ if (ltp.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ CarrierEthernetUni uni = (CarrierEthernetUni) ltp.ni();
+ // Change the name of the UNI's BWP to the FC name if it is an EVC BWP
+ if (uni.bwp().type().equals(CarrierEthernetBandwidthProfile.Type.EVC)) {
+ // FIXME: Find a way to use the EVC name instead
+ uni.bwp().setId(fc.id());
+ }
}
- validatedLtpSet.add(ltp);
+ // Check first if LTP already exists by checking against the global LTP Map
+ if (ltpMap.keySet().contains(ltp.id())) {
+ CarrierEthernetNetworkInterface existingNi = ltpMap.get(ltp.id()).ni();
+ // Check if the FC-specific NI is compatible with the global one
+ if (!(existingNi.validateEcNi(ltp.ni()))) {
+ ltpValidated = false;
+ }
+ }
+ if (!ltpValidated) {
+ // If EVC is of ROOT_MULTIPOINT type and we have removed the root, return null
+ if (fc.type() == CarrierEthernetForwardingConstruct.Type.ROOT_MULTIPOINT &&
+ ltp.role() == CarrierEthernetLogicalTerminationPoint.Role.ROOT) {
+ log.error("Root LTP could not be added to %s FC.", fc.type().name());
+ return null;
+ }
+ log.warn("LTP {} could not be added to FC.", ltp.id());
+ continue;
+ } else {
+ // Add LTP to FC description
+ validatedLtpSet.add(ltp);
+ }
}
+
fc.setLtpSet(validatedLtpSet);
return fc;
@@ -486,55 +702,23 @@
fc.setId(null);
}
- fc = validateFc(fc);
-
- if (fc == null) {
+ if (validateFc(fc) == null) {
log.error("FC could not be installed, please check log for details.");
return null;
}
- // Temporary set for iterating through FC NI pairs
- Set<CarrierEthernetNetworkInterface> niSet = new HashSet<>();
- fc.ltpSet().forEach(ltp -> {
- niSet.add(ltp.ni());
- });
+ ceProvisioner.setupConnectivity(fc);
- ceProvisioner.setupConnectivity(niSet, fc.evcLite());
-
- // FIXME: Update the LTP set within setupConnectivity()
- // Update the FC LTP set, based on the NIs actually used
- Set<CarrierEthernetLogicalTerminationPoint> usedLtpSet = new HashSet<>();
- Iterator<CarrierEthernetLogicalTerminationPoint> ltpIt = fc.ltpSet().iterator();
- while (ltpIt.hasNext()) {
- CarrierEthernetLogicalTerminationPoint ltp = ltpIt.next();
- if (fc.evcLite().niSet().contains(ltp.ni())) {
- usedLtpSet.add(ltp);
- }
- }
- fc.setLtpSet(usedLtpSet);
-
- // Set FC state according to EVC Lite state
- fc.setState(CarrierEthernetForwardingConstruct.State.valueOf(fc.evcLite().state().name()));
- fc.setActiveState(CarrierEthernetForwardingConstruct.ActiveState.valueOf(fc.evcLite().activeState().name()));
-
- // If no pair was connected, do not register the FC
+ // If connectivity was not successful, then do not register the FC and do not apply BW profiles
if (fc.state().equals(CarrierEthernetForwardingConstruct.State.ACTIVE)) {
// Apply BWP-related resources (e.g. Meters) to the packet switches
- // FIXME: Hack - Resetting the evcLite set to only UNIs until setupConnectivity() uses FCs
- Set<CarrierEthernetNetworkInterface> tempNiSet = new HashSet<>();
- fc.ltpSet().forEach(ltp -> {
- if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- tempNiSet.add(ltp.ni());
- }
- });
- fc.evcLite().setNiSet(tempNiSet);
- ceProvisioner.applyBandwidthProfiles(fc.evcLite());
- // Apply the BWPs of the EVC UNI to the global UNIs, creating them if needed
- applyBandwidthProfiles(fc.evcLite().niSet());
+ ceProvisioner.applyBandwidthProfiles(fc);
+ // Apply the BWPs of the FC UNIs to the global UNIs, creating them if needed
+ //applyEvcToGlobalUnis(fc.uniSet());
+ applyFcToGlobalLtps(fc.ltpSet());
// Increment the global LTP and corresponding NI refCount
fc.ltpSet().forEach(ltp -> ltpMap.get(ltp.id()).refCount().incrementAndGet());
fcMap.put(fc.id(), fc);
- evcMap.put(fc.evcLite().id(), fc.evcLite());
}
return fc;
@@ -551,7 +735,8 @@
if (fcMap.containsKey(fc.id())) {
log.info("Updating existing FC {}", fc.id());
// Keep the VLAN ID of the original FC
- fc.evcLite().setVlanId(fcMap.get(fc.id()).evcLite().vlanId());
+ fc.setVlanId(fcMap.get(fc.id()).vlanId());
+ // FIXME: Currently FC update only possible for standalone FCs
removeFc(fc.id());
}
return installFc(fc);
@@ -563,49 +748,49 @@
* This will be called either from the deactivate method or as a response to a CLI command.
* */
public void removeAllFcs() {
- fcMap.keySet().forEach(fcId -> {
- removeEvc(fcMap.get(fcId).evcLite().id());
- // FIXME: Remove the UNI constraint as soon as EVCs are always made of FCs
- fcMap.get(fcId).ltpSet()
- .forEach(ltp -> {
- if (!(ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI))) {
- ltpMap.get(ltp.id()).refCount().decrementAndGet();
- }
- });
- });
- fcMap.clear();
+ fcMap.keySet().forEach(fcId -> removeFc(fcId));
}
/**
* Removes all resources associated with a specific FC.
*
* @param fcId the FC id
+ * @return the FC that was removed or null if removal failed
* */
- public void removeFc(String fcId) {
+ public CarrierEthernetForwardingConstruct removeFc(String fcId) {
if (fcMap.containsKey(fcId)) {
- // FIXME: For now, UNI refCount will be updated in removeEvc()
- removeEvc(fcMap.get(fcId).evcLite().id());
+ CarrierEthernetForwardingConstruct fc = fcMap.get(fcId);
+ if (fc.refCount().get() != 0) {
+ log.warn("Could not remove FC {}: RefCount is not zero", fc.id());
+ return null;
+ }
+ ceProvisioner.removeConnectivity(fc);
+ ceProvisioner.removeBandwidthProfiles(fc);
+ removeFcFromGlobalLtps(fc);
+ // Avoid excessively incrementing FC VLAN ids
+ nextVlanId = (fcMap.get(fcId).vlanId().toShort() < nextVlanId ? fcMap.get(fcId).vlanId().toShort() : nextVlanId);
// Decrement the global LTP and corresponding NI refCount
- // FIXME: Remove the UNI constraint as soon as EVCs are always constructed of FCs
- fcMap.get(fcId).ltpSet()
- .forEach(ltp -> {
- if (!(ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI))) {
- ltpMap.get(ltp.id()).refCount().decrementAndGet();
- }
- });
+ fcMap.get(fcId).ltpSet().forEach(ltp -> ltpMap.get(ltp.id()).refCount().decrementAndGet());
fcMap.remove(fcId);
+ return fc;
}
+ return null;
}
/**
* Generates a unique vlanId in the context of the CE app.
*
+ * @param extraVlanList additional vlanIds to be excluded from the vlanId generation
* @return the generated vlanId or null if none found
* */
- public VlanId generateVlanId() {
+ // FIXME: Providing extra VLAN list as argument is probably a temporary solution
+ public VlanId generateVlanId(List<VlanId> extraVlanList) {
- List<VlanId> vlanList = evcMap.values().stream().map(CarrierEthernetVirtualConnection::vlanId)
- .collect(Collectors.toList());
+ List<VlanId> vlanList = fcMap.values().stream().map(CarrierEthernetForwardingConstruct::vlanId)
+ .collect(Collectors.toList());
+ if (extraVlanList != null) {
+ vlanList.addAll(extraVlanList);
+ }
// If all vlanIds are being used return null, else try to find the next available one
if (vlanList.size() < VlanId.MAX_VLAN - 1) {
@@ -619,12 +804,36 @@
}
/**
+ * Generates a unique vlanId in the context of the CE app.
+ *
+ * @return the generated vlanId or null if none found
+ * */
+ private Short generateEvcShortId() {
+
+ List<Short> evcShortIdList = evcMap.values()
+ .stream()
+ .map(evc -> Short.valueOf(evc.shortId()))
+ .collect(Collectors.toList());
+
+ // If all vlanIds are being used return null, else try to find the next available one
+ if (evcShortIdList.size() < Short.MAX_VALUE - 1) {
+ while (evcShortIdList.contains(nextEvcShortId)) {
+ // Get next valid short
+ nextEvcShortId =
+ (nextEvcShortId >= Short.MAX_VALUE || nextEvcShortId <= 0 ? 1 : (short) (nextEvcShortId + 1));
+ }
+ }
+
+ return evcShortIdList.contains(nextEvcShortId) ? null : nextEvcShortId;
+ }
+
+ /**
* Generates a unique EVC id in the context of the CE app.
*
* @param evc the EVC representation
* @return the generated EVC id or null if none found
* */
- public String generateEvcId(CarrierEthernetVirtualConnection evc) {
+ private String generateEvcId(CarrierEthernetVirtualConnection evc) {
// TODO: Add different connectivity types
@@ -638,19 +847,31 @@
tmpType = "Tree";
}
- String evcId = "E" + (evc.isVirtual() ? "V" : "") + "P-" + tmpType + "-" +
- evc.vlanId().toString();
-
- return evcId;
+ return "E" + (evc.isVirtual() ? "V" : "") + "P-" + tmpType + "-" +
+ evc.shortId().toString();
}
/**
- * Remove an LTP from the set of global LTPs.
+ * Generates a unique FC id in the context of the CE app.
+ *
+ * @param fc the FC representation
+ * @return the generated FC id or null if none found
+ * */
+ private String generateFcId(CarrierEthernetForwardingConstruct fc) {
+
+ // TODO: Add different connectivity types
+
+ return "FC-" + fc.vlanId().toString();
+ }
+
+ /**
+ * Remove an LTP from the set of global LTPs, as well as the corresponding INNI LTP at the other end of the link.
*
*
* @param ltpId the id of the LTP to be removed
* @return the LTP that was removed or null in case of failure (didn't exist of refCount was not 0)
* */
+ // TODO: Add removeAllGlobalLtps method (or command only?)
public CarrierEthernetLogicalTerminationPoint removeGlobalLtp(String ltpId) {
if (!ltpMap.containsKey(ltpId)) {
@@ -665,12 +886,23 @@
// Remove LTP from ltpMap and (if needed) UNI from uniMap
CarrierEthernetLogicalTerminationPoint ltp = ltpMap.remove(ltpId);
- if (ltp.ni() instanceof CarrierEthernetUni) {
- removeGlobalUni(ltp.ni().id());
- }
-
// Add LTP to removed set
removedLtpSet.add(ltpId);
+ if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ removeGlobalUni(ltp.ni().id());
+ // Add UNI to removed set
+ // TODO: Check if this is right
+ removedUniSet.add(ltp.ni().id());
+ }
+
+ // Find cp at other end of link and try to remove both LTPs - assuming LTP ids are the same as connect point ids
+ if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.INNI)) {
+ Link link = linkService.getEgressLinks(ltp.ni().cp()).iterator().next();
+ String pairLtpId = link.dst().deviceId().toString() + "/" + link.dst().port().toString();
+ ltpMap.remove(pairLtpId);
+ // Add LTP to removed set
+ removedLtpSet.add(pairLtpId);
+ }
return ltp;
}
@@ -681,6 +913,7 @@
* @param uniId the id of the UNI to be removed
* @return the UNI that was removed or null in case of failure (didn't exist of refCount was not 0)
* */
+ // TODO: Add removeAllGlobalUnis method (or command only?)
public CarrierEthernetUni removeGlobalUni(String uniId) {
if (!uniMap.containsKey(uniId)) {
@@ -698,7 +931,7 @@
// Note: If refCount for UNI is not zero, then it should be for the corresponding LTP as well
ltpMap.remove(uniId);
- // Add UNI to removed set
+ // Add UNI and LTP to removed set
removedUniSet.add(uniId);
removedLtpSet.add(uniId);
@@ -865,7 +1098,7 @@
return null;
}
- return new CarrierEthernetLogicalTerminationPoint(cp, ltpId, ltpType);
+ return new CarrierEthernetLogicalTerminationPoint(cp, ltpId, ltpType, null);
}
/**
@@ -908,14 +1141,14 @@
}
/**
- * Adds a potential LTP and its UNI to the global LTP/UNI maps if it's not already there.
+ * Adds a potential LTP and its UNI or pair INNI to the global LTP/UNI maps if they are not already there.
*
* @param ltp the potential LTP to add to global LTP map
* @return the LTP that was added or null if it already existed
* */
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
- if (ltp.ni() != null && ltp.ni() instanceof CarrierEthernetUni) {
+ 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());
} else {
@@ -924,6 +1157,20 @@
}
// Add LTP only if it's not already there
if (!ltpMap.containsKey(ltp.id())) {
+ // Try to create and add INNI LTP at other end of link as well
+ if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.INNI)) {
+ Link link = linkService.getEgressLinks(ltp.ni().cp()).iterator().next();
+ CarrierEthernetLogicalTerminationPoint pairLtp =
+ generateLtp(link.dst(), CarrierEthernetNetworkInterface.Type.INNI);
+ if (pairLtp == null) {
+ return null;
+ }
+ if (!ltpMap.containsKey(pairLtp.id())) {
+ ltpMap.put(pairLtp.id(), pairLtp);
+ } else {
+ return null;
+ }
+ }
ltpMap.put(ltp.id(), ltp);
return ltp;
} else {
@@ -931,4 +1178,45 @@
}
}
+ /**
+ * Utility method to obtain an FC-specific LTP (UNI/INNI or ENNI) associated with a connect point.
+ *
+ * @param cp the connect point to check
+ * @return a new FC-specific LTP associated with cp if the corresponding global LTP exists or null otherwise
+ * */
+ private CarrierEthernetLogicalTerminationPoint fcLtpFromCp(ConnectPoint cp,
+ CarrierEthernetLogicalTerminationPoint.Role ltpRole) {
+ // Check first if cp is associated with a device
+ if (cp.deviceId() == null) {
+ return null;
+ }
+ // Assuming LTP id is the same as the connect point id
+ String cpId = cp.deviceId().toString() + "/" + cp.port().toString();
+ if (ltpMap.containsKey(cpId)) {
+ CarrierEthernetLogicalTerminationPoint ltp =
+ new CarrierEthernetLogicalTerminationPoint(cp, cpId, ltpMap.get(cpId).type(), ltpRole);
+ return ltp;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Utility method to obtain the first FC in a set which contains the LTP with the provided id.
+ *
+ * @param ltpId the LTP id to search
+ * @param fcSet the FC set to search
+ * @return a the first FC found in fcSet which contains an LTP with id ltpId, or null if no such FC is found
+ * */
+ // FIXME: Find more efficient way to do that
+ private CarrierEthernetForwardingConstruct getFcFromLtpId(String ltpId,
+ Set<CarrierEthernetForwardingConstruct> fcSet) {
+ // Get the first FC that contains the LTP with the provided id
+ for (CarrierEthernetForwardingConstruct fc : fcSet) {
+ if (!fc.ltpSet().stream().filter(ltp -> ltp.id().equals(ltpId)).collect(Collectors.toList()).isEmpty()) {
+ return fc;
+ }
+ }
+ return null;
+ }
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetNetworkInterface.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetNetworkInterface.java
index 4c0e3b4..f77cd62 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetNetworkInterface.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetNetworkInterface.java
@@ -30,7 +30,7 @@
/**
* Representation of a Carrier Ethernet Network Interface (UNI, INNI or ENNI).
*/
-public abstract class CarrierEthernetNetworkInterface {
+public abstract class CarrierEthernetNetworkInterface <E extends CarrierEthernetNetworkInterface> {
protected DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
@@ -187,6 +187,28 @@
*/
public abstract <T> T role();
+ /**
+ * Adds the resources associated with an EVC- or FC-specific NI to a global NI.
+ *
+ * @param ni the EVC- or FC-specific NI to be added
+ */
+ public abstract void addEcNi(E ni);
+
+ /**
+ * Removes the resources associated with an EVC- or FC-specific NI from a global NI.
+ *
+ * @param ni the EVC- or FC-specific NI to be removed
+ */
+ public abstract void removeEcNi(E ni);
+
+ /**
+ * Validates whether an EVC- or FC-specific NI is compatible with the corresponding global NI.
+ *
+ * @param ni the EVC- or FC-specific NI
+ * @return boolean value indicating whether the NIs are compatible
+ */
+ public abstract boolean validateEcNi(E ni);
+
@Override
public String toString() {
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
index 10bc43b..285fe5f 100644
--- 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
@@ -96,7 +96,7 @@
protected void deactivate() {}
@Override
- public void setNodeForwarding(CarrierEthernetVirtualConnection evc, CarrierEthernetNetworkInterface ingressNi,
+ public void setNodeForwarding(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface ingressNi,
Set<CarrierEthernetNetworkInterface> egressNiSet) {
if (ingressNi == null || egressNiSet.isEmpty()) {
@@ -104,20 +104,20 @@
return;
}
- flowObjectiveMap.putIfAbsent(evc.id(), new LinkedList<>());
+ flowObjectiveMap.putIfAbsent(fc.id(), new LinkedList<>());
// TODO: Get created FlowObjectives from this method
- createFlowObjectives(evc, ingressNi, egressNiSet);
+ createFlowObjectives(fc, ingressNi, egressNiSet);
}
/**
- * Creates and submits FlowObjectives depending on role of the device in the EVC and ingress/egress NI types.
+ * Creates and submits FlowObjectives depending on role of the device in the FC and ingress/egress NI types.
*
- * @param evc the EVC representation
+ * @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(CarrierEthernetVirtualConnection evc, CarrierEthernetNetworkInterface ingressNi,
+ private void createFlowObjectives(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface ingressNi,
Set<CarrierEthernetNetworkInterface> egressNiSet) {
/////////////////////////////////////////
@@ -132,7 +132,7 @@
TrafficTreatment.Builder filterTreatmentBuilder = DefaultTrafficTreatment.builder();
// In general, nodes would match on the VLAN tag assigned to the EVC/FC
- Criterion filterVlanIdCriterion = Criteria.matchVlanId(evc.vlanId());
+ Criterion filterVlanIdCriterion = Criteria.matchVlanId(fc.vlanId());
if ((ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.INNI))
|| (ingressNi.type().equals(CarrierEthernetNetworkInterface.Type.ENNI)) ) {
@@ -140,12 +140,12 @@
// 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(evc.vlanId());
+ 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(evc.vlanId());
+ filterTreatmentBuilder.pushVlan().setVlanId(fc.vlanId());
}
filteringObjectiveBuilder.addCondition(filterVlanIdCriterion);
@@ -156,14 +156,14 @@
}
flowObjectiveService.filter(ingressNi.cp().deviceId(), filteringObjectiveBuilder.add());
- flowObjectiveMap.get(evc.id()).addFirst(Pair.of(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(evc.vlanId())
+ .matchVlanId(fc.vlanId())
.matchInPort(ingressNi.cp().port())
.matchEthType(Ethernet.TYPE_IPV4)
.build();
@@ -205,14 +205,14 @@
flowObjectiveService.next(ingressNi.cp().deviceId(), nextObjective);
// Add all NextObjectives at the end of the list so that they will be removed last
- flowObjectiveMap.get(evc.id()).addLast(Pair.of(ingressNi.cp().deviceId(), nextObjective));
+ flowObjectiveMap.get(fc.id()).addLast(Pair.of(ingressNi.cp().deviceId(), nextObjective));
flowObjectiveService.forward(ingressNi.cp().deviceId(), forwardingObjective);
- flowObjectiveMap.get(evc.id()).addFirst(Pair.of(ingressNi.cp().deviceId(), forwardingObjective));
+ flowObjectiveMap.get(fc.id()).addFirst(Pair.of(ingressNi.cp().deviceId(), forwardingObjective));
}
@Override
- void applyBandwidthProfileResources(CarrierEthernetVirtualConnection evc, CarrierEthernetUni uni) {
+ void applyBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni) {
Dpid dpid = Dpid.dpid(uni.cp().deviceId().uri());
OpenFlowSwitch sw = controller.getSwitch(dpid);
@@ -223,12 +223,12 @@
}
// Create meters and add them to global MeterId map
- Set<DeviceMeterId> deviceMeterIdSet = deviceMeterIdMap.get(evc.id());
+ Set<DeviceMeterId> deviceMeterIdSet = deviceMeterIdMap.get(fc.id());
if (deviceMeterIdSet == null) {
deviceMeterIdSet = new HashSet<>();
}
deviceMeterIdSet.addAll(createMeters(uni));
- deviceMeterIdMap.put(evc.id(), deviceMeterIdSet);
+ deviceMeterIdMap.put(fc.id(), deviceMeterIdSet);
// Apply meters to already installed flows
@@ -251,10 +251,11 @@
}
ConnectPoint flowInCp = new ConnectPoint(flowRule.deviceId(), inPort);
// FIXME: Maybe check also if there is a group action?
- if (uni.cp().equals(flowInCp) && evc.vlanId().equals(flowInVlanId)) {
+ // 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(evc.id()).forEach(deviceMeterId -> {
+ deviceMeterIdMap.get(fc.id()).forEach(deviceMeterId -> {
if (deviceMeterId.deviceId().equals(flowRule.deviceId())) {
tmpDeviceMeterIdSet.add(deviceMeterId);
}
@@ -359,20 +360,19 @@
}
@Override
- void removeBandwidthProfileResources(String serviceId, CarrierEthernetUni uni) {
-
- removeMeters(serviceId, uni);
+ void removeBandwidthProfileResources(String fcId, CarrierEthernetUni uni) {
+ removeMeters(fcId, uni);
}
/**
- * Removes the meters associated with a specific UNI of a service.
+ * Removes the meters associated with a specific UNI of an FC.
*
- * @param serviceId the CE service ID
+ * @param fcId the EVC ID
* @param uni the UNI descriptor
* */
- private void removeMeters(String serviceId, CarrierEthernetUni uni) {
+ private void removeMeters(String fcId, CarrierEthernetUni uni) {
- Set<DeviceMeterId> newDeviceMeterIdSet = deviceMeterIdMap.get(serviceId);
+ Set<DeviceMeterId> newDeviceMeterIdSet = deviceMeterIdMap.get(fcId);
DeviceMeterId tmpDeviceMeterId;
Collection<Meter> meters = meterService.getMeters(uni.cp().deviceId());
@@ -382,7 +382,7 @@
Meter meter = it.next();
tmpDeviceMeterId = new DeviceMeterId(uni.cp().deviceId(), meter.id());
if (meter.appId().equals(appId) &&
- deviceMeterIdMap.get(serviceId).contains(tmpDeviceMeterId)) {
+ deviceMeterIdMap.get(fcId).contains(tmpDeviceMeterId)) {
MeterRequest.Builder mBuilder;
mBuilder = DefaultMeterRequest.builder()
.fromApp(meter.appId())
@@ -397,22 +397,22 @@
}
}
- deviceMeterIdMap.put(serviceId, newDeviceMeterIdSet);
+ deviceMeterIdMap.put(fcId, newDeviceMeterIdSet);
}
@Override
- void removeAllForwardingResources(CarrierEthernetVirtualConnection evc) {
- removeFlowObjectives(evc.id());
+ void removeAllForwardingResources(CarrierEthernetForwardingConstruct fc) {
+ removeFlowObjectives(fc.id());
}
/**
- * Removes all flow objectives installed by the application which are associated with a specific EVC.
+ * Removes all flow objectives installed by the application which are associated with a specific FC.
*
- * @param evcId the EVC id
+ * @param fcId the FC id
* */
- private void removeFlowObjectives(String evcId) {
- // Note: A Flow Rule cannot be shared by multiple services due to different VLAN or CE-VLAN ID match.
- List<Pair<DeviceId, Objective>> flowObjectiveList = flowObjectiveMap.remove(evcId);
+ 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()) {
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 4be8901..b34d12a 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
@@ -22,13 +22,13 @@
*/
public abstract class CarrierEthernetPacketNodeManager {
- abstract void setNodeForwarding(CarrierEthernetVirtualConnection evc, CarrierEthernetNetworkInterface srcNi,
+ abstract void setNodeForwarding(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface srcNi,
Set<CarrierEthernetNetworkInterface> dstNiSet);
- abstract void applyBandwidthProfileResources(CarrierEthernetVirtualConnection service, CarrierEthernetUni uni);
+ abstract void applyBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni);
- abstract void removeBandwidthProfileResources(String serviceId, CarrierEthernetUni uni);
+ abstract void removeBandwidthProfileResources(String fcId, CarrierEthernetUni uni);
- abstract void removeAllForwardingResources(CarrierEthernetVirtualConnection service);
+ abstract 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 e60f08d..bbbecad 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
@@ -35,14 +35,12 @@
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.Device;
-import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.PathService;
-import org.onosproject.net.topology.TopologyEdge;
-import org.onosproject.net.topology.TopologyService;
import org.onosproject.newoptical.api.OpticalConnectivityId;
import org.onosproject.newoptical.api.OpticalPathEvent;
import org.onosproject.newoptical.api.OpticalPathListener;
import org.onosproject.newoptical.api.OpticalPathService;
+import org.onosproject.net.topology.TopologyService;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;
@@ -133,39 +131,39 @@
factories.forEach(cfgRegistry::unregisterConfigFactory);
}
- // TODO: Get FC as input
- public void setupConnectivity(Set<CarrierEthernetNetworkInterface> niSet, CarrierEthernetVirtualConnection evc) {
+ public void setupConnectivity(CarrierEthernetForwardingConstruct fc) {
boolean allPairsConnected = true;
HashMap<CarrierEthernetNetworkInterface, HashSet<CarrierEthernetNetworkInterface>> ingressEgressNiMap =
new HashMap<>();
- // Temporary set for iterating through NI pairs
- Set<CarrierEthernetNetworkInterface> tempNiSet = new HashSet<>(niSet);
+ // Temporary set for iterating through LTP pairs
+ Set<CarrierEthernetLogicalTerminationPoint> tempLtpSet = new HashSet<>(fc.ltpSet());
- // Temporary set for indicating which NIs were finally included
- Set<CarrierEthernetNetworkInterface> usedNiSet = new HashSet<>();
+ // Temporary set for indicating which LTPs were finally included
+ Set<CarrierEthernetLogicalTerminationPoint> usedLtpSet = new HashSet<>();
- Iterator<CarrierEthernetNetworkInterface> niIt1 = tempNiSet.iterator();
- while (niIt1.hasNext()) {
+ Iterator<CarrierEthernetLogicalTerminationPoint> ltpIt1 = tempLtpSet.iterator();
+ while (ltpIt1.hasNext()) {
- CarrierEthernetNetworkInterface ni1 = niIt1.next();
+ CarrierEthernetLogicalTerminationPoint ltp1 = ltpIt1.next();
// Iterate through all the remaining NIs
- Iterator<CarrierEthernetNetworkInterface> niIt2 = tempNiSet.iterator();
- while (niIt2.hasNext()) {
+ Iterator<CarrierEthernetLogicalTerminationPoint> ltpIt2 = tempLtpSet.iterator();
+ while (ltpIt2.hasNext()) {
- CarrierEthernetNetworkInterface ni2 = niIt2.next();
+ CarrierEthernetLogicalTerminationPoint ltp2 = ltpIt2.next();
// Skip equals
- if (ni1.equals(ni2)) {
+ if (ltp1.equals(ltp2)) {
continue;
}
// Do not establish connectivity between leaf NIs (applies to Rooted_Multipoint)
- if (ni1.role().equals(CarrierEthernetUni.Role.LEAF)
- && ni2.role().equals(CarrierEthernetUni.Role.LEAF)) {
+ // FIXME: Use proper LTP roles
+ if (ltp1.role().equals(CarrierEthernetLogicalTerminationPoint.Role.LEAF)
+ && ltp2.role().equals(CarrierEthernetLogicalTerminationPoint.Role.LEAF)) {
continue;
}
@@ -175,88 +173,88 @@
Bandwidth reqBw;
- if (ni1.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- reqBw = ((CarrierEthernetUni) ni1).bwp().cir();
- } else if (ni2.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
- reqBw = ((CarrierEthernetUni) ni2).bwp().cir();
+ if (ltp1.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ reqBw = ((CarrierEthernetUni) ltp1.ni()).bwp().cir();
+ } else if (ltp2.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ reqBw = ((CarrierEthernetUni) ltp2.ni()).bwp().cir();
} else {
reqBw = Bandwidth.bps((double) 0);
}
- opticalConnectId = setupOpticalConnectivity(ni1.cp(), ni2.cp(), reqBw, evc.latency());
+ opticalConnectId = setupOpticalConnectivity(ltp1.ni().cp(), ltp2.ni().cp(), reqBw, fc.maxLatency());
if (opticalConnectId == null ||
opticalConnectStatusMap.get(opticalConnectId) != OpticalPathEvent.Type.PATH_INSTALLED) {
log.error("Could not establish optical connectivity between {} and {}" +
- " (optical id and status: {}, {})", ni1.cp(), ni2.cp(), opticalConnectId,
+ " (optical id and status: {}, {})",
+ ltp1.ni().cp(), ltp2.ni().cp(), opticalConnectId,
(opticalConnectId == null ? "null" : opticalConnectStatusMap.get(opticalConnectId)));
allPairsConnected = false;
continue;
}
if (opticalConnectId != null) {
- evc.setMetroConnectivityId(opticalConnectId);
- evc.setMetroConnectivityStatus(opticalConnectStatusMap.get(opticalConnectId));
+ fc.setMetroConnectivityId(opticalConnectId);
+ fc.setMetroConnectivityStatus(opticalConnectStatusMap.get(opticalConnectId));
}
- log.info("Metro connectivity id and status for EVC {}: {}, {}", evc.id(),
- evc.metroConnectivity().id(), evc.metroConnectivity().status());
+ log.info("Metro connectivity id and status for FC {}: {}, {}", fc.id(),
+ fc.metroConnectivity().id(), fc.metroConnectivity().status());
if (opticalConnectId != null) {
// TODO: find vlanIds for both CO and store to service
opticalPathService.getPath(opticalConnectId).ifPresent(links -> {
getVlanTag(links).ifPresent(vlan -> {
- log.info("VLAN ID {} is assigned to CE service {}", vlan, evc.id());
- evc.setVlanId(vlan);
+ log.info("VLAN ID {} is assigned to CE service {}", vlan, fc.id());
+ fc.setVlanId(vlan);
});
getTransportVlanTag(links).ifPresent(vlan -> {
- log.info("Transport VLAN ID {} is assigned to CE service {}", vlan, evc.id());
- evc.setTransportVlanId(vlan);
+ log.info("Transport VLAN ID {} is assigned to CE service {}", vlan, fc.id());
+ fc.setTransportVlanId(vlan);
});
});
}
}
- // Update the cpPathHashSet based on the calculated paths
- if (!updateIngressEgressNiMap(ni1, ni2, ingressEgressNiMap, evc.congruentPaths(), evc.type())) {
+ // Update the ingress-egress NI map based on the calculated paths
+ if (!updateIngressEgressNiMap(ltp1.ni(), ltp2.ni(), ingressEgressNiMap,
+ fc.congruentPaths(), fc.type())) {
removeOpticalConnectivity(opticalConnectId);
allPairsConnected = false;
continue;
}
// Indicate that connection for at least one NI pair has been established
- evc.setState(CarrierEthernetVirtualConnection.State.ACTIVE);
+ fc.setState(CarrierEthernetForwardingConstruct.State.ACTIVE);
// Add NIs to the set of NIs used by the EVC
- usedNiSet.add(ni1);
- usedNiSet.add(ni2);
+ usedLtpSet.add(ltp1);
+ usedLtpSet.add(ltp2);
}
// Remove NI from temporary set so that each pair is visited only once
- niIt1.remove();
+ ltpIt1.remove();
}
// Establish connectivity using the ingressEgressNiMap
ingressEgressNiMap.keySet().forEach(srcNi -> {
// Set forwarding only on packet switches
if (deviceService.getDevice(srcNi.cp().deviceId()).type().equals(Device.Type.SWITCH)) {
- ceOfPktNodeManager.setNodeForwarding(evc, srcNi, ingressEgressNiMap.get(srcNi));
+ ceOfPktNodeManager.setNodeForwarding(fc, srcNi, ingressEgressNiMap.get(srcNi));
}
});
// Update the NI set, based on the NIs actually used
- evc.setNiSet(usedNiSet);
+ fc.setLtpSet(usedLtpSet);
- if (evc.state().equals(CarrierEthernetVirtualConnection.State.ACTIVE)) {
- if (allPairsConnected) {
- evc.setActiveState(CarrierEthernetVirtualConnection.ActiveState.FULL);
- } else {
- evc.setActiveState(CarrierEthernetVirtualConnection.ActiveState.PARTIAL);
+ if (fc.isActive()) {
+ if (!allPairsConnected) {
+ fc.setState(CarrierEthernetConnection.State.PARTIAL);
}
}
}
/**
- * Select a feasible link path between two NIs
+ * Select feasible link paths between two NIs in both directions and update ingressEgressNiMap accordingly
*
* @param ni1 the first NI
* @param ni2 the second NI
@@ -270,6 +268,7 @@
boolean congruentPaths, CarrierEthernetVirtualConnection.Type evcType) {
// Find the paths for both directions at the same time, so that we can skip the pair if needed
+ // TODO: Handle the case when ni1 and ni2 are on the same device - probably in the generateLinkList
List<Link> forwardLinks = generateLinkList(ni1.cp(), ni2.cp(), evcType);
List<Link> backwardLinks =
congruentPaths ? generateInverseLinkList(forwardLinks) : generateLinkList(ni2.cp(), ni1.cp(), evcType);
@@ -294,17 +293,25 @@
HashMap<CarrierEthernetNetworkInterface,
HashSet<CarrierEthernetNetworkInterface>> ingressEgressNiMap
) {
+ // FIXME: Fix the method - avoid generating GENERIC NIs if not needed
// Add the src and destination NIs as well as the associated Generic NIs
ingressEgressNiMap.putIfAbsent(srcNi, new HashSet<>());
- ingressEgressNiMap.get(srcNi).add(new CarrierEthernetGenericNi(linkList.get(1).src(), null));
- CarrierEthernetGenericNi ingressNi =
- new CarrierEthernetGenericNi(linkList.get(linkList.size() - 2).dst(), null);
- ingressEgressNiMap.putIfAbsent(ingressNi, new HashSet<>());
- ingressEgressNiMap.get(ingressNi).add(dstNi);
+ // Add last hop entry only if srcNi, dstNi aren't on same device (in which case srcNi, ingressNi would coincide)
+ if (!srcNi.cp().deviceId().equals(dstNi.cp().deviceId())) {
+ // If srcNi, dstNi are not on the same device, create mappings to/from new GENERIC NIs
+ ingressEgressNiMap.get(srcNi).add(new CarrierEthernetGenericNi(linkList.get(1).src(), null));
+ CarrierEthernetGenericNi ingressNi =
+ new CarrierEthernetGenericNi(linkList.get(linkList.size() - 2).dst(), null);
+ ingressEgressNiMap.putIfAbsent(ingressNi, new HashSet<>());
+ ingressEgressNiMap.get(ingressNi).add(dstNi);
+ } else {
+ // If srcNi, dstNi are on the same device, this is the only mapping that will be created
+ ingressEgressNiMap.get(srcNi).add(dstNi);
+ }
// Go through the links and create/add the intermediate NIs
for (int i = 1; i < linkList.size() - 2; i++) {
- ingressNi = new CarrierEthernetGenericNi(linkList.get(i).dst(), null);
+ CarrierEthernetGenericNi ingressNi = new CarrierEthernetGenericNi(linkList.get(i).dst(), null);
ingressEgressNiMap.putIfAbsent(ingressNi, new HashSet<>());
ingressEgressNiMap.get(ingressNi).add(new CarrierEthernetGenericNi(linkList.get(i + 1).src(), null));
}
@@ -312,28 +319,35 @@
private List<Link> generateLinkList(ConnectPoint cp1, ConnectPoint cp2,
CarrierEthernetVirtualConnection.Type evcType) {
-
Set<Path> paths;
- if (evcType.equals(CarrierEthernetVirtualConnection.Type.POINT_TO_POINT)) {
- // For point-to-point connectivity use the pre-calculated paths to make sure the shortest paths are chosen
- paths = pathService.getPaths(cp1.deviceId(), cp2.deviceId());
- } else {
- // Recalculate path so that it's over the pre-calculated spanning tree
- // FIXME: Find a more efficient way (avoid recalculating paths)
- paths = pathService.getPaths(cp1.deviceId(), cp2.deviceId(), new SpanningTreeWeight());
- }
+ Path path = null;
- // Just select any of the returned paths
- // TODO: Select path in more sophisticated way and return null if any of the constraints cannot be met
- Path path = paths.iterator().hasNext() ? paths.iterator().next() : null;
+ if (!cp1.deviceId().equals(cp2.deviceId())) {
+ // If cp1 and cp2 are not on the same device a path must be found
+ if (evcType.equals(CarrierEthernetVirtualConnection.Type.POINT_TO_POINT)) {
+ // For point-to-point connectivity use pre-calculated paths to make sure the shortest paths are chosen
+ paths = pathService.getPaths(cp1.deviceId(), cp2.deviceId());
+ } else {
+ // Recalculate path so that it's over the pre-calculated spanning tree
+ // FIXME: Find a more efficient way (avoid recalculating paths)
+ paths = pathService.getPaths(cp1.deviceId(), cp2.deviceId(),
+ new CarrierEthernetSpanningTreeWeight(topologyService));
+ }
- if (path == null) {
- return null;
+ // Just select any of the returned paths
+ // TODO: Select path in more sophisticated way and return null if any of the constraints cannot be met
+ path = paths.iterator().hasNext() ? paths.iterator().next() : null;
+
+ if (path == null) {
+ return null;
+ }
}
List<Link> links = new ArrayList<>();
links.add(createEdgeLink(cp1, true));
- links.addAll(path.links());
+ if (!cp1.deviceId().equals(cp2.deviceId())) {
+ links.addAll(path.links());
+ }
links.add(createEdgeLink(cp2, false));
return links;
@@ -363,31 +377,34 @@
return inverseLinks;
}
- public void removeConnectivity(CarrierEthernetVirtualConnection evc) {
+ public void removeConnectivity(CarrierEthernetForwardingConstruct fc) {
// TODO: Add here the same call for all node manager types
- ceOfPktNodeManager.removeAllForwardingResources(evc);
- removeOpticalConnectivity(evc.metroConnectivity().id());
+ ceOfPktNodeManager.removeAllForwardingResources(fc);
+ removeOpticalConnectivity(fc.metroConnectivity().id());
}
/**
- * Applies bandwidth profiles to the UNIs of an EVC.
+ * Applies bandwidth profiles to the UNIs of an FC.
*
- * @param evc the EVC representation
+ * @param fc the FC representation
*/
- public void applyBandwidthProfiles(CarrierEthernetVirtualConnection evc) {
+ public void applyBandwidthProfiles(CarrierEthernetForwardingConstruct fc) {
// TODO: Select node manager depending on device protocol
- evc.niSet().forEach((uni -> ceOfPktNodeManager.applyBandwidthProfileResources(evc, (CarrierEthernetUni) uni)));
+ fc.uniSet().forEach(uni -> ceOfPktNodeManager.applyBandwidthProfileResources(fc, uni));
}
/**
- * Removes bandwidth profiles from the UNIs of an EVC.
+ * Removes bandwidth profiles from the UNIs of an FC.
*
- * @param evc the EVC representation
+ * @param fc the FC representation
*/
- public void removeBandwidthProfiles(CarrierEthernetVirtualConnection evc) {
+ public void removeBandwidthProfiles(CarrierEthernetForwardingConstruct fc) {
// TODO: Select node manager depending on device protocol
- evc.niSet().forEach(uni -> ceOfPktNodeManager
- .removeBandwidthProfileResources(evc.id(), (CarrierEthernetUni) uni));
+ fc.ltpSet().forEach((ltp -> {
+ if (ltp.ni().type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ ceOfPktNodeManager.removeBandwidthProfileResources(fc.id(), (CarrierEthernetUni) ltp.ni());
+ }
+ }));
}
private class OpticalEventListener implements OpticalPathListener {
@@ -511,31 +528,4 @@
}
}
-
- /**
- * Checks if a connect point is on the pre-calculated spanning tree.
- *
- * @param cp the connect point to check
- * @return true if the connect point is on the spanning tree and false otherwise
- */
- private boolean isBroadCastPoint(ConnectPoint cp) {
- // TODO: Get topology snapshot so that same spanning tree is used by all pairs if topology changes
- return topologyService.isBroadcastPoint(topologyService.currentTopology(), cp);
- }
-
- /**
- * Weight class to cause path selection only on the pre-calculated spanning tree.
- */
- private class SpanningTreeWeight implements LinkWeight {
-
- @Override
- public double weight(TopologyEdge edge) {
- if (!isBroadCastPoint(edge.link().src()) || !isBroadCastPoint(edge.link().dst())) {
- return -1;
- } else {
- return 1;
- }
- }
- }
-
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetSpanningTreeWeight.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetSpanningTreeWeight.java
new file mode 100644
index 0000000..c5f5e4a
--- /dev/null
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetSpanningTreeWeight.java
@@ -0,0 +1,64 @@
+/*
+ * 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 org.onosproject.net.ConnectPoint;
+import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.TopologyEdge;
+import org.onosproject.net.topology.TopologyService;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Weight class to cause path selection only on the pre-calculated spanning tree.
+ */
+public class CarrierEthernetSpanningTreeWeight implements LinkWeight {
+
+ private final Logger log = getLogger(getClass());
+
+ protected TopologyService topologyService = null;
+
+ public CarrierEthernetSpanningTreeWeight(TopologyService topologyService) {
+ this.topologyService = topologyService;
+ }
+
+ @Override
+ public double weight(TopologyEdge edge) {
+ if (!isBroadCastPoint(edge.link().src()) || !isBroadCastPoint(edge.link().dst())) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * Checks if a connect point is on the pre-calculated spanning tree.
+ *
+ * @param cp the connect point to check
+ * @return true if the connect point is on the spanning tree and false otherwise
+ */
+ private boolean isBroadCastPoint(ConnectPoint cp) {
+ // TODO: Get topology snapshot so that same spanning tree is used by all pairs if topology changes
+ if (cp == null) {
+ log.info("Cp is null!");
+ }
+ if (topologyService == null) {
+ log.info("topologyservice is null!");
+ }
+ return topologyService.isBroadcastPoint(topologyService.currentTopology(), cp);
+ }
+}
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 4c75831..75ac1b6 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
@@ -38,7 +38,7 @@
* 1. As a global UNI descriptor containing one or more BW profiles
* 2. As a service-specific UNI descriptor containing a single BW profile and including a type (root, leaf)
*/
-public class CarrierEthernetUni extends CarrierEthernetNetworkInterface {
+public class CarrierEthernetUni extends CarrierEthernetNetworkInterface <CarrierEthernetUni> {
private final Logger log = getLogger(getClass());
@@ -109,11 +109,26 @@
}
/**
- * Adds the resources associated with an EVC-specific UNI to a global UNI.
+ * Adds a BW profile to a UNI.
*
- * @param uni the EVC UNI to be added
+ * @param bwp the BWP to be added
*/
- public void addEvcUni(CarrierEthernetUni uni) {
+ public void addBandwidthProfile(CarrierEthernetBandwidthProfile 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()));
+ }
+
+ /**
+ * Adds the resources associated with an EVC- or FC-specific UNI to a global UNI.
+ *
+ * @param uni the EVC- or FC-specific UNI to be added
+ */
+ @Override
+ public void addEcNi(CarrierEthernetUni uni) {
// Add CE-VLAN ID
if (uni.ceVlanId() != VlanId.NONE) {
@@ -130,25 +145,12 @@
}
/**
- * Adds a BW profile to a UNI.
+ * Removes the resources associated with an EVC- or FC-specific UNI from a global UNI.
*
- * @param bwp the BWP to be added
+ * @param uni the EVC- or FC-specific UNI to be removed
*/
- public void addBandwidthProfile(CarrierEthernetBandwidthProfile 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()));
- }
-
- /**
- * Removes the resources associated with a service-specific UNI from a global UNI.
- *
- * @param uni the service UNI to be added
- */
- public void removeEvcUni(CarrierEthernetUni uni) {
+ @Override
+ public void removeEcNi(CarrierEthernetUni uni) {
// Remove UNI CE-VLAN ID
if (uni.ceVlanId() != VlanId.NONE) {
@@ -165,12 +167,13 @@
}
/**
- * Validates whether an EVC-specific UNI is compatible with a global UNI.
+ * Validates whether an EVC- or FC-specific UNI is compatible with the corresponding global UNI.
*
- * @param uni the EVC-specific UNI
+ * @param uni the EVC- or FC-specific UNI
* @return boolean value indicating whether the UNIs are compatible
*/
- public boolean validateEvcUni(CarrierEthernetUni uni) {
+ @Override
+ public boolean validateEcNi(CarrierEthernetUni uni) {
// Check if the CE-VLAN ID of the UNI is already included in global UNI
if (uni.ceVlanId() != VlanId.NONE) {
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetVirtualConnection.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetVirtualConnection.java
index 81c7aed..fb58a8b 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetVirtualConnection.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/app/CarrierEthernetVirtualConnection.java
@@ -15,197 +15,46 @@
*/
package org.onosproject.ecord.carrierethernet.app;
-import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.VlanId;
-import org.onosproject.newoptical.api.OpticalConnectivityId;
-import org.onosproject.newoptical.api.OpticalPathEvent;
-import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
+import java.time.Duration;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Representation of a Carrier Ethernet EVC.
*/
-public class CarrierEthernetVirtualConnection {
+public class CarrierEthernetVirtualConnection extends CarrierEthernetConnection {
- public enum Type {
-
- POINT_TO_POINT("Point_To_Point"),
- MULTIPOINT_TO_MULTIPOINT("Multipoint_To_Multipoint"),
- ROOT_MULTIPOINT("Root_Multipoint");
-
- private String value;
-
- Type(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- public static Type fromString(String value) {
- if (value != null) {
- for (Type b : Type.values()) {
- if (value.equals(b.value)) {
- return b;
- }
- }
- }
- throw new IllegalArgumentException("Type " + value + " is not valid");
- }
- }
-
- public enum State {
-
- ACTIVE("Active"),
- INACTIVE("Inactive");
-
- private String value;
-
- State(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- public static State fromString(String value) {
- if (value != null) {
- for (State b : State.values()) {
- if (value.equals(b.value)) {
- return b;
- }
- }
- }
- throw new IllegalArgumentException("State " + value + " is not valid");
- }
- }
-
- public enum ActiveState {
-
- FULL("Full"),
- PARTIAL("Partial");
-
- private String value;
-
- ActiveState(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return value;
- }
- }
-
- // FIXME: single vlanId is a hack for ONS2016. CE service must store vlanId for each CO.
- protected String evcId;
- protected String evcCfgId;
- protected Type evcType;
- protected State evcState;
- protected ActiveState evcActiveState;
- protected VlanId vlanId;
- private VlanId transportVlanId;
- protected boolean isVirtual;
- protected Integer maxNumUni;
- protected Set<CarrierEthernetNetworkInterface> niSet;
- protected Duration latency;
- protected CarrierEthernetMetroConnectivity metroConnectivity;
- protected boolean congruentPaths;
- // Set to true if both directions should use the same path
- private static final boolean CONGRUENT_PATHS = true;
-
- private static final Duration DEFAULT_LATENCY = Duration.ofMillis(50);
+ private Short shortId;
+ private Set<CarrierEthernetUni> uniSet;
+ private boolean isVirtual;
+ private Integer maxNumUni;
+ private Set<CarrierEthernetForwardingConstruct> fcSet;
// Maximum possible number of UNIs for non-Point-to-Point EVCs
public static final Integer MAX_NUM_UNI = 1000;
// Note: evcId should be provided only when updating an existing service
- public CarrierEthernetVirtualConnection(String evcId, String evcCfgId, Type evcType, Integer maxNumUni,
- Set<CarrierEthernetNetworkInterface> niSet) {
- this.evcId = evcId;
- this.evcCfgId = evcCfgId;
- this.evcType = evcType;
- this.evcState = State.INACTIVE;
- this.evcActiveState = null;
- this.maxNumUni = (maxNumUni != null ? maxNumUni : (evcType.equals(Type.POINT_TO_POINT) ? 2 : MAX_NUM_UNI));
- this.vlanId = null;
- this.niSet = new HashSet<>(niSet);
- this.congruentPaths = CONGRUENT_PATHS;
- this.latency = DEFAULT_LATENCY;
- this.metroConnectivity = new CarrierEthernetMetroConnectivity(null, OpticalPathEvent.Type.PATH_REMOVED);
+ public CarrierEthernetVirtualConnection(String id, String cfgId, Type type, Integer maxNumUni,
+ Set<CarrierEthernetUni> uniSet,
+ Duration maxLatency) {
+ super(id, cfgId, type, maxLatency);
+ this.maxNumUni = (maxNumUni != null ? maxNumUni : (type.equals(Type.POINT_TO_POINT) ? 2 : MAX_NUM_UNI));
+ this.uniSet = new HashSet<>(uniSet);
+ this.fcSet = new HashSet<>();
+ this.shortId = null;
}
/**
- * Returns service identifier.
+ * Returns numerical identifier.
*
- * @return service identifier
+ * @return numerical identifier
*/
- public String id() {
- return evcId;
- }
-
- /**
- * Returns service config identifier.
- *
- * @return service config identifier
- */
- public String cfgId() {
- return evcCfgId;
- }
-
- /**
- * Returns type of service.
- *
- * @return type of service
- */
- public Type type() {
- return evcType;
- }
-
- /**
- * Returns connectivity state of the EVC.
- *
- * @return connectivity state
- */
- public State state() {
- return evcState;
- }
-
- /**
- * Returns active connectivity state of the EVC.
- *
- * @return active connectivity state
- */
- public ActiveState activeState() {
- return evcActiveState;
- }
-
- /**
- * Returns Vlan id.
- *
- * @return Vlan id
- */
- public VlanId vlanId() {
- return vlanId;
- }
-
- /**
- * Returns Transport Vlan ID.
- *
- * @return Transport Vlan ID.
- */
- @Beta
- public VlanId transportVlanId() {
- return transportVlanId;
+ public Short shortId() {
+ return shortId;
}
/**
@@ -229,95 +78,44 @@
*
* @return set of UNIs
*/
- public Set<CarrierEthernetNetworkInterface> niSet() {
- return ImmutableSet.copyOf(niSet);
+ public Set<CarrierEthernetUni> uniSet() {
+ return ImmutableSet.copyOf(uniSet);
}
/**
- * Returns latency constraint.
+ * Returns the set of FCs associated with the EVC.
*
- * @return latency constraint
+ * @return set of FCs associated with the EVC
*/
- public Duration latency() {
- return latency;
+ public Set<CarrierEthernetForwardingConstruct> fcSet() {
+ return ImmutableSet.copyOf(fcSet);
}
/**
- * Returns true if service requires congruent paths.
+ * Set numerical identifier.
*
- * @return true if congruent paths required
+ * @param shortId the numerical identifier to set
*/
- public boolean congruentPaths() {
- return congruentPaths;
- }
-
- /**
- * Sets service identifier.
- *
- * @param serviceId the service identifier to set
- */
- public void setId(String serviceId) {
- this.evcId = serviceId;
- }
-
- /**
- * Sets service config identifier.
- *
- * @param serviceCfgId service config identifier
- */
- public void setCfgId(String serviceCfgId) {
- this.evcCfgId = serviceCfgId;
+ public void setShortId(Short shortId) {
+ this.shortId = shortId;
}
/**
* Sets the set of UNIs.
*
- * @param niSet the set of UNIs to be set
+ * @param uniSet the set of UNIs to be set
*/
- public void setNiSet(Set<CarrierEthernetNetworkInterface> niSet) {
- this.niSet = niSet;
+ public void setUniSet(Set<CarrierEthernetUni> uniSet) {
+ this.uniSet = uniSet;
}
/**
- * Sets the connectivity state of the EVC.
+ * Sets the set of FCs.
*
- * @param evcState the connectivity state to set
+ * @param fcSet the set of UNIs to be set
*/
- public void setState(State evcState) { this.evcState = evcState; }
-
- /**
- * Sets the active connectivity state of the EVC.
- *
- * @param evcActiveState the active connectivity state to set
- */
- public void setActiveState(ActiveState evcActiveState) { this.evcActiveState = evcActiveState; }
-
- /**
- * Sets the value of the congruent paths parameter.
- *
- * @param congruentPaths the congruent paths parameter value to set
- */
- public void setCongruentPaths(boolean congruentPaths) {
- this.congruentPaths = congruentPaths;
- }
-
- /**
- * Sets the vlanId to be used by the service.
- *
- * @param vlanId the vlanId to set
- */
- public void setVlanId(VlanId vlanId) {
- this.vlanId = vlanId;
- }
-
- /**
- * Sets the vlanId to be used by the transport.
- *
- * @param vlan the vlanId to set
- */
- @Beta
- public void setTransportVlanId(VlanId vlan) {
- this.transportVlanId = vlan;
+ public void setFcSet(Set<CarrierEthernetForwardingConstruct> fcSet) {
+ this.fcSet = fcSet;
}
/**
@@ -329,44 +127,15 @@
this.isVirtual = isVirtual;
}
- /**
- * Gets metro connectivity id.
- *
- * @return the metro connectivity of the service
- */
- public CarrierEthernetMetroConnectivity metroConnectivity() {
- return this.metroConnectivity;
- }
-
- /**
- * Sets metro connectivity id.
- *
- * @param id the metro connectivity identifier to set
- */
- public void setMetroConnectivityId(OpticalConnectivityId id) {
- this.metroConnectivity.setId(id);
- }
-
- /**
- * Sets metro connectivity status.
- *
- * @param status the metro connectivity status
- */
- public void setMetroConnectivityStatus(OpticalPathEvent.Type status) {
- this.metroConnectivity.setStatus(status);
- }
-
@Override
public String toString() {
return toStringHelper(this)
.omitNullValues()
- .add("id", evcId)
- .add("cfgId", evcCfgId)
- .add("type", evcType)
- .add("vlanId", vlanId)
- .add("transportVlanId", transportVlanId)
- .add("metroConnectId", (metroConnectivity.id() == null ? "null" : metroConnectivity.id().id()))
- .add("NIs", niSet).toString();
+ .add("id", id)
+ .add("cfgId", cfgId)
+ .add("type", type)
+ .add("UNIs", uniSet)
+ .add("FCs", fcSet).toString();
}
}
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 c0f663b..b95236b 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
@@ -34,7 +34,7 @@
import java.util.Set;
/**
- * CLI command for installing EVCs.
+ * CLI command for installing an Ethernet Virtual Connection.
*/
@Command(scope = "onos", name = "ce-evc-create",
description = "Carrier Ethernet EVC creation command.")
@@ -80,9 +80,9 @@
CarrierEthernetManager ceManager = get(CarrierEthernetManager.class);
CarrierEthernetVirtualConnection evc = new CarrierEthernetVirtualConnection(argEvcId, argEvcCfgId,
- generateEvcType(), generateMaxNumUni(), generateUniSet());
+ generateEvcType(), generateMaxNumUni(), generateUniSet(), null);
- ceManager.establishConnectivity(evc);
+ ceManager.installEvc(evc);
}
/**
@@ -159,9 +159,9 @@
*
* @return the set of UNIs for the CE EVC
*/
- Set<CarrierEthernetNetworkInterface> generateUniSet() {
+ Set<CarrierEthernetUni> generateUniSet() {
- Set<CarrierEthernetNetworkInterface> uniSet = new HashSet<>();
+ Set<CarrierEthernetUni> uniSet = new HashSet<>();
CarrierEthernetVirtualConnection.Type evcType = generateEvcType();
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 d9a7126..ee7f058 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
@@ -30,7 +30,7 @@
import java.util.Set;
/**
- * CLI command for generating Carrier Ethernet Forwarding Constructs.
+ * CLI command for installing a Carrier Ethernet Forwarding Construct.
*/
@Command(scope = "onos", name = "ce-fc-create",
description = "Creates and installs a Carrier Ethernet Forwarding Construct.")
@@ -75,8 +75,8 @@
CarrierEthernetManager ceManager = get(CarrierEthernetManager.class);
- CarrierEthernetForwardingConstruct fc = new CarrierEthernetForwardingConstruct(argFcId, argFcCfgId, null,
- generateServiceType(), generateLtpSet());
+ CarrierEthernetForwardingConstruct fc = new CarrierEthernetForwardingConstruct(argFcId, argFcCfgId,
+ generateServiceType(), generateLtpSet(), null);
ceManager.installFc(fc);
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateLtpCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateLtpCommand.java
index 4c957d0..a519111 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateLtpCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateLtpCommand.java
@@ -28,7 +28,7 @@
import java.util.Set;
/**
- * CLI command for generating Carrier Ethernet Logical Termination Points.
+ * CLI command for generating one or more Carrier Ethernet Logical Termination Points.
*/
@Command(scope = "onos", name = "ce-ltp-create",
description = "Creates Carrier Ethernet Logical Termination Points.")
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateUniCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateUniCommand.java
index ea02b81..f500d29 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateUniCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetCreateUniCommand.java
@@ -26,7 +26,7 @@
import java.util.List;
/**
- * CLI command for generating Carrier Ethernet UNIs.
+ * CLI command for generating one or more Carrier Ethernet UNIs.
*/
@Command(scope = "onos", name = "ce-uni-create",
description = "Creates Carrier Ethernet UNIs.")
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveEvcCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveEvcCommand.java
index b17afb2..dba5dcf 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveEvcCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveEvcCommand.java
@@ -24,7 +24,7 @@
import java.util.List;
/**
- * CLI command for removing installed EVCs.
+ * CLI command for removing one or more installed EVCs.
*/
@Command(scope = "onos", name = "ce-evc-remove",
description = "Carrier Ethernet EVC removal command.")
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveFcCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveFcCommand.java
index 873925d..f07cc37 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveFcCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveFcCommand.java
@@ -15,24 +15,28 @@
*/
package org.onosproject.ecord.carrierethernet.cli.commands;
+import com.google.common.collect.Lists;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.ecord.carrierethernet.app.CarrierEthernetManager;
+import java.util.List;
+
/**
- * CLI command for removing an installed Carrier Ethernet Forwarding Construct.
+ * CLI command for removing one or more installed Carrier Ethernet Forwarding Constructs.
*/
@Command(scope = "onos", name = "ce-fc-remove",
description = "Carrier Ethernet service removal command.")
public class CarrierEthernetRemoveFcCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "argFcId", description = "Forwarding Construct ID", required = true, multiValued = false)
- String argFcId = null;
+ @Argument(index = 0, name = "argFcIdList", description = "Forwarding Construct IDs",
+ required = true, multiValued = true)
+ List<String> argFcIdList = Lists.newArrayList();
@Override
protected void execute() {
CarrierEthernetManager ceManager = get(CarrierEthernetManager.class);
- ceManager.removeFc(argFcId);
+ argFcIdList.forEach(argFcId -> ceManager.removeFc(argFcId));
}
}
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveLtpCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveLtpCommand.java
index dc84ef5..6163430 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveLtpCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveLtpCommand.java
@@ -24,7 +24,7 @@
import java.util.List;
/**
- * CLI command for removing LTPs.
+ * CLI command for removing one or multiple LTPs.
*/
@Command(scope = "onos", name = "ce-ltp-remove",
description = "Carrier Ethernet LTP removal command.")
diff --git a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveUniCommand.java b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveUniCommand.java
index 701a447..dd47ba8 100644
--- a/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveUniCommand.java
+++ b/ecord/carrierethernet/src/main/java/org/onosproject/ecord/carrierethernet/cli/commands/CarrierEthernetRemoveUniCommand.java
@@ -24,7 +24,7 @@
import java.util.List;
/**
- * CLI command for removing UNIs.
+ * CLI command for removing one or more UNIs.
*/
@Command(scope = "onos", name = "ce-uni-remove",
description = "Carrier Ethernet UNI removal command.")