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