Porting CE app to 4.1
Change-Id: Ic3280ce797f6225773ade789d9793ae445f9f525
diff --git a/ce-api/pom.xml b/ce-api/pom.xml
new file mode 100644
index 0000000..5ac4b5d
--- /dev/null
+++ b/ce-api/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2017-present Open Networking Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opencord</groupId>
+ <artifactId>ce</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <groupId>org.opencord.ce</groupId>
+ <artifactId>ce-api</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <description>Carrier Ethernet service API</description>
+
+ <properties>
+ <onos.app.name>org.opencord.ce.api</onos.app.name>
+ <onos.app.title>Carrier Ethernet service API</onos.app.title>
+ <onos.app.url>http://opencord.org</onos.app.url>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>1.10.6</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetBandwidthProfile.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetBandwidthProfile.java
new file mode 100644
index 0000000..3eeae81
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetBandwidthProfile.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+
+import org.onlab.util.Bandwidth;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Bandwidth profile for a CE UNI.
+ */
+// TODO: Methods to associate a CE BWP to a generic BWP and a Meter
+public final class CarrierEthernetBandwidthProfile {
+
+ public enum Type {
+ INTERFACE, EVC, COS
+ }
+
+ protected String id;
+ protected String cfgId;
+ protected Type type;
+ protected Bandwidth cir;
+ protected Bandwidth eir;
+ protected long cbs;
+ protected long ebs;
+
+ // TODO: Remove id from constructor - should be generated by some manager
+ private CarrierEthernetBandwidthProfile(String id, String cfgId, Type type,
+ Bandwidth cir, Bandwidth eir,
+ long cbs, long ebs) {
+ checkNotNull(cir, "BW Profile must have an associated CIR");
+ checkNotNull(type, "BW profile must have a type");
+ this.id = id;
+ this.cfgId = cfgId;
+ this.type = type;
+ this.cir = cir;
+ this.eir = eir;
+ this.cbs = cbs;
+ this.ebs = ebs;
+ }
+
+ /**
+ * Returns BWP string identifier.
+ *
+ * @return BWP string identifier
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * Returns BWP string config identifier.
+ *
+ * @return BWP string config identifier
+ */
+ public String cfgId() {
+ return cfgId;
+ }
+
+ /**
+ * Returns BWP type (INTERFACE, EVC, COS).
+ *
+ * @return BWP type
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns BWP CIR rate.
+ *
+ * @return BWP CIR rate
+ */
+ public Bandwidth cir() {
+ return cir;
+ }
+
+ /**
+ * Returns BWP EIR rate.
+ *
+ * @return BWP EIR rate
+ */
+ public Bandwidth eir() {
+ return eir;
+ }
+
+ /**
+ * Returns BWP CBS in Bytes.
+ *
+ * @return BWP CBS in Bytes
+ */
+ public long cbs() {
+ return cbs;
+ }
+
+ /**
+ * Returns BWP EBS in Bytes.
+ *
+ * @return BWP EBS in Bytes
+ */
+ public long ebs() {
+ return ebs;
+ }
+
+ /**
+ * Sets BWP id.
+ *
+ * @param id the id to set
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets BWP CIR rate.
+ *
+ * @param cir the CIR to set
+ */
+ public void setCir(Bandwidth cir) {
+ this.cir = cir;
+ }
+
+ /**
+ * Sets BWP EIR rate.
+ *
+ * @param eir the EIR to set
+ */
+ public void setEir(Bandwidth eir) {
+ this.eir = eir;
+ }
+
+ public String toString() {
+
+ return toStringHelper(this)
+ .add("id", id)
+ .add("type", type)
+ .add("cir", cir)
+ .add("cbs", cbs)
+ .add("eir", eir)
+ .add("ebs", ebs).toString();
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of CarrierEthernetBandwidthProfile entities.
+ */
+ public static final class Builder {
+
+ String id;
+ String cfgId;
+ Type type;
+ Bandwidth cir;
+ Bandwidth eir;
+ long cbs;
+ long ebs;
+
+ /**
+ * Sets the id of this builder.
+ *
+ * @param id the builder id to set
+ * @return this builder instance
+ */
+ public Builder id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Sets the cfgId of this builder.
+ *
+ * @param cfgId the builder cfgId to set
+ * @return this builder instance
+ */
+ public Builder cfgId(String cfgId) {
+ this.cfgId = cfgId;
+ return this;
+ }
+
+ /**
+ * Sets the type of this builder.
+ *
+ * @param type the builder type to set
+ * @return this builder instance
+ */
+ public Builder type(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * Sets the cir of this builder.
+ *
+ * @param cir the builder cir to set
+ * @return this builder instance
+ */
+ public Builder cir(Bandwidth cir) {
+ this.cir = cir;
+ return this;
+ }
+
+ /**
+ * Sets the eir of this builder.
+ *
+ * @param eir the builder eir to set
+ * @return this builder instance
+ */
+ public Builder eir(Bandwidth eir) {
+ this.eir = eir;
+ return this;
+ }
+
+ /**
+ * Sets the cbs of this builder.
+ *
+ * @param cbs the builder cbs to set
+ * @return this builder instance
+ */
+ public Builder cbs(long cbs) {
+ this.cbs = cbs;
+ return this;
+ }
+
+ /**
+ * Sets the ebs of this builder.
+ *
+ * @param ebs the builder ebs to set
+ * @return this builder instance
+ */
+ public Builder ebs(long ebs) {
+ this.ebs = ebs;
+ return this;
+ }
+
+ /**
+ * Builds a new CarrierEthernetBandwidthProfile instance based on this builder's parameters.
+ *
+ * @return a new CarrierEthernetBandwidthProfile instance
+ */
+ public CarrierEthernetBandwidthProfile build() {
+ return new CarrierEthernetBandwidthProfile(id, cfgId, type, cir, eir, cbs, ebs);
+ }
+ }
+}
+
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetConnection.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetConnection.java
new file mode 100644
index 0000000..ce4b1ed
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetConnection.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+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, // E-LINE
+ MULTIPOINT_TO_MULTIPOINT, // E-LAN
+ ROOT_MULTIPOINT // E_TREE
+ }
+
+ public enum State {
+ ACTIVE,
+ INACTIVE,
+ PARTIAL
+ }
+
+ protected EvcConnId 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(EvcConnId 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 EvcConnId 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(EvcConnId 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/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetEnni.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetEnni.java
new file mode 100644
index 0000000..15659d6
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetEnni.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+
+import com.google.common.collect.Sets;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+import org.slf4j.Logger;
+
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Representation of a Carrier Ethernet ENNI.
+ * Class can be used in different two ways:
+ * 1. As a global ENNI descriptor containing one or more S-VLAN tags
+ * 2. As a service-specific ENNI descriptor containing a single S-VLAN tag and including a role (e.g. hub, spoke)
+ */
+public final class CarrierEthernetEnni extends CarrierEthernetNetworkInterface {
+
+ private final Logger log = getLogger(getClass());
+
+ public enum Role {
+
+ HUB("Hub"),
+ SPOKE("Spoke"),
+ // FIXME: Remove these after LTP-NI role mapping is fixed
+ ROOT("Root"),
+ LEAF("Leaf");
+
+ private String value;
+
+ Role(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+ protected Role role;
+ protected Set<VlanId> sVlanIdSet;
+ String tpid;
+
+ private CarrierEthernetEnni(ConnectPoint cp, String uniCfgId,
+ Role role, VlanId sVlanId, String tpid,
+ Bandwidth usedCapacity, Annotations...annotations) {
+ super(cp, Type.ENNI, uniCfgId, annotations);
+ // TODO: Check for null
+ this.role = role;
+ this.sVlanIdSet = Sets.newConcurrentHashSet();
+ // The following applies only to service-specific ENNIs
+ if (sVlanId != null) {
+ this.sVlanIdSet.add(sVlanId);
+ // TODO: Use Hub/Spoke role correctly
+ this.role = Role.HUB;
+ this.usedCapacity = usedCapacity;
+ this.tpid = tpid;
+ }
+ }
+
+ /**
+ * Adds the resources associated with an FC-specific ENNI to a global ENNI.
+ *
+ * @param enni the FC-specific ENNI to be added
+ */
+ @Override
+ public void addEcNi(CarrierEthernetNetworkInterface enni) {
+ // Add S-VLAN ID
+ if (enni.sVlanId() != VlanId.NONE) {
+ this.sVlanIdSet.add(enni.sVlanId());
+ }
+ // Used capacity cannot be more than ENNI capacity
+ this.usedCapacity = Bandwidth.bps(Math.min(this.usedCapacity.bps() + enni.usedCapacity().bps(),
+ this.capacity.bps()));
+ }
+
+ /**
+ * Removes the resources associated with an FC-specific ENNI from a global ENNI.
+ *
+ * @param enni the FC-specific ENNI to be removed
+ */
+ @Override
+ public void removeEcNi(CarrierEthernetNetworkInterface 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 FC-specific ENNI is compatible with the corresponding global ENNI.
+ *
+ * @param enni the FC-specific ENNI
+ * @return boolean value indicating whether the ENNIs are compatible
+ */
+ @Override
+ public boolean validateEcNi(CarrierEthernetNetworkInterface enni) {
+
+ // Check if the S-VLAN ID of the ENNI is already included in global ENNI
+ if (enni.sVlanId() != VlanId.NONE) {
+ if (sVlanIdSet.contains(enni.sVlanId())) {
+ log.error("S-VLAN ID {} already exists in ENNI {}", enni.sVlanId().toString(), this.id());
+ return false;
+ }
+ }
+
+ // Check whether there are enough available resources on the ENNI
+ if (usedCapacity.bps() + enni.usedCapacity().bps() > capacity.bps()) {
+ log.error("ENNI {} cannot be added to global ENNI {} due to lack of resources", enni.id(), this.id());
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns ENNI role - applicable only to service-specific ENNIs.
+ *
+ * @return ENNI role
+ */
+ @Override
+ public Role role() {
+ return role;
+ }
+
+ /**
+ * Returns the S-VLAN id associated with a service ENNI,
+ * or the first S-VLAN ID found for a global ENNI.
+ * This is assumed to be the S-TAG of another FC interconnected with this ENNI.
+ *
+ * @return S-VLAN id
+ */
+ @Override
+ public VlanId sVlanId() {
+ if (sVlanIdSet.isEmpty()) {
+ return VlanId.NONE;
+ } else {
+ return sVlanIdSet.iterator().next();
+ }
+ }
+
+ /**
+ * Always returns null, since CE-VLAN IDs are not associated with ENNIs.
+ *
+ * @return null
+ */
+ @Override
+ public VlanId ceVlanId() {
+ return null;
+ }
+
+ /**
+ * Returns ENNI tpid - applicable only to service-specific ENNIs.
+ *
+ * @return tpid
+ */
+ public String tpid() {
+ return tpid;
+ }
+
+ /**
+ * Returns the set of S-VLAN ids associated with the ENNI.
+ * Those are assumed to be the S-TAGs of other FCs interconnected with this ENNI.
+ *
+ * @return S-VLAN id set
+ */
+ public Set<VlanId> sVlanIdSet() {
+ 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() {
+
+ return toStringHelper(this)
+ .add("id", this.id)
+ .add("cfgId", this.cfgId)
+ .add("role", role)
+ .add("refCount", refCount)
+ .add("sVlanIds", sVlanIdSet)
+ .add("capacity", this.capacity)
+ .add("usedCapacity", this.usedCapacity).toString();
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of CarrierEthernetEnni entities.
+ */
+ public static final class Builder {
+
+ private ConnectPoint cp;
+ private String cfgId;
+ private Role role;
+ private VlanId sVlanId;
+ private String tpid;
+ private Bandwidth usedCapacity;
+ private Annotations annotations;
+
+ /**
+ * Sets the cp of this builder.
+ *
+ * @param cp the builder cp to set
+ * @return this builder instance
+ */
+ public Builder cp(ConnectPoint cp) {
+ this.cp = cp;
+ return this;
+ }
+
+ /**
+ * Sets the cfgId of this builder.
+ *
+ * @param cfgId the builder cfgId to set
+ * @return this builder instance
+ */
+ public Builder cfgId(String cfgId) {
+ this.cfgId = cfgId;
+ return this;
+ }
+
+ /**
+ * Sets the role of this builder.
+ *
+ * @param role the builder role to set
+ * @return this builder instance
+ */
+ public Builder role(Role role) {
+ this.role = role;
+ return this;
+ }
+
+ /**
+ * Sets the sVlanId of this builder.
+ *
+ * @param sVlanId the builder sVlanId to set
+ * @return this builder instance
+ */
+ public Builder sVlanId(VlanId sVlanId) {
+ this.sVlanId = sVlanId;
+ return this;
+ }
+
+ /**
+ * Sets the tpid of this builder.
+ *
+ * @param tpid the builder tpid to set
+ * @return this builder instance
+ */
+ public Builder tpid(String tpid) {
+ this.tpid = tpid;
+ return this;
+ }
+
+ /**
+ * Sets the usedCapacity of this builder.
+ *
+ * @param usedCapacity the builder usedCapacity to set
+ * @return this builder instance
+ */
+ public Builder usedCapacity(Bandwidth usedCapacity) {
+ this.usedCapacity = usedCapacity;
+ return this;
+ }
+
+ /**
+ * Sets annotations.
+ *
+ * @param annotations annotations
+ * @return this builder instance
+ */
+ public Builder annotations(Annotations annotations) {
+ this.annotations = annotations;
+ return this;
+ }
+
+ /**
+ * Builds a new CarrierEthernetEnni instance.
+ * based on this builder's parameters
+ *
+ * @return a new CarrierEthernetEnni instance
+ */
+ public CarrierEthernetEnni build() {
+ return new CarrierEthernetEnni(cp, cfgId, role, sVlanId, tpid, usedCapacity, annotations);
+ }
+ }
+}
+
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetEvcUtils.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetEvcUtils.java
new file mode 100644
index 0000000..dd59c42
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetEvcUtils.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+
+import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.opencord.ce.api.models.CarrierEthernetVirtualConnection.MAX_NUM_UNI;
+
+/**
+ * Utilities to build EthernetVirtualConnections.
+ */
+public final class CarrierEthernetEvcUtils {
+
+ // no instantiation
+ private CarrierEthernetEvcUtils() {
+ }
+
+ /**
+ * Return the CE-VLAN ID for the CE evc based on the CLI-supplied argument.
+ *
+ * @param argCeVlanId vlanID
+ * @return CE-VLAN ID for the CE evc
+ */
+ public static VlanId generateCeVlanId(short argCeVlanId) {
+ return ((argCeVlanId == -1) ? null : VlanId.vlanId(argCeVlanId));
+ }
+
+ /**
+ * Return the CE evc type based on the CLI-supplied arguments.
+ *
+ * @param evcTypeString EVC type
+ * @param uniList UNIs list
+ * @return the CE evc type
+ */
+ public static CarrierEthernetConnection.Type generateEvcType(String evcTypeString, List<String> uniList) {
+ if (evcTypeString == null) {
+ return ((uniList.size() > 2) ?
+ CarrierEthernetConnection.Type.MULTIPOINT_TO_MULTIPOINT :
+ CarrierEthernetConnection.Type.POINT_TO_POINT);
+ } else {
+ // TODO: Catch exception
+ return CarrierEthernetConnection.Type.valueOf(evcTypeString);
+ }
+ }
+
+ /**
+ * Return the EVC maxNumUni parameter based on the CLI-supplied arguments.
+ *
+ * @param maxNumUni maximum numbers of UNIs
+ * @param evcTypeString EVC Type
+ * @param uniList UNIs list
+ * @return the maxNumUni parameter
+ */
+ public static Integer generateMaxNumUni(int maxNumUni, String evcTypeString, List<String> uniList) {
+ if (maxNumUni == -1) {
+ if (evcTypeString == null) {
+ return ((uniList.size() > 2) ?
+ MAX_NUM_UNI : 2);
+ } else {
+ // TODO: Catch exception
+ CarrierEthernetConnection.Type evcType =
+ CarrierEthernetConnection.Type.valueOf(evcTypeString);
+ return (evcType.equals(CarrierEthernetConnection.Type.POINT_TO_POINT) ? 2 :
+ MAX_NUM_UNI);
+ }
+ } else {
+ return maxNumUni;
+ }
+ }
+
+ /**
+ * Return the BW profile type based on the CLI-supplied arguments.
+ *
+ * @param ceVlanId vlanID
+ * @return the BWP profile type
+ */
+ public static CarrierEthernetBandwidthProfile.Type generateBandwidthProfileType(short ceVlanId) {
+ // TODO: Add the CoS BW profile case
+ return ((ceVlanId == -1) ?
+ CarrierEthernetBandwidthProfile.Type.INTERFACE : CarrierEthernetBandwidthProfile.Type.EVC);
+ }
+
+ /**
+ * Return the BW profile id based on the CLI-supplied arguments.
+ *
+ * @param uniId UNI id
+ * @param evcCfgId EVC configuration Id
+ * @param ceVlanId vlanID
+ * @return the BW profile id
+ */
+ public static String generateBandwidthProfileId(String uniId, String evcCfgId, int ceVlanId) {
+ // TODO: Add the CoS BW profile case
+ return ((ceVlanId == -1) ? uniId : evcCfgId);
+ }
+
+ /**
+ * Return the set of UNIs for the CE EVC based on the CLI-supplied arguments.
+ *
+ * @param evcTypeString Type of the UNI
+ * @param uniList list of remaning UNIs
+ * @param ceVlanId vlanID
+ * @param firstUni first UNI id
+ * @param evcCfgId EVC configuration Id
+ * @param cir The CIR in Mbps
+ * @param eir The EIR in Mbps
+ * @param cbs The CBS in Byte
+ * @param ebs The EBS in Byte
+ * @return the set of UNIs for the CE EVC
+ */
+ public static Set<CarrierEthernetUni> generateUniSet(String evcTypeString, List<String> uniList,
+ short ceVlanId, String firstUni, String evcCfgId,
+ Double cir, Double eir, Long cbs, Long ebs) {
+
+ Set<CarrierEthernetUni> uniSet = new HashSet<>();
+
+ CarrierEthernetConnection.Type evcType = generateEvcType(evcTypeString, uniList);
+
+ // We assume that first UNI supplied is always root
+ uniSet.add(CarrierEthernetUni.builder()
+ .cp(ConnectPoint.deviceConnectPoint(firstUni))
+ .role(CarrierEthernetUni.Role.ROOT)
+ .ceVlanId(generateCeVlanId(ceVlanId))
+ .bwp(CarrierEthernetBandwidthProfile.builder()
+ .id(generateBandwidthProfileId(firstUni, evcCfgId, ceVlanId))
+ .type(generateBandwidthProfileType(ceVlanId))
+ .cir(Bandwidth.mbps(cir))
+ .eir(Bandwidth.mbps(eir))
+ .cbs(cbs)
+ .ebs(ebs)
+ .build())
+ .build());
+
+ final CarrierEthernetUni.Role role;
+ // For E-Line and E-LAN all UNIs are roots. For E-Tree all UNIs are leafs except from one
+ role = ((evcType == CarrierEthernetConnection.Type.ROOT_MULTIPOINT) ?
+ CarrierEthernetUni.Role.LEAF : CarrierEthernetUni.Role.ROOT);
+
+ uniList.forEach(argUni -> uniSet.add(
+ CarrierEthernetUni.builder()
+ .cp(ConnectPoint.deviceConnectPoint(argUni))
+ .role(role)
+ .ceVlanId(generateCeVlanId(ceVlanId))
+ .bwp(CarrierEthernetBandwidthProfile.builder()
+ .id(generateBandwidthProfileId(argUni, evcCfgId, ceVlanId))
+ .type(generateBandwidthProfileType(ceVlanId))
+ .cir(Bandwidth.mbps(cir))
+ .eir(Bandwidth.mbps(eir))
+ .cbs(cbs)
+ .ebs(ebs)
+ .build())
+ .build()));
+
+ return uniSet;
+ }
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetForwardingConstruct.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetForwardingConstruct.java
new file mode 100644
index 0000000..e4e4ddc
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetForwardingConstruct.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+import org.onlab.packet.VlanId;
+
+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 com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a CE Forwarding Construct.
+ */
+public final class CarrierEthernetForwardingConstruct extends CarrierEthernetConnection {
+
+ private Set<CarrierEthernetLogicalTerminationPoint> ltpSet;
+ private VlanId vlanId;
+ private boolean congruentPaths = true;
+ protected AtomicInteger refCount;
+
+ // TODO: Remove id from constructor - currently used only when updating FC
+ // TODO: Add congruentPaths flag to constructor and Builder
+ private CarrierEthernetForwardingConstruct(EvcConnId id, String cfgId, Type type,
+ Set<CarrierEthernetLogicalTerminationPoint> ltpSet,
+ Duration maxLatency) {
+ super(id, cfgId, type, maxLatency);
+ this.ltpSet = new HashSet<>(ltpSet);
+ this.vlanId = null;
+ this.refCount = new AtomicInteger();
+ }
+
+ /**
+ * Returns Vlan id.
+ *
+ * @return Vlan id
+ */
+ public VlanId vlanId() {
+ return vlanId;
+ }
+
+
+ /**
+ * Returns the set of LTPs associated with the FC.
+ *
+ * @return set of LTPs associated with the FC
+ */
+ public Set<CarrierEthernetLogicalTerminationPoint> ltpSet() {
+ return ltpSet;
+ }
+
+ /**
+ * Returns the set of UNIs associated with the FC.
+ *
+ * @return set of UNIs associated with the FC
+ */
+ 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 true if FC requires that both directions should use the same path.
+ *
+ * @return true if both directions should use the same path
+ */
+ public boolean congruentPaths() {
+ return congruentPaths;
+ }
+
+ /**
+ * Returns counter with the number of references (from EVCs) to the particular FC.
+ *
+ * @return number of references counter
+ */
+ public AtomicInteger refCount() {
+ return refCount;
+ }
+
+ /**
+ * Sets the vlanId to be used by the FC.
+ *
+ * @param vlanId the vlanId to set
+ */
+ public void setVlanId(VlanId vlanId) {
+ this.vlanId = vlanId;
+ }
+
+ /**
+ * Sets the set of LTPs.
+ *
+ * @param ltpSet the set of LTPs to be set
+ */
+ public void setLtpSet(Set<CarrierEthernetLogicalTerminationPoint> ltpSet) {
+ this.ltpSet = ltpSet;
+ }
+
+ public String toString() {
+
+ return toStringHelper(this)
+ .add("id", id)
+ .add("cfgId", cfgId)
+ .add("type", type)
+ .add("vlanId", vlanId)
+ .add("refCount", refCount)
+ .add("LTPs", ltpSet).toString();
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of CarrierEthernetForwardingConstruct entities.
+ */
+ public static final class Builder {
+
+ private EvcConnId id;
+ private String cfgId;
+ private Type type;
+ private Duration maxLatency;
+ private Set<CarrierEthernetLogicalTerminationPoint> ltpSet;
+
+ /**
+ * Sets the id of this builder.
+ *
+ * @param id the builder id to set
+ * @return this builder instance
+ */
+ public Builder id(EvcConnId id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Sets the cfgId of this builder.
+ *
+ * @param cfgId the builder cfgId to set
+ * @return this builder instance
+ */
+ public Builder cfgId(String cfgId) {
+ this.cfgId = cfgId;
+ return this;
+ }
+
+ /**
+ * Sets the type of this builder.
+ *
+ * @param type the builder type to set
+ * @return this builder instance
+ */
+ public Builder type(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * Sets the maxLatency of this builder.
+ *
+ * @param maxLatency the builder maxLatency to set
+ * @return this builder instance
+ */
+ public Builder maxLatency(Duration maxLatency) {
+ this.maxLatency = maxLatency;
+ return this;
+ }
+
+ /**
+ * Sets the ltpSet of this builder.
+ *
+ * @param ltpSet the builder ltpSet to set
+ * @return this builder instance
+ */
+ public Builder ltpSet(Set<CarrierEthernetLogicalTerminationPoint> ltpSet) {
+ this.ltpSet = ltpSet;
+ return this;
+ }
+
+ /**
+ * Builds a new CarrierEthernetForwardingConstruct instance.
+ * based on this builder's parameters
+ *
+ * @return a new CarrierEthernetForwardingConstruct instance
+ */
+ public CarrierEthernetForwardingConstruct build() {
+ checkNotNull(type, "FC must have a type");
+ checkArgument(ltpSet != null && ltpSet.size() > 1,
+ "FC must include at least two LTPs");
+
+ return new CarrierEthernetForwardingConstruct(id, cfgId, type, ltpSet, maxLatency);
+ }
+ }
+}
+
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetGenericNi.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetGenericNi.java
new file mode 100644
index 0000000..e543a07
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetGenericNi.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+
+import org.onlab.packet.VlanId;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Representation of a Generic Carrier Ethernet NI.
+ * Class is only meant to be used for establishing forwarding in CarrierEthernetPacketNodeManagers
+ */
+public class CarrierEthernetGenericNi extends CarrierEthernetNetworkInterface {
+
+ public enum Role {
+
+ NONE("None");
+
+ private String value;
+
+ Role(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+ public CarrierEthernetGenericNi(ConnectPoint connectPoint, String uniCfgId,
+ Annotations...annotations) {
+ super(connectPoint, Type.GENERIC, uniCfgId, annotations);
+ }
+
+ @Override
+ public Role role() {
+ return Role.NONE;
+ }
+
+ /**
+ * Always returns null, since CE-VLAN IDs are not associated with Generic NIs.
+ *
+ * @return null
+ */
+ @Override
+ public VlanId ceVlanId() {
+ return null;
+ }
+
+ /**
+ * Always returns null, since S-TAGs are not associated with Generic NIs.
+ *
+ * @return null
+ */
+ @Override
+ public VlanId sVlanId() {
+ 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(CarrierEthernetNetworkInterface 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(CarrierEthernetNetworkInterface 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(CarrierEthernetNetworkInterface gni) {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+
+ return toStringHelper(this)
+ .add("id", this.id)
+ .add("cfgId", this.cfgId)
+ .add("refCount", refCount)
+ .add("capacity", this.capacity)
+ .add("usedCapacity", this.usedCapacity).toString();
+ }
+
+}
+
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetInni.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetInni.java
new file mode 100644
index 0000000..ec49e88
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetInni.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+import org.slf4j.Logger;
+
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Representation of a Carrier Ethernet INNI.
+ * Class can be used in different two ways:
+ * 1. As a global INNI descriptor containing one or more S-VLAN tags
+ * 2. As a service-specific INNI descriptor containing a single S-VLAN tag and including a role (e.g. hub, spoke)
+ */
+public final class CarrierEthernetInni extends CarrierEthernetNetworkInterface {
+
+ private final Logger log = getLogger(getClass());
+
+ public enum Role {
+
+ HUB("Hub"),
+ // FIXME: Remove that after hackathon?
+ TRUNK("Trunk"),
+ SPOKE("Spoke"),
+ // FIXME: Remove these after LTP-NI role mapping is fixed
+ ROOT("Root"),
+ LEAF("Leaf");
+
+ private String value;
+
+ Role(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+ protected Role role;
+ protected Set<VlanId> sVlanIdSet;
+ // TODO: Associate TPIDs with S-TAGs
+ protected String tpid;
+
+ // TODO: Change sVlanId to Collection<VlanId>
+ private CarrierEthernetInni(ConnectPoint connectPoint, String uniCfgId,
+ Role role, VlanId sVlanId, String tpid,
+ Bandwidth usedCapacity,
+ Annotations...annotations) {
+
+ super(connectPoint, Type.INNI, uniCfgId, annotations);
+
+ // TODO: Check for null
+ this.role = role;
+ this.sVlanIdSet = Sets.newConcurrentHashSet();
+ // The following applies only to service-specific INNIs
+ if (sVlanId != null) {
+ this.sVlanIdSet.add(sVlanId);
+ // TODO: Use role correctly
+ this.role = Role.HUB;
+ this.usedCapacity = usedCapacity;
+ this.tpid = tpid;
+ }
+ }
+
+ /**
+ * Adds the resources associated with an FC-specific INNI to a global INNI.
+ *
+ * @param inni the FC-specific INNI to be added
+ */
+ @Override
+ public void addEcNi(CarrierEthernetNetworkInterface inni) {
+ // Add S-VLAN ID
+ if (inni.sVlanId() != VlanId.NONE) {
+ this.sVlanIdSet.add(inni.sVlanId());
+ }
+ // Used capacity cannot be more than INNI capacity
+ this.usedCapacity = Bandwidth.bps(Math.min(this.usedCapacity.bps() + inni.usedCapacity().bps(),
+ this.capacity.bps()));
+ }
+
+ /**
+ * Removes the resources associated with an FC-specific INNI from a global INNI.
+ *
+ * @param inni the FC-specific INNI to be removed
+ */
+ @Override
+ public void removeEcNi(CarrierEthernetNetworkInterface 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 FC-specific INNI is compatible with the corresponding global INNI.
+ *
+ * @param inni the FC-specific INNI
+ * @return boolean value indicating whether the INNIs are compatible
+ */
+ @Override
+ public boolean validateEcNi(CarrierEthernetNetworkInterface inni) {
+
+ // Check if the S-VLAN ID of the INNI is already included in global INNI
+ if (inni.sVlanId() != null) {
+ if (sVlanIdSet.contains(inni.sVlanId())) {
+ log.error("S-VLAN ID {} already exists in INNI {}", inni.sVlanId().toString(), this.id());
+ return false;
+ }
+ }
+
+ // Check whether there are enough available resources on the INNI
+ if (usedCapacity.bps() + inni.usedCapacity().bps() > capacity.bps()) {
+ log.error("INNI {} cannot be added to global INNI {} due to lack of resources", inni.id(), this.id());
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns INNI role - applicable only to service-specific INNIs.
+ *
+ * @return INNI role
+ */
+ @Override
+ public Role role() {
+ return role;
+ }
+
+ /**
+ * Returns the S-VLAN id associated with a service INNI, or the first S-VLAN ID found for a global INNI.
+ * This is assumed to be the S-TAG of another FC interconnected with this INNI.
+ *
+ * @return S-VLAN id
+ */
+ @Override
+ public VlanId sVlanId() {
+ if (sVlanIdSet.isEmpty()) {
+ return VlanId.NONE;
+ } else {
+ return sVlanIdSet.iterator().next();
+ }
+ }
+
+ /**
+ * Always returns null, since CE-VLAN IDs are not associated with INNIs.
+ *
+ * @return null
+ */
+ @Override
+ public VlanId ceVlanId() {
+ return null;
+ }
+
+ /**
+ * Returns the set of S-VLAN ids associated with the INNI.
+ * Those are assumed to be the S-TAGs of other FCs interconnected with this INNI.
+ *
+ * @return S-VLAN id set
+ */
+ public Set<VlanId> sVlanIdSet() {
+ 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.
+ *
+ * @return tpid
+ */
+ public String tpid() {
+ return tpid;
+ }
+
+ @Override
+ public String toString() {
+
+ return toStringHelper(this)
+ .add("id", this.id)
+ .add("cfgId", this.cfgId)
+ .add("role", role)
+ .add("refCount", refCount)
+ .add("sVlanIds", sVlanIdSet)
+ .add("capacity", this.capacity)
+ .add("usedCapacity", this.usedCapacity).toString();
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of CarrierEthernetInni entities.
+ */
+ public static final class Builder {
+
+ private ConnectPoint cp;
+ private String cfgId;
+ private Role role;
+ private VlanId sVlanId;
+ private String tpid;
+ private Bandwidth usedCapacity;
+ private Annotations annotations;
+
+ /**
+ * Sets the cp of this builder.
+ *
+ * @param cp the builder cp to set
+ * @return this builder instance
+ */
+ public Builder cp(ConnectPoint cp) {
+ this.cp = cp;
+ return this;
+ }
+
+ /**
+ * Sets the cfgId of this builder.
+ *
+ * @param cfgId the builder cfgId to set
+ * @return this builder instance
+ */
+ public Builder cfgId(String cfgId) {
+ this.cfgId = cfgId;
+ return this;
+ }
+
+ /**
+ * Sets the role of this builder.
+ *
+ * @param role the builder role to set
+ * @return this builder instance
+ */
+ public Builder role(Role role) {
+ this.role = role;
+ return this;
+ }
+
+ /**
+ * Sets the sVlanId of this builder.
+ *
+ * @param sVlanId the builder sVlanId to set
+ * @return this builder instance
+ */
+ public Builder sVlanId(VlanId sVlanId) {
+ this.sVlanId = sVlanId;
+ return this;
+ }
+
+ /**
+ * Sets the tpid of this builder.
+ *
+ * @param tpid the builder tpid to set
+ * @return this builder instance
+ */
+ public Builder tpid(String tpid) {
+ this.tpid = tpid;
+ return this;
+ }
+
+ /**
+ * Sets the usedCapacity of this builder.
+ *
+ * @param usedCapacity the builder usedCapacity to set
+ * @return this builder instance
+ */
+ public Builder usedCapacity(Bandwidth usedCapacity) {
+ this.usedCapacity = usedCapacity;
+ return this;
+ }
+
+ /**
+ * Sets annotations.
+ *
+ * @param annotations annotations
+ * @return this builder instance
+ */
+ public CarrierEthernetInni.Builder annotations(Annotations annotations) {
+ this.annotations = annotations;
+ return this;
+ }
+
+ /**
+ * Builds a new CarrierEthernetInni instance.
+ * based on this builder's parameters
+ *
+ * @return a new CarrierEthernetInni instance
+ */
+ public CarrierEthernetInni build() {
+ return new CarrierEthernetInni(cp, cfgId, role, sVlanId, tpid, usedCapacity, annotations);
+ }
+ }
+}
+
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetLogicalTerminationPoint.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetLogicalTerminationPoint.java
new file mode 100644
index 0000000..3e0e582
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetLogicalTerminationPoint.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+
+import org.onosproject.net.ConnectPoint;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a CE Logical Termination Point.
+ */
+public class CarrierEthernetLogicalTerminationPoint {
+
+ public enum Role {
+
+ WORKING("Working"),
+ PROTECTION("Protection"),
+ PROTECTED("Protected"),
+ SYMMETRIC("Symmetric"),
+ HUB("Hub"),
+ SPOKE("Spoke"),
+ LEAF("Leaf"),
+ // FIXME: Remove that after hackathon?
+ TRUNK("Trunk"),
+ ROOT("Root");
+
+ private String value;
+
+ Role(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+ protected String ltpId;
+ protected String ltpCfgId;
+ protected Role role;
+ // A global LTP will point to the corresponding global NI and a service LTP to the corresponding service NI
+ protected CarrierEthernetNetworkInterface ni;
+
+ public CarrierEthernetLogicalTerminationPoint(String ltpCfgId, CarrierEthernetNetworkInterface ni) {
+ checkNotNull(ni);
+ this.ni = ni;
+ // NOTE: Role is expected to be null for global LTPs/NIs
+ if (ni.type().equals(CarrierEthernetNetworkInterface.Type.UNI)) {
+ this.role = (ni.role() == null ? null : Role.valueOf(((CarrierEthernetUni) ni).role().name()));
+ } else if (ni.type().equals(CarrierEthernetNetworkInterface.Type.INNI)) {
+ this.role = (ni.role() == null ? null : Role.valueOf(((CarrierEthernetInni) ni).role().name()));
+ } else if (ni.type().equals(CarrierEthernetNetworkInterface.Type.ENNI)) {
+ this.role = (ni.role() == null ? null : Role.valueOf(((CarrierEthernetEnni) ni).role().name()));
+ }
+ this.ltpId = this.cp().deviceId().toString() + "/" + this.cp().port().toString();
+ this.ltpCfgId = (ltpCfgId == null ? this.ltpId : ltpCfgId);
+ }
+
+ public CarrierEthernetLogicalTerminationPoint(ConnectPoint cp, String ltpCfgId,
+ CarrierEthernetNetworkInterface.Type niType,
+ CarrierEthernetLogicalTerminationPoint.Role role) {
+ this.ltpId = cp.deviceId().toString() + "/" + cp.port().toString();
+ this.ltpCfgId = (ltpCfgId == null ? this.ltpId : ltpCfgId);
+ 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)) {
+ CarrierEthernetUni.Role uniRole = (role == null) ? null : CarrierEthernetUni.Role.valueOf(role.name());
+ this.ni = CarrierEthernetUni.builder()
+ .cp(cp)
+ .cfgId(ltpId)
+ .role(uniRole)
+ .build();
+ } else if (niType.equals(CarrierEthernetNetworkInterface.Type.INNI)) {
+ CarrierEthernetInni.Role inniRole = (role == null) ? null : CarrierEthernetInni.Role.valueOf(role.name());
+ this.ni = CarrierEthernetInni.builder()
+ .cp(cp)
+ .cfgId(ltpId)
+ .role(inniRole)
+ .build();
+ } else if (niType.equals(CarrierEthernetNetworkInterface.Type.ENNI)) {
+ CarrierEthernetEnni.Role enniRole = (role == null) ? null : CarrierEthernetEnni.Role.valueOf(role.name());
+ this.ni = CarrierEthernetEnni.builder()
+ .cp(cp)
+ .cfgId(ltpId)
+ .role(enniRole)
+ .build();
+ }
+ }
+
+ /**
+ * Returns associated connect point.
+ *
+ * @return associated connect point
+ */
+ public ConnectPoint cp() {
+ return ni.cp();
+ }
+
+ /**
+ * Returns LTP string identifier.
+ *
+ * @return LTP string identifier
+ */
+ public String id() {
+ return ltpId;
+ }
+
+ /**
+ * Returns LTP string config identifier.
+ *
+ * @return LTP string config identifier
+ */
+ public String cfgId() {
+ return ltpCfgId;
+ }
+
+ /**
+ * Returns LTP role - applicable only to service-specific LTPs.
+ *
+ * @return LTP role
+ */
+ public Role role() {
+ return role;
+ }
+
+ /**
+ * Returns LTP type.
+ *
+ * @return LTP type
+ */
+ public CarrierEthernetNetworkInterface.Type type() {
+ return ni.type();
+ }
+
+ /**
+ * Returns the NI associated with the LTP or null of there is none.
+ *
+ * @return NI associated with LTP
+ */
+ public CarrierEthernetNetworkInterface ni() {
+ return ni;
+ }
+
+ /**
+ * Returns the scope of the LTP (always matches that of the associated NI).
+ *
+ * @return LTP scope
+ */
+ public CarrierEthernetNetworkInterface.Scope scope() {
+ return this.ni().scope();
+ }
+
+ /**
+ * Returns counter with the number of references (from EVCs/FCs) to the associated NI.
+ *
+ * @return number of references counter
+ */
+ public AtomicInteger refCount() {
+ return ni().refCount();
+ }
+
+ /**
+ * Sets the NI associated with the LTP.
+ *
+ * @param ni the NI to set
+ */
+ public void setNi(CarrierEthernetNetworkInterface ni) {
+ this.ni = ni;
+ }
+
+ /**
+ * Sets LTP role - applicable only to EVC- or FC-specific LTPs.
+ *
+ * @param role the LTP role to set
+ */
+ public void setRole(Role role) {
+ this.role = role;
+ }
+
+ public String toString() {
+
+ return toStringHelper(this)
+ .add("id", ltpId)
+ .add("cfgId", ltpCfgId)
+ .add("role", role)
+ .add("ni", ni).toString();
+ }
+
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetNetworkInterface.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetNetworkInterface.java
new file mode 100644
index 0000000..322e3a4
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetNetworkInterface.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+
+import com.google.common.base.Objects;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.AbstractAnnotated;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Port;
+import org.onosproject.net.device.DeviceService;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a Carrier Ethernet Network Interface (UNI, INNI or ENNI).
+ */
+public abstract class CarrierEthernetNetworkInterface extends AbstractAnnotated {
+
+ protected static ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+
+ public enum Scope {
+ GLOBAL, SERVICE
+ }
+
+ public enum Type {
+ UNI, INNI, ENNI, GENERIC
+ }
+
+ protected ConnectPoint connectPoint;
+ protected String id;
+ protected String cfgId;
+ protected Bandwidth capacity;
+ protected Bandwidth usedCapacity;
+ protected Scope scope;
+ protected AtomicInteger refCount;
+ protected Type type;
+
+
+ public CarrierEthernetNetworkInterface(ConnectPoint connectPoint, Type type, String cfgId,
+ Annotations...annotations) {
+ super(annotations);
+ checkNotNull(connectPoint);
+ checkNotNull(type);
+ this.type = type;
+ this.connectPoint = connectPoint;
+ this.id = this.connectPoint.deviceId().toString() + "/" + this.connectPoint.port().toString();
+ this.cfgId = (cfgId == null ? this.id : cfgId);
+ DeviceService deviceService = serviceDirectory.get(DeviceService.class);
+ Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
+ if (port != null) {
+ this.capacity = Bandwidth.mbps(port.portSpeed());
+ } else {
+ this.capacity = Bandwidth.mbps((double) 1000);
+ }
+
+ this.usedCapacity = Bandwidth.mbps((double) 0);
+ this.scope = null;
+ this.refCount = new AtomicInteger();
+ }
+
+ /**
+ * Returns associated connect point.
+ *
+ * @return associated connect point
+ */
+ public ConnectPoint cp() {
+ return connectPoint;
+ }
+
+ /**
+ * Returns NI string identifier.
+ *
+ * @return NI string identifier
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * Returns NI string config identifier.
+ *
+ * @return NI string config identifier
+ */
+ public String cfgId() {
+ return cfgId;
+ }
+
+ /**
+ * Returns NI capacity.
+ *
+ * @return NI capacity
+ */
+ public Bandwidth capacity() {
+ return capacity;
+ }
+
+ /**
+ * Returns NI used capacity.
+ *
+ * @return NI used capacity
+ */
+ public Bandwidth usedCapacity() {
+ return usedCapacity;
+ }
+
+ /**
+ * Returns the NI S-TAG.
+ *
+ * @return NI S-TAG
+ */
+ public abstract VlanId sVlanId();
+
+ /**
+ * Returns the NI CE-VLAN ID.
+ *
+ * @return NI CE-VLAN ID
+ */
+ public abstract VlanId ceVlanId();
+
+ /**
+ * Returns the scope of the NI (GLOBAL or SERVICE).
+ *
+ * @return NI scope
+ */
+ public Scope scope() {
+ return scope;
+ }
+
+ /**
+ * Returns the type of the NI (UNI, INNI or ENNI).
+ *
+ * @return NI scope
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns counter with the number of references (from EVCs/FCs) to the particular NI.
+ *
+ * @return number of references counter
+ */
+ public AtomicInteger refCount() {
+ return refCount;
+ }
+
+ /**
+ * Sets NI string identifier.
+ *
+ * @param id the UNI string identifier to set
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets NI string config identifier.
+ *
+ * @param cfgId the UNI string config identifier to set
+ */
+ public void setCfgId(String cfgId) {
+ this.cfgId = cfgId;
+ }
+
+ /**
+ * Sets NI capacity.
+ *
+ * @param capacity the capacity to set
+ */
+ public void setCapacity(Bandwidth capacity) {
+ this.capacity = capacity;
+ }
+
+ /**
+ * Returns the NI role, depending on the NI.
+ *
+ * @param <T> the NI role
+ * @return the NI role
+ */
+ 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(CarrierEthernetNetworkInterface 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(CarrierEthernetNetworkInterface 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(CarrierEthernetNetworkInterface ni);
+
+ @Override
+ public String toString() {
+
+ return toStringHelper(this)
+ .add("id", id)
+ .add("cfgId", cfgId)
+ .add("capacity", capacity)
+ .add("usedCapacity", usedCapacity).toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ CarrierEthernetNetworkInterface that = (CarrierEthernetNetworkInterface) o;
+ return Objects.equal(connectPoint, that.connectPoint);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(connectPoint);
+ }
+
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetSpanningTreeWeight.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetSpanningTreeWeight.java
new file mode 100644
index 0000000..5f480d6
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetSpanningTreeWeight.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+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/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetUni.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetUni.java
new file mode 100644
index 0000000..2e97c61
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetUni.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+import org.slf4j.Logger;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Representation of a Carrier Ethernet UNI.
+ * Class can be used in different two ways:
+ * 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 final class CarrierEthernetUni extends CarrierEthernetNetworkInterface {
+
+ private final Logger log = getLogger(getClass());
+
+ public enum Role {
+
+ ROOT("Root"),
+ LEAF("Leaf");
+
+ private String value;
+
+ Role(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+ protected Role role = null;
+ protected Set<VlanId> ceVlanIdSet = Sets.newConcurrentHashSet();
+
+ // Note: INTERFACE BWP map can only have up to one element
+ protected final Map<CarrierEthernetBandwidthProfile.Type, Map<String, CarrierEthernetBandwidthProfile>> bwpMap =
+ new HashMap<>();
+
+ // TODO: May be needed to add refCount for CoS BWPs - only applicable to global UNIs
+ // TODO: Change ceVlanId to Collection<VlanId>
+ private CarrierEthernetUni(ConnectPoint cp, String uniCfgId, Role role,
+ VlanId ceVlanId,
+ CarrierEthernetBandwidthProfile bwp,
+ Annotations annotations) {
+ super(cp, Type.UNI, uniCfgId, annotations);
+
+ this.role = role;
+ // FIXME: Set the NI scope directly instead?
+ this.scope = (role == null ? Scope.GLOBAL : Scope.SERVICE);
+ if (ceVlanId != null) {
+ this.ceVlanIdSet.add(ceVlanId);
+ }
+ for (CarrierEthernetBandwidthProfile.Type bwpType : CarrierEthernetBandwidthProfile.Type.values()) {
+ this.bwpMap.put(bwpType, new HashMap<>());
+ }
+
+ if (bwp != null) {
+ // Limit the CIR of the provided bwp according to UNI capacity
+ if (bwp.cir().bps() > this.capacity.bps()) {
+ log.warn("UNI {}: Limiting provided CIR ({} bps) to UNI capacity ({} bps)",
+ this.id, (long) bwp.cir().bps(), this.capacity);
+ }
+ bwp.setCir(Bandwidth.bps(Math.min(bwp.cir().bps(), this.capacity.bps())));
+
+ // Limit the EIR of the provided bwp according to the UNI capacity minus CIR
+ if (bwp.eir().bps() > this.capacity.bps() - bwp.cir().bps()) {
+ log.warn("UNI {}: Limiting provided EIR ({} bps) to UNI capacity minus CIR ({} bps)",
+ this.id, bwp.eir().bps(), this.capacity.bps() - bwp.cir().bps());
+ }
+ bwp.setEir(Bandwidth.bps(Math.min(bwp.eir().bps(), this.capacity.bps() - bwp.cir().bps())));
+
+ addBandwidthProfile(bwp);
+ }
+ }
+
+ /**
+ * Adds a BW profile to a UNI.
+ *
+ * @param bwp the BWP to be added
+ */
+ 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 ni the EVC- or FC-specific UNI to be added
+ */
+ @Override
+ public void addEcNi(CarrierEthernetNetworkInterface ni) {
+ CarrierEthernetUni uni;
+ if (!(ni instanceof CarrierEthernetUni)) {
+ return;
+ } else {
+ uni = (CarrierEthernetUni) ni;
+ }
+
+ // Add CE-VLAN ID
+ if (uni.ceVlanId() != VlanId.NONE) {
+ this.ceVlanIdSet.add(uni.ceVlanId());
+ }
+
+ // Add UNI BWP
+ CarrierEthernetBandwidthProfile bwp = uni.bwp();
+ if (bwp != null) {
+ Map<String, CarrierEthernetBandwidthProfile> subBwpMap = this.bwpMap.get(bwp.type());
+ subBwpMap.put(bwp.id(), bwp);
+ this.bwpMap.put(bwp.type(), subBwpMap);
+ // Used capacity cannot be more than UNI capacity
+ // (redundant check - should be avoided by check in validateBwp)
+ this.usedCapacity = Bandwidth.bps(Math.min(this.usedCapacity.bps() + bwp.cir().bps(), this.capacity.bps()));
+ }
+ }
+
+ /**
+ * Removes the resources associated with an EVC- or FC-specific UNI from a global UNI.
+ *
+ * @param ni the EVC- or FC-specific UNI to be removed
+ */
+ @Override
+ public void removeEcNi(CarrierEthernetNetworkInterface ni) {
+ CarrierEthernetUni uni;
+ if (!(ni instanceof CarrierEthernetUni)) {
+ return;
+ } else {
+ uni = (CarrierEthernetUni) ni;
+ }
+
+ // Remove UNI CE-VLAN ID
+ if (uni.ceVlanId() != VlanId.NONE) {
+ ceVlanIdSet.remove(uni.ceVlanId());
+ }
+
+ // Remove UNI BWP
+ CarrierEthernetBandwidthProfile bwp = uni.bwp();
+ Map<String, CarrierEthernetBandwidthProfile> subBwpMap = this.bwpMap.get(bwp.type());
+ subBwpMap.remove(bwp.id());
+ this.bwpMap.put(bwp.type(), subBwpMap);
+ // Redundant check - should be avoided by check in validateBwp
+ this.usedCapacity = Bandwidth.bps(Math.max(this.usedCapacity.bps() - bwp.cir().bps(), 0));
+ }
+
+ /**
+ * Validates whether an EVC- or FC-specific UNI is compatible with the corresponding global UNI.
+ *
+ * @param ni the EVC- or FC-specific UNI
+ * @return boolean value indicating whether the UNIs are compatible
+ */
+ @Override
+ public boolean validateEcNi(CarrierEthernetNetworkInterface ni) {
+ CarrierEthernetUni uni;
+ if (!(ni instanceof CarrierEthernetUni)) {
+ return false;
+ } else {
+ uni = (CarrierEthernetUni) ni;
+ }
+
+ // Check if the CE-VLAN ID of the UNI is already included in global UNI
+ if (uni.ceVlanId() != VlanId.NONE) {
+ if (ceVlanIdSet.contains(uni.ceVlanId())) {
+ log.error("CE-VLAN ID {} already exists in UNI {}", uni.ceVlanId().toString(), this.id());
+ return false;
+ }
+ }
+
+ CarrierEthernetBandwidthProfile bwp = uni.bwp();
+
+ // Check if the UNI BW profile is allowed based on its type and id and the existing profiles on the global UNI
+ for (CarrierEthernetBandwidthProfile.Type bwpType : CarrierEthernetBandwidthProfile.Type.values()) {
+ Map<String, CarrierEthernetBandwidthProfile> subBwpMap = this.bwpMap.get(bwpType);
+ if (!(subBwpMap.isEmpty())) {
+ if (bwpType != bwp.type()) {
+ log.error("Different bandwidth profile type than {} already exists in UNI {}",
+ bwp.type().name(), this.id());
+ return false;
+ } else if (subBwpMap.containsKey(bwp.id())) {
+ log.error("Bandwidth profile {} already exists in UNI {}", bwp.id(), this.id());
+ return false;
+ } else if (bwp.type().equals(CarrierEthernetBandwidthProfile.Type.INTERFACE)) {
+ log.error("Another bandwidth profile already exists in UNI {}", this.id());
+ return false;
+ }
+ }
+ }
+
+ // Check whether there are enough available resources on the UNI
+ if (usedCapacity.bps() + bwp.cir().bps() > capacity.bps()) {
+ log.error("Bandwidth profile {} cannot be added to UNI {} due to lack of resources", bwp.id(), this.id());
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns UNI role (ROOT or LEAF) - applicable only to service-specific UNIs.
+ *
+ * @return UNI role
+ */
+ @Override
+ public Role role() {
+ return role;
+ }
+
+ /**
+ * Returns the CE-VLAN id associated with a local UNI, or the first CE-VLAN ID found for a global UNI.
+ *
+ * @return CE-VLAN id
+ */
+ @Override
+ public VlanId ceVlanId() {
+ if (ceVlanIdSet.isEmpty()) {
+ return VlanId.NONE;
+ } else {
+ return ceVlanIdSet.iterator().next();
+ }
+ }
+
+ /**
+ * Always returns null, since S-TAGs are not associated with UNIs.
+ *
+ * @return null
+ */
+ @Override
+ public VlanId sVlanId() {
+ return null;
+ }
+
+ /**
+ * Returns the set of CE-VLAN ids associated with the UNI.
+ *
+ * @return CE-VLAN id set
+ */
+ public Set<VlanId> ceVlanIdSet() {
+ return ImmutableSet.copyOf(ceVlanIdSet);
+ }
+
+ /**
+ * Returns the first non-null BWP of the UNI found - used mainly for service-specific UNIs.
+ * Note: The EVC-specific UNI representation will only have one BWP
+ *
+ * @return first non-null BWP of the UNI
+ */
+ public CarrierEthernetBandwidthProfile bwp() {
+
+ for (CarrierEthernetBandwidthProfile.Type bwpType : CarrierEthernetBandwidthProfile.Type.values()) {
+ if (!(this.bwpMap.get(bwpType).isEmpty())) {
+ return bwpMap.get(bwpType).entrySet().iterator().next().getValue();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a collection of all BWPs of the UNI.
+ *
+ * @return all BWPs of the UNI
+ */
+ public Collection<CarrierEthernetBandwidthProfile> bwps() {
+
+ for (CarrierEthernetBandwidthProfile.Type bwpType : CarrierEthernetBandwidthProfile.Type.values()) {
+ if (!(this.bwpMap.get(bwpType).isEmpty())) {
+ return bwpMap.get(bwpType).values();
+ }
+ }
+ // Return an empty collection if no BWPs exist
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String toString() {
+
+ return toStringHelper(this)
+ .add("id", this.id)
+ .add("cfgId", this.cfgId)
+ .add("role", role)
+ .add("refCount", refCount)
+ .add("ceVlanIds", ceVlanIdSet)
+ .add("capacity", this.capacity)
+ .add("usedCapacity", this.usedCapacity)
+ .add("bandwidthProfiles", this.bwps()).toString();
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of CarrierEthernetUni entities.
+ */
+ public static final class Builder {
+
+ private ConnectPoint cp;
+ private String cfgId;
+ private Role role;
+ private VlanId ceVlanId;
+ private CarrierEthernetBandwidthProfile bwp;
+ private Annotations annotations;
+
+ /**
+ * Sets the cp of this builder.
+ *
+ * @param cp the builder cp to set
+ * @return this builder instance
+ */
+ public Builder cp(ConnectPoint cp) {
+ this.cp = cp;
+ return this;
+ }
+
+ /**
+ * Sets the cfgId of this builder.
+ *
+ * @param cfgId the builder cfgId to set
+ * @return this builder instance
+ */
+ public Builder cfgId(String cfgId) {
+ this.cfgId = cfgId;
+ return this;
+ }
+
+ /**
+ * Sets the role of this builder.
+ *
+ * @param role the builder role to set
+ * @return this builder instance
+ */
+ public Builder role(Role role) {
+ this.role = role;
+ return this;
+ }
+
+ /**
+ * Sets the ceVlanId of this builder.
+ *
+ * @param ceVlanId the builder ceVlanId to set
+ * @return this builder instance
+ */
+ public Builder ceVlanId(VlanId ceVlanId) {
+ this.ceVlanId = ceVlanId;
+ return this;
+ }
+
+ /**
+ * Sets the bwp of this builder.
+ *
+ * @param bwp the builder bwp to set
+ * @return this builder instance
+ */
+ public Builder bwp(CarrierEthernetBandwidthProfile bwp) {
+ this.bwp = bwp;
+ return this;
+ }
+ /**
+ * Sets annotations.
+ *
+ * @param annotations annotations
+ * @return this builder instance
+ */
+ public CarrierEthernetUni.Builder annotations(Annotations annotations) {
+ this.annotations = annotations;
+ return this;
+ }
+
+ /**
+ * Builds a new CarrierEthernetUni instance.
+ * based on this builder's parameters
+ *
+ * @return a new CarrierEthernetUni instance
+ */
+ public CarrierEthernetUni build() {
+ return new CarrierEthernetUni(cp, cfgId, role, ceVlanId, bwp, annotations);
+ }
+ }
+}
+
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetVirtualConnection.java b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetVirtualConnection.java
new file mode 100644
index 0000000..15686d9
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/CarrierEthernetVirtualConnection.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.time.Duration;
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a Carrier Ethernet EVC.
+ */
+public final class CarrierEthernetVirtualConnection extends CarrierEthernetConnection {
+
+ 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;
+
+ // TODO: Remove id from constructor - currently used only when updating EVC
+ private CarrierEthernetVirtualConnection(EvcConnId 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 numerical identifier.
+ *
+ * @return numerical identifier
+ */
+ public Short shortId() {
+ return shortId;
+ }
+
+ /**
+ * Returns the Virtual status of the service (i.e. if all UNIs have CE-VLAN ids).
+ *
+ * @return true if service is virtual, false otherwise
+ */
+ public boolean isVirtual() {
+ return isVirtual;
+ }
+
+ /**
+ * Returns the maximum number of UNIs in the EVC.
+ *
+ * @return true the maximum number of UNIs in the EVC
+ */
+ public Integer maxNumUni() {
+ return maxNumUni;
+ }
+
+ /**
+ * Returns set of UNIs.
+ *
+ * @return set of UNIs
+ */
+ public Set<CarrierEthernetUni> uniSet() {
+ return ImmutableSet.copyOf(uniSet);
+ }
+
+ /**
+ * Returns the set of FCs associated with the EVC.
+ *
+ * @return set of FCs associated with the EVC
+ */
+ public Set<CarrierEthernetForwardingConstruct> fcSet() {
+ return ImmutableSet.copyOf(fcSet);
+ }
+
+ /**
+ * Set numerical identifier.
+ *
+ * @param shortId the numerical identifier to set
+ */
+ public void setShortId(Short shortId) {
+ this.shortId = shortId;
+ }
+
+ /**
+ * Sets the set of UNIs.
+ *
+ * @param uniSet the set of UNIs to be set
+ */
+ public void setUniSet(Set<CarrierEthernetUni> uniSet) {
+ this.uniSet = uniSet;
+ }
+
+ /**
+ * Sets the set of FCs.
+ *
+ * @param fcSet the set of UNIs to be set
+ */
+ public void setFcSet(Set<CarrierEthernetForwardingConstruct> fcSet) {
+ this.fcSet = fcSet;
+ }
+
+ /**
+ * Sets the Virtual status of the service.
+ *
+ * @param isVirtual boolean value with the status to set
+ */
+ public void setIsVirtual(boolean isVirtual) {
+ this.isVirtual = isVirtual;
+ }
+
+ @Override
+ public String toString() {
+
+ return toStringHelper(this)
+ .omitNullValues()
+ .add("id", id)
+ .add("cfgId", cfgId)
+ .add("type", type)
+ .add("state", state)
+ .add("UNIs", uniSet)
+ .add("FCs", fcSet).toString();
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of CarrierEthernetVirtualConnection entities.
+ */
+ public static final class Builder {
+
+ private EvcConnId id;
+ private String cfgId;
+ private Type type;
+ private Duration maxLatency;
+ private Set<CarrierEthernetUni> uniSet;
+ private Integer maxNumUni;
+
+ /**
+ * Sets the id of this builder.
+ *
+ * @param id the builder id to set
+ * @return this builder instance
+ */
+ public Builder id(EvcConnId id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Sets the cfgId of this builder.
+ *
+ * @param cfgId the builder cfgId to set
+ * @return this builder instance
+ */
+ public Builder cfgId(String cfgId) {
+ this.cfgId = cfgId;
+ return this;
+ }
+
+ /**
+ * Sets the type of this builder.
+ *
+ * @param type the builder type to set
+ * @return this builder instance
+ */
+ public Builder type(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * Sets the maxLatency of this builder.
+ *
+ * @param maxLatency the builder maxLatency to set
+ * @return this builder instance
+ */
+ public Builder maxLatency(Duration maxLatency) {
+ this.maxLatency = maxLatency;
+ return this;
+ }
+
+ /**
+ * Sets the uniSet of this builder.
+ *
+ * @param uniSet the builder uniSet to set
+ * @return this builder instance
+ */
+ public Builder uniSet(Set<CarrierEthernetUni> uniSet) {
+ this.uniSet = uniSet;
+ return this;
+ }
+
+ /**
+ * Sets the maxNumUni of this builder.
+ *
+ * @param maxNumUni the builder maxNumUni to set
+ * @return this builder instance
+ */
+ public Builder maxNumUni(Integer maxNumUni) {
+ this.maxNumUni = maxNumUni;
+ return this;
+ }
+
+ /**
+ * Builds a new CarrierEthernetVirtualConnection instance.
+ * based on this builder's parameters
+ *
+ * @return a new CarrierEthernetVirtualConnection instance
+ */
+ public CarrierEthernetVirtualConnection build() {
+ checkNotNull(type, "EVC must have a type");
+ checkArgument(uniSet != null && uniSet.size() > 1,
+ "EVC must include at least two UNIs");
+ return new CarrierEthernetVirtualConnection(id, cfgId, type, maxNumUni, uniSet, maxLatency);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/DomainEndPoint.java b/ce-api/src/main/java/org/opencord/ce/api/models/DomainEndPoint.java
new file mode 100644
index 0000000..f7d8375
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/DomainEndPoint.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.domain.DomainId;
+
+/**
+ * ONOS cluster endpoint for the communication between local and global.
+ */
+public class DomainEndPoint {
+ private DomainId domainId;
+ private IpAddress publicIp;
+ private int port;
+ private String username;
+ private String password;
+ private String topic;
+
+ public DomainEndPoint(DomainId domainId, IpAddress publicIp, int port,
+ String username, String password, String topic) {
+ this.domainId = domainId;
+ this.publicIp = publicIp;
+ this.port = port;
+ this.username = username;
+ this.password = password;
+ this.topic = topic;
+ }
+
+ public DomainId domainId() {
+ return domainId;
+ }
+
+ public IpAddress publicIp() {
+ return publicIp;
+ }
+
+ public int port() {
+ return port;
+ }
+
+ public String username() {
+ return username;
+ }
+
+ public String password() {
+ return password;
+ }
+
+ public String topic() {
+ return topic;
+ }
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/EvcConnId.java b/ce-api/src/main/java/org/opencord/ce/api/models/EvcConnId.java
new file mode 100644
index 0000000..77de4a2
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/EvcConnId.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+import org.onlab.util.Identifier;
+
+/**
+ * Virtual connection identifier class.
+ */
+public class EvcConnId extends Identifier<String> {
+
+ public EvcConnId(String connId) {
+ super(connId);
+ }
+
+ public static EvcConnId of(String connId) {
+ return new EvcConnId(connId);
+ }
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/PortVlanConfig.java b/ce-api/src/main/java/org/opencord/ce/api/models/PortVlanConfig.java
new file mode 100644
index 0000000..be2e5ee
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/PortVlanConfig.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.config.Config;
+
+import java.util.Optional;
+
+/**
+ * Configuration information for edge connect point and corresponding VLAN tag.
+ */
+public class PortVlanConfig extends Config<ConnectPoint> {
+ public static final String CONFIG_KEY = "portVlan";
+
+ public static final String S_TAG_KEY = "s-tag";
+
+ public Optional<VlanId> portVlanId() {
+ String s = get(S_TAG_KEY, null);
+ if (s == null) {
+ return Optional.empty();
+ }
+ return Optional.of(VlanId.vlanId(Short.valueOf(s)));
+ }
+
+ public PortVlanConfig portVlanId(VlanId vlanId) {
+ if (vlanId == null) {
+ return (PortVlanConfig) setOrClear(S_TAG_KEY, (String) null);
+ }
+ return (PortVlanConfig) setOrClear(S_TAG_KEY, String.valueOf(vlanId.toShort()));
+ }
+}
\ No newline at end of file
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetBwProfileCodec.java b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetBwProfileCodec.java
new file mode 100644
index 0000000..1865ab3
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetBwProfileCodec.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models.codecs;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.util.Bandwidth;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.opencord.ce.api.models.CarrierEthernetBandwidthProfile;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Codec for {@link CarrierEthernetBandwidthProfile}.
+ */
+public class CarrierEthernetBwProfileCodec extends JsonCodec<CarrierEthernetBandwidthProfile> {
+ private static final String ID = "bwpId";
+ private static final String CFG_ID = "cfgId";
+ private static final String TYPE = "bwpType";
+ private static final String CIR = "cir";
+ private static final String CBS = "cbs";
+ private static final String EIR = "eir";
+ private static final String EBS = "ebs";
+
+ @Override
+ public ObjectNode encode(CarrierEthernetBandwidthProfile bwProfile, CodecContext context) {
+ checkNotNull(bwProfile, "BW profile cannot be null");
+ ObjectNode result = context.mapper().createObjectNode();
+ result.put(ID, bwProfile.id())
+ .put(CFG_ID, bwProfile.cfgId())
+ .put(TYPE, bwProfile.type().name())
+ .put(CIR, bwProfile.cir().bps())
+ .put(EIR, bwProfile.eir().bps())
+ .put(CBS, bwProfile.cbs())
+ .put(EBS, bwProfile.ebs());
+ return result;
+ }
+
+ @Override
+ public CarrierEthernetBandwidthProfile decode(ObjectNode json, CodecContext context) {
+ return CarrierEthernetBandwidthProfile.builder()
+ .id(json.path(ID).asText())
+ .cfgId(json.path(CFG_ID).asText())
+ .type(CarrierEthernetBandwidthProfile.Type.valueOf(json.path(TYPE).asText()))
+ .cir(Bandwidth.bps(json.path(CIR).asDouble()))
+ .eir(Bandwidth.bps(json.path(EIR).asDouble()))
+ .cbs(json.path(CBS).asLong())
+ .ebs(json.path(EBS).asLong())
+ .build();
+ }
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetConnectionCodec.java b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetConnectionCodec.java
new file mode 100644
index 0000000..093c373
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetConnectionCodec.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models.codecs;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.opencord.ce.api.models.CarrierEthernetConnection;
+import org.opencord.ce.api.models.EvcConnId;
+
+import java.time.Duration;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opencord.ce.api.models.CarrierEthernetConnection.Type;
+import static org.opencord.ce.api.models.CarrierEthernetConnection.State;
+/**
+ * Codec for {@link org.opencord.ce.api.models.CarrierEthernetConnection}.
+ */
+public class CarrierEthernetConnectionCodec extends JsonCodec<CarrierEthernetConnection> {
+
+ private static final String ID = "connectionId";
+ private static final String CFG_ID = "cfgId";
+ private static final String TYPE = "type";
+ private static final String STATE = "state";
+ private static final String MAX_LATENCY = "maxLatency";
+
+ @Override
+ public ObjectNode encode(CarrierEthernetConnection connection, CodecContext context) {
+ checkNotNull(connection, "Java connection object cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(ID, connection.id().id())
+ .put(CFG_ID, connection.cfgId())
+ .put(TYPE, connection.type().toString())
+ .put(STATE, connection.type().toString())
+ .put(MAX_LATENCY, connection.maxLatency().toString());
+ return result;
+ }
+
+ @Override
+ public CarrierEthernetConnection decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ EvcConnId id = EvcConnId.of(json.path(ID).asText());
+ String cfgId = json.path(CFG_ID).asText();
+ Type type = Type.valueOf(json.path(TYPE).asText());
+ State state = State.valueOf(json.path(STATE).asText());
+ Duration maxLatency = Duration.parse(json.path(MAX_LATENCY).asText());
+ return null;
+ }
+
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetEvcCodec.java b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetEvcCodec.java
new file mode 100644
index 0000000..89bc338
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetEvcCodec.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models.codecs;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.opencord.ce.api.models.CarrierEthernetBandwidthProfile;
+import org.opencord.ce.api.models.CarrierEthernetNetworkInterface;
+import org.opencord.ce.api.models.CarrierEthernetUni;
+import org.opencord.ce.api.models.CarrierEthernetVirtualConnection;
+import org.opencord.ce.api.models.EvcConnId;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.opencord.ce.api.models.CarrierEthernetEvcUtils.generateEvcType;
+import static org.opencord.ce.api.models.CarrierEthernetEvcUtils.generateMaxNumUni;
+import static org.opencord.ce.api.models.CarrierEthernetEvcUtils.generateUniSet;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of encoder for Alarm codec.
+ */
+public class CarrierEthernetEvcCodec extends JsonCodec<CarrierEthernetVirtualConnection> {
+
+ private static final String EVC_ID_REQUIRED = "EVC Id Must be specified";
+ private static final String EVC_TYPE_REQUIRED = "EVC Type Must be specified";
+ private static final String ARRAY_REQUIRED = "UNI array was not specified";
+
+ private final Logger log = getLogger(getClass());
+
+ @Override
+ public ObjectNode encode(CarrierEthernetVirtualConnection evc, CodecContext context) {
+ ObjectNode evcRoot = context.mapper().createObjectNode();
+ evcRoot.put("evcCfgId", evc.cfgId());
+ evcRoot.put("evcId", evc.id().id());
+ ArrayNode uniList = context.mapper()
+ .valueToTree(evc.uniSet().stream()
+ .map(CarrierEthernetNetworkInterface::id)
+ .collect(Collectors.toList()));
+ evcRoot.putArray("uniList").addAll(uniList);
+ evcRoot.put("maxNumUni", evc.maxNumUni());
+ CarrierEthernetUni uni = evc.uniSet().iterator().next();
+ evcRoot.put("vlanId", uni.ceVlanId().toString());
+ CarrierEthernetBandwidthProfile bwp = uni.bwp();
+ if (bwp != null) {
+ evcRoot.put("cir", bwp.cir().bps());
+ evcRoot.put("eir", bwp.eir().bps());
+ evcRoot.put("cbs", bwp.cbs());
+ evcRoot.put("ebs", bwp.ebs());
+ }
+ return evcRoot;
+ }
+
+ @Override
+ public CarrierEthernetVirtualConnection decode(ObjectNode json, CodecContext context) {
+ String argEvcCfgId = json.get("evcCfgId").asText(null);
+ String argEvcId = null;
+ if (json.has("evcId")) {
+ argEvcId = json.get("evcId").asText();
+ }
+ ArrayNode uniArray = nullIsIllegal((ArrayNode) json.get("uniList"),
+ ARRAY_REQUIRED);
+ List<String> uniList = new ArrayList<>();
+ uniArray.forEach(jsonNode -> uniList.add(jsonNode.asText()));
+ String evcTypeString = nullIsIllegal(json.get("evcType").asText(),
+ EVC_TYPE_REQUIRED);
+ int maxNumUni = -1;
+ if (json.has("maxNumUni")) {
+ maxNumUni = json.get("maxNumUni").asInt(-1);
+ }
+
+ short vlanId = -1;
+ if (json.has("vlanId")) {
+ vlanId = json.get("vlanId").shortValue();
+ }
+ double cir = json.get("cir").asDouble(0.0);
+ double eir = json.get("eir").asDouble(0.0);
+ long cbs = json.get("cbs").asLong(0L);
+ long ebs = json.get("ebs").asLong(0L);
+ log.info("Received REST call with parameters: " + "evcCfgId={}, evcId={}," +
+ " uniList={}, evcType={}, maxNumUni={}, vlanId={}, cir={}, " +
+ "eir={}, cbs={}, ebs={}", argEvcCfgId, argEvcId, uniList,
+ evcTypeString, maxNumUni, vlanId, cir, eir, cbs, ebs);
+ return CarrierEthernetVirtualConnection.builder()
+ .id(EvcConnId.of(argEvcId == null ? argEvcCfgId : argEvcId))
+ .cfgId(argEvcCfgId)
+ .type(generateEvcType(evcTypeString, uniList))
+ .maxNumUni(generateMaxNumUni(maxNumUni, evcTypeString, uniList))
+ .uniSet(generateUniSet(evcTypeString, uniList.subList(1, uniList.size()),
+ vlanId, uniList.get(0), argEvcCfgId, cir, eir,
+ cbs, ebs))
+ .build();
+ }
+
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetNetworkInterfaceCodec.java b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetNetworkInterfaceCodec.java
new file mode 100644
index 0000000..7395279
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CarrierEthernetNetworkInterfaceCodec.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models.codecs;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.VlanId;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.ConnectPoint;
+import org.opencord.ce.api.models.CarrierEthernetBandwidthProfile;
+import org.opencord.ce.api.models.CarrierEthernetEnni;
+import org.opencord.ce.api.models.CarrierEthernetGenericNi;
+import org.opencord.ce.api.models.CarrierEthernetInni;
+import org.opencord.ce.api.models.CarrierEthernetNetworkInterface;
+import org.opencord.ce.api.models.CarrierEthernetUni;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opencord.ce.api.models.CarrierEthernetNetworkInterface.Type;
+
+/**
+ * Codec for {@link org.opencord.ce.api.models.CarrierEthernetNetworkInterface}.
+ */
+public class CarrierEthernetNetworkInterfaceCodec extends JsonCodec<CarrierEthernetNetworkInterface> {
+
+ private static final String TYPE = "type";
+ private static final String CONNECT_POINT = "cp";
+ private static final String NI_ID = "niId";
+ private static final String CFG_ID = "cfgId";
+ private static final String BWP = "bwp";
+ private static final String C_TAGS = "cTags";
+ private static final String ROLE = "role";
+ private static final String CAPACITY = "capacity";
+ private static final String USED_CAPACITY = "usedCapacity";
+ private static final String S_TAG = "sTag";
+ private static final String C_TAG = "cTag";
+
+ @Override
+ public ObjectNode encode(CarrierEthernetNetworkInterface networkInterface, CodecContext context) {
+ checkNotNull(networkInterface, "Java networkInterface class cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(CFG_ID, networkInterface.id())
+ .put(TYPE, networkInterface.type().toString())
+ .put(ROLE, networkInterface.role().toString());
+ if (networkInterface.capacity() != null) {
+ result.put(CAPACITY, networkInterface.capacity().bps());
+ }
+ if (networkInterface.usedCapacity() != null) {
+ result.put(USED_CAPACITY, networkInterface.usedCapacity().bps());
+ }
+ JsonCodec<ConnectPoint> cpCodec = context.codec(ConnectPoint.class);
+ result.set(CONNECT_POINT, cpCodec.encode(networkInterface.cp(), context));
+ switch (networkInterface.type()) {
+ case UNI:
+ CarrierEthernetUni uni = (CarrierEthernetUni) networkInterface;
+ JsonCodec<CarrierEthernetBandwidthProfile> bwpCodec =
+ context.codec(CarrierEthernetBandwidthProfile.class);
+ result.set(BWP, bwpCodec.encode(uni.bwp(), context));
+ ArrayNode ctags = context.mapper().createArrayNode();
+ uni.ceVlanIdSet().forEach(ceVlan -> ctags.add(ceVlan.toShort()));
+ result.set(C_TAGS, ctags);
+ break;
+ case INNI:
+ CarrierEthernetInni inni = (CarrierEthernetInni) networkInterface;
+ result.put(S_TAG, inni.sVlanId().toShort());
+ break;
+ case ENNI:
+ CarrierEthernetEnni enni = (CarrierEthernetEnni) networkInterface;
+ result.put(S_TAG, enni.sVlanId().toShort());
+ break;
+ case GENERIC:
+ default:
+ }
+ return result;
+ }
+
+ @Override
+ public CarrierEthernetNetworkInterface decode(ObjectNode json, CodecContext context) {
+ String id = json.path(NI_ID).asText();
+ String cfgId = json.path(CFG_ID).asText();
+ Type type = Type.valueOf(json.path(TYPE).asText());
+
+ JsonCodec<ConnectPoint> cpCodec = context.codec(ConnectPoint.class);
+ ConnectPoint cp = cpCodec.decode((ObjectNode) json.path(CONNECT_POINT), context);
+ CarrierEthernetNetworkInterface ni;
+ switch (type) {
+ case UNI:
+ JsonCodec<CarrierEthernetBandwidthProfile> bwpCodec =
+ context.codec(CarrierEthernetBandwidthProfile.class);
+ Set<VlanId> ceVlanIds = new HashSet<>();
+ json.path(C_TAGS).forEach(jsonCeVlan ->
+ ceVlanIds.add(VlanId.vlanId(jsonCeVlan.shortValue())));
+ CarrierEthernetUni.Role role = null;
+ for (CarrierEthernetUni.Role r : CarrierEthernetUni.Role.values()) {
+ if (r.toString().equals(json.path(ROLE).asText())) {
+ role = r;
+ break;
+ }
+ }
+ ni = CarrierEthernetUni.builder()
+ .cp(cp)
+ .cfgId(cfgId)
+ .bwp(bwpCodec.decode((ObjectNode) json.path(BWP), context))
+ .ceVlanId(ceVlanIds.iterator().next())
+ .role(role)
+ .build();
+ break;
+ case ENNI:
+ VlanId sTag = VlanId.vlanId(json.path(S_TAG).shortValue());
+ CarrierEthernetEnni.Role roleEnni = null;
+ for (CarrierEthernetEnni.Role r : CarrierEthernetEnni.Role.values()) {
+ if (r.toString().equals(json.path(ROLE).asText())) {
+ roleEnni = r;
+ break;
+ }
+ }
+ ni = CarrierEthernetEnni.builder()
+ .cp(cp)
+ .cfgId(cfgId)
+ .sVlanId(sTag)
+ .role(roleEnni)
+ .build();
+ break;
+ case INNI:
+ VlanId sTagInni = VlanId.vlanId(json.path(S_TAG).shortValue());
+ CarrierEthernetInni.Role roleInni = null;
+ for (CarrierEthernetInni.Role r : CarrierEthernetInni.Role.values()) {
+ if (r.toString().equals(json.path(ROLE).asText())) {
+ roleInni = r;
+ break;
+ }
+ }
+ ni = CarrierEthernetInni.builder()
+ .cp(cp)
+ .cfgId(cfgId)
+ .sVlanId(sTagInni)
+ .role(roleInni)
+ .build();
+ break;
+ case GENERIC:
+ default:
+ ni = new CarrierEthernetGenericNi(cp, cfgId);
+ }
+ return ni;
+ }
+
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CodecRegistrator.java b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CodecRegistrator.java
new file mode 100644
index 0000000..67b46ae
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/CodecRegistrator.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models.codecs;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.codec.CodecService;
+import org.opencord.ce.api.models.CarrierEthernetBandwidthProfile;
+import org.opencord.ce.api.models.CarrierEthernetForwardingConstruct;
+import org.opencord.ce.api.models.CarrierEthernetLogicalTerminationPoint;
+import org.opencord.ce.api.models.CarrierEthernetNetworkInterface;
+import org.opencord.ce.api.models.CarrierEthernetVirtualConnection;
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+@Component(immediate = true)
+public class CodecRegistrator {
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CodecService codecService;
+
+ @Activate
+ public void activate() {
+ codecService.registerCodec(CarrierEthernetVirtualConnection.class,
+ new CarrierEthernetEvcCodec());
+ codecService.registerCodec(CarrierEthernetBandwidthProfile.class, new CarrierEthernetBwProfileCodec());
+ codecService.registerCodec(CarrierEthernetNetworkInterface.class,
+ new CarrierEthernetNetworkInterfaceCodec());
+ codecService.registerCodec(CarrierEthernetLogicalTerminationPoint.class,
+ new LogicalTerminationEndPointCodec());
+ codecService.registerCodec(CarrierEthernetForwardingConstruct.class,
+ new ForwardingConstructCodec());
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ codecService.unregisterCodec(CarrierEthernetVirtualConnection.class);
+ codecService.unregisterCodec(CarrierEthernetBandwidthProfile.class);
+ codecService.unregisterCodec(CarrierEthernetNetworkInterface.class);
+ codecService.unregisterCodec(CarrierEthernetForwardingConstruct.class);
+ codecService.unregisterCodec(CarrierEthernetLogicalTerminationPoint.class);
+ log.info("Stopped");
+ }
+}
\ No newline at end of file
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/codecs/ForwardingConstructCodec.java b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/ForwardingConstructCodec.java
new file mode 100644
index 0000000..3c633fc
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/ForwardingConstructCodec.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models.codecs;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.VlanId;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.opencord.ce.api.models.CarrierEthernetConnection;
+import org.opencord.ce.api.models.CarrierEthernetForwardingConstruct;
+import org.opencord.ce.api.models.CarrierEthernetLogicalTerminationPoint;
+import org.opencord.ce.api.models.EvcConnId;
+
+import java.time.Duration;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Codec {@link CarrierEthernetForwardingConstruct}.
+ */
+public class ForwardingConstructCodec extends JsonCodec<CarrierEthernetForwardingConstruct> {
+ private static final String FC_ID = "fcId";
+ private static final String CFG_ID = "cfgId";
+ private static final String TYPE = "type";
+ private static final String STATE = "state";
+ private static final String MAX_LATENCY = "maxLatency";
+ private static final String VLAN_ID = "vlanId";
+ private static final String LTP_LIST = "ltpList";
+
+ @Override
+ public ObjectNode encode(CarrierEthernetForwardingConstruct fc, CodecContext context) {
+ JsonCodec<CarrierEthernetLogicalTerminationPoint> ltpCodec =
+ context.codec(CarrierEthernetLogicalTerminationPoint.class);
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(FC_ID, fc.id().id())
+ .put(CFG_ID, fc.cfgId())
+ .put(TYPE, fc.type().toString())
+ .put(STATE, fc.type().toString())
+ .put(MAX_LATENCY, fc.maxLatency().toString());
+ result.put(VLAN_ID, fc.vlanId().toShort());
+ ArrayNode ltpsNode = context.mapper().createArrayNode();
+ fc.ltpSet().forEach(ltp ->
+ ltpsNode.add(ltpCodec.encode(ltp, context)));
+ result.set(LTP_LIST, ltpsNode);
+ return result;
+ }
+
+ @Override
+ public CarrierEthernetForwardingConstruct decode(ObjectNode json, CodecContext context) {
+ JsonCodec<CarrierEthernetLogicalTerminationPoint> ltpCodec =
+ context.codec(CarrierEthernetLogicalTerminationPoint.class);
+ Set<CarrierEthernetLogicalTerminationPoint> ltps =
+ new HashSet<>();
+ json.path(LTP_LIST).forEach(ltpJson ->
+ ltps.add(ltpCodec.decode((ObjectNode) ltpJson, context)));
+
+ CarrierEthernetForwardingConstruct fc = CarrierEthernetForwardingConstruct.builder()
+ .id(EvcConnId.of(json.path(FC_ID).asText()))
+ .cfgId(json.path(CFG_ID).asText())
+ .type(CarrierEthernetConnection.Type.valueOf(json.path(TYPE).asText()))
+ .maxLatency(Duration.parse(json.path(MAX_LATENCY).asText()))
+ .ltpSet(ltps)
+ .build();
+ fc.setVlanId(VlanId.vlanId(json.path(VLAN_ID).shortValue()));
+ return fc;
+ }
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/codecs/LogicalTerminationEndPointCodec.java b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/LogicalTerminationEndPointCodec.java
new file mode 100644
index 0000000..10061fd
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/LogicalTerminationEndPointCodec.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.models.codecs;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.opencord.ce.api.models.CarrierEthernetLogicalTerminationPoint;
+import org.opencord.ce.api.models.CarrierEthernetNetworkInterface;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opencord.ce.api.models.CarrierEthernetLogicalTerminationPoint.Role;
+
+/**
+ * Codec for {@link CarrierEthernetLogicalTerminationPoint}.
+ */
+public class LogicalTerminationEndPointCodec extends JsonCodec<CarrierEthernetLogicalTerminationPoint> {
+
+ private static final String ROLE = "role";
+ private static final String LTP_ID = "ltpId";
+ private static final String CFG_ID = "cfgId";
+ private static final String NETWORK_INTERFACE = "ni";
+
+ @Override
+ public ObjectNode encode(CarrierEthernetLogicalTerminationPoint ltp, CodecContext context) {
+ checkNotNull(ltp, "Java ltp object cannot be null");
+
+ JsonCodec<CarrierEthernetNetworkInterface> niCodec =
+ context.codec(CarrierEthernetNetworkInterface.class);
+
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(LTP_ID, ltp.id())
+ .put(CFG_ID, ltp.cfgId())
+ .put(ROLE, ltp.role().toString());
+ result.set(NETWORK_INTERFACE, niCodec.encode(ltp.ni(), context));
+ return result;
+ }
+
+ @Override
+ public CarrierEthernetLogicalTerminationPoint decode(ObjectNode json, CodecContext context) {
+
+ String ltpId = json.path(LTP_ID).asText();
+ String cfgId = json.path(CFG_ID).asText();
+ JsonCodec<CarrierEthernetNetworkInterface> niCodec =
+ context.codec(CarrierEthernetNetworkInterface.class);
+ ObjectNode niJson = get(json, NETWORK_INTERFACE);
+ CarrierEthernetNetworkInterface networkInterface =
+ niCodec.decode(niJson, context);
+ CarrierEthernetLogicalTerminationPoint ltp =
+ new CarrierEthernetLogicalTerminationPoint(cfgId, networkInterface);
+ for (Role r : Role.values()) {
+ if (r.toString().equals(json.path(ROLE).asText())) {
+ ltp.setRole(r);
+ }
+ }
+ return ltp;
+ }
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/codecs/package-info.java b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/package-info.java
new file mode 100644
index 0000000..060acc1
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/codecs/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Json/Java codecs package.
+ */
+package org.opencord.ce.api.models.codecs;
\ No newline at end of file
diff --git a/ce-api/src/main/java/org/opencord/ce/api/models/package-info.java b/ce-api/src/main/java/org/opencord/ce/api/models/package-info.java
new file mode 100644
index 0000000..6d815fe
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/models/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * VEE APIs.
+ */
+package org.opencord.ce.api.models;
\ No newline at end of file
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/MetroNetworkProvisionerService.java b/ce-api/src/main/java/org/opencord/ce/api/services/MetroNetworkProvisionerService.java
new file mode 100644
index 0000000..c57bccc
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/MetroNetworkProvisionerService.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services;
+
+
+import com.google.common.annotations.Beta;
+import org.opencord.ce.api.models.CarrierEthernetForwardingConstruct;
+
+/**
+ * Service interface for provisioning of Carrier Ethernet connections.
+ */
+@Beta
+public interface MetroNetworkProvisionerService {
+ /**
+ * Creates bandwidth profiles at the UNIs of an FC.
+ *
+ * @param fc the forwarding construct
+ */
+ void createBandwidthProfiles(CarrierEthernetForwardingConstruct fc);
+
+ /**
+ * Applies bandwidth profiles to the UNIs of an FC.
+ *
+ * @param fc the forwarding construct
+ */
+ void applyBandwidthProfiles(CarrierEthernetForwardingConstruct fc);
+
+ /**
+ * Removes bandwidth profiles from the UNIs of an FC.
+ *
+ * @param fc the forwarding construct
+ */
+ void removeBandwidthProfiles(CarrierEthernetForwardingConstruct fc);
+
+ /**
+ * Establishes connectivity for the provided FC by installing all necessary forwarding rules.
+ *
+ * @param fc the forwarding construct
+ */
+ void setupConnectivity(CarrierEthernetForwardingConstruct fc);
+
+ /**
+ * Removes connectivity for the provided FC by removing all installed forwarding rules.
+ *
+ * @param fc the forwarding construct
+ */
+ void removeConnectivity(CarrierEthernetForwardingConstruct fc);
+
+}
+
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/MetroNetworkVirtualNodeService.java b/ce-api/src/main/java/org/opencord/ce/api/services/MetroNetworkVirtualNodeService.java
new file mode 100644
index 0000000..2f1894d
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/MetroNetworkVirtualNodeService.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services;
+
+import org.opencord.ce.api.models.CarrierEthernetForwardingConstruct;
+import org.opencord.ce.api.models.CarrierEthernetNetworkInterface;
+import org.opencord.ce.api.models.CarrierEthernetUni;
+import org.opencord.ce.api.models.EvcConnId;
+
+import java.util.Set;
+
+/**
+ * Boundary interface between global Carrier Ethernet orchestration and local-site
+ * Carrier Ethernet service provisioning.
+ */
+public interface MetroNetworkVirtualNodeService {
+
+ /**
+ * Creates and submits FlowObjectives depending on role of the device in the FC and ingress/egress NI types.
+ *
+ * @param fc the forwarding construct
+ * @param srcNi the source network interface
+ * @param dstNiSet the set of destination network interfaces
+ */
+ void setNodeForwarding(CarrierEthernetForwardingConstruct fc, CarrierEthernetNetworkInterface srcNi,
+ Set<CarrierEthernetNetworkInterface> dstNiSet);
+
+ /**
+ * Creates and stores meters based on the UNI's bandwidth profile.
+ *
+ * @param fc the forwarding construct
+ * @param uni the user to network interface
+ */
+ void createBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni);
+
+ /**
+ * Applies meters to flows.
+ *
+ * @param fc the forwarding construct
+ * @param uni the user to network interface
+ */
+ void applyBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni);
+
+ /**
+ * Removes the meters associated with a specific UNI of an FC.
+ *
+ * @param fc the forwarding construct
+ * @param uni the user to network interface
+ */
+ void removeBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni);
+
+ /**
+ * Removes all installed flow objectives associated with a specific FC.
+ *
+ * @param fcId the forwarding construct
+ */
+ void removeAllForwardingResources(EvcConnId fcId);
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/MetroOrchestrationService.java b/ce-api/src/main/java/org/opencord/ce/api/services/MetroOrchestrationService.java
new file mode 100644
index 0000000..f0d158f
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/MetroOrchestrationService.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.ConnectPoint;
+import org.opencord.ce.api.models.CarrierEthernetForwardingConstruct;
+import org.opencord.ce.api.models.CarrierEthernetLogicalTerminationPoint;
+import org.opencord.ce.api.models.CarrierEthernetUni;
+import org.opencord.ce.api.models.CarrierEthernetVirtualConnection;
+import org.opencord.ce.api.models.EvcConnId;
+
+import java.util.Map;
+import java.util.Set;
+
+import static org.opencord.ce.api.models.CarrierEthernetNetworkInterface.Type;
+
+/**
+ * Service interface for Carrier Ethernet.
+ *
+ * Defines interactions with CE concepts such as Ethernet Virtual Circuit (EVC), Forwarding Construct (FC),
+ * Logical Termination Point (LTP), and User to Network Interface (UNI).
+ */
+@Beta
+public interface MetroOrchestrationService {
+ /**
+ * Returns the map of installed EVCs.
+ *
+ * @return map of installed EVCs
+ */
+ Map<EvcConnId, CarrierEthernetVirtualConnection> evcMap();
+
+ /**
+ * Get an installed EVC using its id.
+ *
+ * @param evcId the EVC id
+ * @return the EVC representation or null if the EVC doesn't exist
+ */
+ CarrierEthernetVirtualConnection getEvc(EvcConnId evcId);
+
+ // TODO: Add method to remove a UNI from an already installed EVC
+
+ /**
+ * 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 in case of failure
+ */
+ CarrierEthernetVirtualConnection installEvc(CarrierEthernetVirtualConnection evc);
+
+ /**
+ * Re-establish 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
+ */
+ CarrierEthernetVirtualConnection updateEvc(CarrierEthernetVirtualConnection evc);
+
+
+ /**
+ * Removes all resources associated with a specific installed EVC.
+ *
+ * @param evcId the EVC id
+ */
+ void removeEvc(EvcConnId evcId);
+
+
+ /**
+ * Removes all installed EVCs and the associated resources.
+ * <p>
+ * This will be called either from the deactivate method or as a response to a CLI/REST command.
+ */
+ void removeAllEvcs();
+
+ /**
+ * Enable or disable EVC fragmentation into FCs.
+ *
+ * @param evcFragmentationEnabled true to enable fragmentation, false otherwise
+ */
+ void setEvcFragmentation(boolean evcFragmentationEnabled);
+
+
+ /**
+ * Checks the fragmentation state of the EVC.
+ *
+ * @return true if fragmentation is enabled, false otherwise
+ */
+ boolean getEvcFragmentation();
+
+ /**
+ * Set the EVC fragmentation flag to the value before its last change.
+ *
+ */
+ void resetEvcFragmentation();
+
+ /**
+ * Get the map containing all installed FCs.
+ *
+ * @return the FC map
+ */
+ Map<EvcConnId, CarrierEthernetForwardingConstruct> fcMap();
+
+ /**
+ * Get an installed FC using its id.
+ *
+ * @param fcId the FC id
+ * @return the FC representation or null if the EVC doesn't exist
+ */
+ CarrierEthernetForwardingConstruct getFc(EvcConnId fcId);
+
+ /**
+ * Installs all resources associated with a specific FC.
+ *
+ * @param fc the FC to install
+ * @return the FC that was installed
+ */
+ CarrierEthernetForwardingConstruct installFc(CarrierEthernetForwardingConstruct fc);
+
+ /**
+ * Re-establish connectivity for an existing FC.
+ *
+ * @param fc the updated FC representation
+ * @return the possibly modified FC that was installed or null if updated FC could not be installed
+ */
+ CarrierEthernetForwardingConstruct updateFc(CarrierEthernetForwardingConstruct fc);
+
+ /**
+ * Removes all resources associated with a specific FC.
+ *
+ * @param fcId the FC id
+ * @return the FC that was removed or null if removal failed
+ */
+ CarrierEthernetForwardingConstruct removeFc(EvcConnId fcId);
+
+ /**
+ * Removes all resources associated with the application.
+ *
+ * This will be called either from the deactivate method or as a response to a CLI command.
+ */
+ void removeAllFcs();
+
+ /**
+ * Get the map containing all global UNIs.
+ *
+ * @return the global UNI map
+ */
+ Map<String, CarrierEthernetUni> getUniMap();
+
+ /**
+ * Adds a potential UNI to the global UNI map if they are not already there.
+ *
+ * @param uni the potential UNI to add to global UNI map
+ * @return the UNI that was added or null if UNI existed already
+ */
+ CarrierEthernetUni addGlobalUni(CarrierEthernetUni uni);
+
+ /**
+ * Remove an UNI from the set of global UNIs.
+ *
+ * @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)
+ */
+ CarrierEthernetUni removeGlobalUni(String uniId);
+
+ // TODO: Add removeAllGlobalUnis method (or command only?)
+
+ /**
+ * Creates a new UNI associated with the provided connect point.
+ *
+ * Conditions for validating an UNI:
+ * - ConnectPoint deviceId and Port are valid
+ * - Port is enabled
+ *
+ * @param cp the connect point to be associated with the generated UNI
+ * @return a new validated UNI or null if the validation failed
+ */
+ CarrierEthernetUni generateUni(ConnectPoint cp);
+
+ /**
+ * Returns all potential UNIs from the topology.
+ *
+ * @param excludeAdded indicates that UNIs already added in the UNI map should not be in the returned set
+ * @param includeRemoved indicates that UNIs explicitly removed from the UNI map should be in the returned set
+ * @return set of all potential UNIs in the topology
+ */
+ Set<CarrierEthernetUni> getUnisFromTopo(boolean excludeAdded, boolean includeRemoved);
+
+ /**
+ * Get the map containing all global LTPs.
+ *
+ * @return the global LTP map
+ */
+ Map<String, CarrierEthernetLogicalTerminationPoint> ltpMap();
+
+ /**
+ * 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
+ */
+ CarrierEthernetLogicalTerminationPoint addGlobalLtp(CarrierEthernetLogicalTerminationPoint ltp);
+
+ /**
+ * 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)
+ */
+ CarrierEthernetLogicalTerminationPoint removeGlobalLtp(String ltpId);
+
+ // TODO: Add removeAllGlobalLtps method (or command only?)
+
+ /**
+ * Creates a new LTP of the provided type and associated with the provided connect point.
+ *
+ * Conditions for validating an LTP:
+ * - ConnectPoint deviceId and Port are valid
+ * - Port is enabled
+ *
+ * @param cp the connect point to be associated with the generated LTP
+ * @param ltpType the type of the LTP to be generated (UNI/INNI/ENNI)
+ * @return a new validated LTP or null if the validation failed
+ */
+ CarrierEthernetLogicalTerminationPoint generateLtp(ConnectPoint cp, Type ltpType);
+
+ /**
+ * Returns all potential LTPs from the topology.
+ *
+ * @param excludeAdded indicates that LTPs already added in the LTP map should not be in the returned set
+ * @param includeRemoved indicates that LTPs explicitly removed from the LTP map should be in the returned set
+ * @return set of all potential LTPs in the topology
+ */
+ Set<CarrierEthernetLogicalTerminationPoint> getLtpsFromTopo(boolean excludeAdded, boolean includeRemoved);
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/channel/ControlChannelListenerService.java b/ce-api/src/main/java/org/opencord/ce/api/services/channel/ControlChannelListenerService.java
new file mode 100644
index 0000000..f85e13d
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/channel/ControlChannelListenerService.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services.channel;
+
+import org.opencord.ce.api.services.MetroNetworkVirtualNodeService;
+
+import java.util.Set;
+
+/**
+ * Service used by the southbound components of the global ONOS to listen for EVCs setup.
+ */
+public interface ControlChannelListenerService {
+
+ void addListener(MetroNetworkVirtualNodeService listener);
+
+ void removeListener(MetroNetworkVirtualNodeService listener);
+
+ Set<MetroNetworkVirtualNodeService> listeners();
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/channel/RequestCallback.java b/ce-api/src/main/java/org/opencord/ce/api/services/channel/RequestCallback.java
new file mode 100644
index 0000000..9d9b0e2
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/channel/RequestCallback.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services.channel;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * HTTP request callback.
+ */
+public interface RequestCallback {
+
+ // called upon a successful network task
+ default void onSuccess(Response response){}
+
+ // called upon a failured network task
+ default void onError(Response response){}
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/channel/Symbols.java b/ce-api/src/main/java/org/opencord/ce/api/services/channel/Symbols.java
new file mode 100644
index 0000000..ea28756
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/channel/Symbols.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services.channel;
+
+
+/**
+ * HTTP resource paths.
+ */
+public final class Symbols {
+
+ private Symbols() {
+ }
+
+ public static final String POST = "post";
+ public static final String GET = "get";
+ public static final String DELETE = "delete";
+ public static final String HTTP = "http";
+ public static final String DOUBLESLASH = "//";
+ public static final String L_BRACKET = "{";
+ public static final String R_BRACKET = "}";
+ public static final String QUOTES = "\"";
+ public static final String COLON = ":";
+ public static final String OK = "ok";
+ public static final String MASTER_IP = "masterIp";
+ public static final String RESULT = "result";
+ public static final String NO_ENDPOINT_AVAILABLE = "unavailable";
+
+ public static final String MASTER_API_NO_IP_BODY = L_BRACKET
+ + QUOTES + RESULT + QUOTES + COLON + QUOTES + NO_ENDPOINT_AVAILABLE + QUOTES
+ + R_BRACKET;
+
+ public static final String BASE_URL = "/ecord";
+
+ public static final String MASTER = "/master";
+
+ public static final String FC = "fc";
+ public static final String SRC_NI = "srcNi";
+ public static final String DST_NI_LIST = "dstNiList";
+ public static final String UNI = "uni";
+
+ public static final String FC_ID = "fcId";
+ // ======== Forwarding Construct data ====== //
+ public static final String FC_TAG = "fcTag";
+ public static final String FC_INGRESS_CP = "fcIngressCp";
+ public static final String FC_TYPE = "fcType";
+ public static final String INGRESS_NI_TYPE = "ingressNiType";
+ public static final String INGRESS_FC_TAG = "ingressFcTag";
+ public static final String CUSTOMER_TAG = "customerTag";
+ public static final String FC_EGRESS_LST = "fcEgressList";
+ public static final String FC_EGRESS_CP = "fcEgressCp";
+ public static final String FC_EGRESS_TYPE = "fcEgressType";
+
+ // ======== Bandwidth profile data ====== //
+ public static final String BW_PROFILE = "bwProfile";
+ public static final String CIR = "cir";
+ public static final String EIR = "eir";
+ public static final String CBS = "cbs";
+ public static final String EBS = "ebs";
+ public static final String UNI_CP = "uniCp";
+
+
+ // ===== Device and Port annotations ==== //
+ public static final String DEVICE_ID = "deviceId";
+ public static final String MEF_PORT_TYPE = "mefPortType";
+
+
+}
+
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/channel/package-info.java b/ce-api/src/main/java/org/opencord/ce/api/services/channel/package-info.java
new file mode 100644
index 0000000..d66fa7e
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/channel/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Communication channel between global orchestrator and local sites.
+ */
+package org.opencord.ce.api.services.channel;
\ No newline at end of file
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/package-info.java b/ce-api/src/main/java/org/opencord/ce/api/services/package-info.java
new file mode 100644
index 0000000..5f6a3a2
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service APIs for Carrier Ethernet.
+ */
+package org.opencord.ce.api.services;
\ No newline at end of file
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DefaultDomainVirtualDevice.java b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DefaultDomainVirtualDevice.java
new file mode 100644
index 0000000..122c309
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DefaultDomainVirtualDevice.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services.virtualprovider;
+
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.domain.DomainId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of a domain device.
+ */
+public class DefaultDomainVirtualDevice implements DomainVirtualDevice {
+ private final DeviceId deviceId;
+ private final DomainId domainId;
+
+ public DefaultDomainVirtualDevice(DeviceId deviceId, DomainId domainId) {
+ this.deviceId = deviceId;
+ this.domainId = domainId;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public DomainId domainId() {
+ return domainId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), deviceId, domainId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultDomainVirtualDevice) {
+ final DefaultDomainVirtualDevice other = (DefaultDomainVirtualDevice) obj;
+ return Objects.equals(this.deviceId, other.deviceId()) &&
+ Objects.equals(this.domainId, other.domainId());
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("deviceId", deviceId.toString())
+ .add("domainId", domainId)
+ .toString();
+ }
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DomainElement.java b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DomainElement.java
new file mode 100644
index 0000000..94e8367
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DomainElement.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services.virtualprovider;
+
+import org.onosproject.net.domain.DomainId;
+
+/**
+ * Interface implemented by the domain topology elements.
+ */
+public interface DomainElement {
+
+ /**
+ * Returns the domain id the element belongs to.
+ * @return domain id
+ */
+ DomainId domainId();
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DomainVirtualDevice.java b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DomainVirtualDevice.java
new file mode 100644
index 0000000..acc1d06
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/DomainVirtualDevice.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services.virtualprovider;
+
+import org.onosproject.net.DeviceId;
+
+/**
+ * Domain virtual device.
+ * Represents an aggregated set of ports associated to an underlying domain.
+ *
+ */
+public interface DomainVirtualDevice extends DomainElement {
+
+ /**
+ * Returns the device ID.
+ * @return device identifier
+ */
+ DeviceId deviceId();
+
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/EcordDeviceProviderService.java b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/EcordDeviceProviderService.java
new file mode 100644
index 0000000..1b099ed
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/EcordDeviceProviderService.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services.virtualprovider;
+
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.domain.DomainId;
+
+import java.util.List;
+
+/**
+ * Service used by the southbound communication channel to notify virtual device presence.
+ */
+public interface EcordDeviceProviderService {
+
+ /**
+ * Signals the domain provider to connect a device of another domain.
+ *
+ * @param domainVirtualDevice device object
+ */
+ void connectRemoteDevice(DomainVirtualDevice domainVirtualDevice);
+
+ /**
+ * Adds or updates ports on a remote domain.
+ *
+ * @param domainId domain ID
+ * @param deviceId device ID
+ * @param ports list of port descriptions
+ */
+ void addOrUpdateRemotePorts(DomainId domainId, DeviceId deviceId, List<PortDescription> ports);
+
+ /**
+ * Signals the domain provider that a specific domain has added a new port to a device.
+ *
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ * @param port port
+ */
+ void addRemotePort(DomainId domainId, DeviceId deviceId, Port port);
+
+ /**
+ * Signals a remote port update.
+ *
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ * @param port port description
+ */
+ void updateRemotePortState(DomainId domainId, DeviceId deviceId, Port port);
+
+ /**
+ * Signals the disconnection of a remote domain device.
+ *
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ */
+ void disconnectRemoteDevice(DomainId domainId, DeviceId deviceId);
+
+ /**
+ * Signals the deletion of a remote domain device port.
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ * @param portNumber port identifier
+ */
+ void removeRemotePort(DomainId domainId, DeviceId deviceId, PortNumber portNumber);
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/LinkId.java b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/LinkId.java
new file mode 100644
index 0000000..cd51403
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/LinkId.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.ce.api.services.virtualprovider;
+
+import org.onlab.util.Identifier;
+
+/**
+ * Domain link identifier class.
+ */
+public class LinkId extends Identifier<String> {
+
+ public LinkId(String identifier) {
+ super(identifier);
+ }
+
+ public static LinkId linkId(String id) {
+
+ return new LinkId(id);
+ }
+}
diff --git a/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/package-info.java b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/package-info.java
new file mode 100644
index 0000000..37711e3
--- /dev/null
+++ b/ce-api/src/main/java/org/opencord/ce/api/services/virtualprovider/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * APIs for virtual device providers.
+ */
+package org.opencord.ce.api.services.virtualprovider;
\ No newline at end of file