Merge branch 'master' of https://gerrit.opencord.org/fpcagent
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bff2d76
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.iml
diff --git a/apps/fpcagent/BUCK b/apps/fpcagent/BUCK
new file mode 100644
index 0000000..4396a00
--- /dev/null
+++ b/apps/fpcagent/BUCK
@@ -0,0 +1,73 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:JACKSON',
+    '//lib:KRYO',
+    '//models/fpcagent:onos-models-fpcagent',
+    '//models/common:onos-models-common',
+    '//lib:onos-yang-model',
+    '//apps/config:onos-apps-config',
+    '//core/api:onos-api',
+    '//lib:javax.ws.rs-api',
+    '//utils/rest:onlab-rest',
+    '//core/store/serializers:onos-core-serializers',
+    '//apps/restconf/utils:onos-apps-restconf-utils',
+    ':zeromq',
+    ':json',
+]
+
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+    '//lib:TEST_REST',
+    '//utils/osgi:onlab-osgi-tests',
+]
+
+BUNDLES = [
+    '//apps/fpcagent:onos-apps-fpcagent',
+]
+
+EXCLUDED_BUNDLES = [
+    ':zeromq',
+    ':json',
+]
+
+APPS = [
+    'org.onosproject.models.fpcagent',
+    'org.onosproject.yang',
+    'org.onosproject.yang-gui',
+    'org.onosproject.config',
+    'org.onosproject.restconf',
+    'org.onosproject.protocols.restconfserver',
+]
+
+osgi_jar_with_tests(
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+)
+
+onos_app(
+    app_name = 'org.onosproject.fpcagent',
+    title = 'YANG FPC Agent',
+    category = 'Traffic Steering',
+    url = 'http://onosproject.org',
+    description = 'FPC Agent YANG Application',
+    required_apps = APPS,
+    excluded_bundles = EXCLUDED_BUNDLES,
+)
+
+remote_jar (
+  name = 'json',
+  out = 'json-20090211.jar',
+  url = 'mvn:org.json:json:jar:20090211',
+  sha1 = 'c183aa3a2a6250293808bba12262c8920ce5a51c',
+  maven_coords = 'org.json:json:jar:NON-OSGI:20090211',
+  visibility = [ 'PUBLIC' ],
+)
+
+remote_jar (
+  name = 'zeromq',
+  out = 'jeromq-0.3.5.jar',
+  url = 'mvn:org.zeromq:jeromq:jar:0.3.5',
+  sha1 = '39a79082570d114bb5433762e836e4dd9c38b03d',
+  maven_coords = 'org.zeromq:jeromq:0.3.5',
+  visibility = [ 'PUBLIC' ],
+)
diff --git a/apps/fpcagent/fpcagent.json b/apps/fpcagent/fpcagent.json
new file mode 100644
index 0000000..a54290a
--- /dev/null
+++ b/apps/fpcagent/fpcagent.json
@@ -0,0 +1,16 @@
+{
+  "apps": {
+    "org.onosproject.fpcagent": {
+      "fpcagent": {
+        "dpn-subscriber-uri": "tcp://*:5560",
+        "dpn-publisher-uri": "tcp://*:5559",
+        "dpn-client-threads": 5,
+        "node-id": "node0",
+        "network-id": "network1",
+        "zmq-broadcast-all": "1",
+        "zmq-broadcast-controllers": "2",
+        "zmq-broadcast-dpns": "3"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java
new file mode 100644
index 0000000..b9cbb9f
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java
@@ -0,0 +1,25 @@
+package org.onosproject.fpcagent;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+import org.onosproject.net.config.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+public class FpcConfig extends Config<ApplicationId> {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    public Optional<ConfigHelper> getConfig() {
+        try {
+            return Optional.of(mapper.treeToValue(object, ConfigHelper.class));
+        } catch (JsonProcessingException e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+        return Optional.empty();
+    }
+}
+
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
new file mode 100644
index 0000000..27e6b8b
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
@@ -0,0 +1,285 @@
+/*
+ * 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.onosproject.fpcagent;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.felix.scr.annotations.*;
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+import org.onosproject.fpcagent.workers.ZMQSBPublisherManager;
+import org.onosproject.fpcagent.workers.ZMQSBSubscriberManager;
+import org.onosproject.net.config.*;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.IetfDmmFpcagentService;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ErrorTypeId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.Result;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.DefaultConfigureInput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.DefaultConfigureOutput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configuredpn.DefaultConfigureDpnInput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configuredpn.DefaultConfigureDpnOutput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.CreateOrUpdate;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.DeleteOrQuery;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.result.ResultEnum;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbody.resulttype.DefaultErr;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbodydpn.resulttype.DefaultEmptyCase;
+import org.onosproject.yang.model.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+import static org.onosproject.fpcagent.FpcUtil.*;
+
+/**
+ * Fpc Manager.
+ */
+@Component(immediate = true)
+@Service
+public class FpcManager implements IetfDmmFpcagentService, FpcService {
+    private static final Logger log = LoggerFactory.getLogger(FpcManager.class);
+
+    private static final Class<FpcConfig> CONFIG_CLASS = FpcConfig.class;
+    private final InternalNetworkConfigListener configListener =
+            new InternalNetworkConfigListener();
+
+    /* Services */
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private TenantService tenantService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private ModelConverter modelConverter;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private DynamicConfigService dynamicConfigService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private RpcRegistry rpcRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private NetworkConfigRegistry registry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private NetworkConfigService configService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private CoreService coreService;
+
+    /* Variables */
+    private FpcConfig fpcConfig;
+
+    /* Config */
+    private ConfigFactory<ApplicationId, FpcConfig> fpcConfigConfigFactory =
+            new ConfigFactory<ApplicationId, FpcConfig>(
+                    SubjectFactories.APP_SUBJECT_FACTORY, FpcConfig.class, "fpcagent") {
+                @Override
+                public FpcConfig createConfig() {
+                    return new FpcConfig();
+                }
+            };
+
+    @Activate
+    protected void activate() {
+        coreService.registerApplication(FPC_APP_ID);
+        configService.addListener(configListener);
+        registry.registerConfigFactory(fpcConfigConfigFactory);
+
+        rpcRegistry.registerRpcService(this);
+
+        log.info("FPC Agent Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        configService.removeListener(configListener);
+        registry.unregisterConfigFactory(fpcConfigConfigFactory);
+
+        // TODO check if null before closing
+        ZMQSBSubscriberManager.getInstance().close();
+        ZMQSBPublisherManager.getInstance().close();
+
+        rpcRegistry.unregisterRpcService(this);
+
+        log.info("FPC Agent Stopped");
+    }
+
+    private void init() {
+        fpcConfig.getConfig().ifPresent(
+                helper -> {
+                    ZMQSBSubscriberManager.createInstance(
+                            helper.dpnSubscriberUri(),
+                            helper.zmqBroadcastAll(),
+                            helper.zmqBroadcastControllers(),
+                            helper.zmqBroadcastDpns(),
+                            helper.nodeId(),
+                            helper.networkId()
+                    );
+
+                    ZMQSBPublisherManager.createInstance(
+                            helper.dpnPublisherUri(),
+                            helper.dpnClientThreads()
+                    );
+
+                    ZMQSBPublisherManager.getInstance().open();
+                    ZMQSBSubscriberManager.getInstance().open();
+                }
+        );
+    }
+
+    @Override
+    public Optional<ConfigHelper> getConfig() {
+        return fpcConfig != null ? fpcConfig.getConfig() : Optional.empty();
+    }
+
+    @Override
+    public RpcOutput configureDpn(RpcInput rpcInput) {
+        DefaultConfigureDpnOutput output = new DefaultConfigureDpnOutput();
+        output.result(Result.of(ResultEnum.OK));
+        output.resultType(new DefaultEmptyCase());
+
+        try {
+            tenantService.getModelObjects(rpcInput.data(), configureDpnResourceId).forEach(
+                    modelObject -> {
+                        DefaultConfigureDpnInput input = (DefaultConfigureDpnInput) modelObject;
+                        String dpnId = input.inputDpnId().fpcIdentity().union().string();
+                        switch (input.operation().enumeration()) {
+                            case ADD:
+                                log.info("Adding DPN {}", dpnId);
+                                // TODO
+                                break;
+                            case REMOVE:
+                                log.info("Removing DPN {}", dpnId);
+                                // TODO
+                                break;
+                        }
+                    });
+        } catch (Exception e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+
+        ResourceData dataNode = modelConverter.createDataNode(
+                DefaultModelObjectData.builder().addModelObject(output).build()
+        );
+        return new RpcOutput(RpcOutput.Status.RPC_SUCCESS, dataNode.dataNodes().get(0));
+    }
+
+    @Override
+    public RpcOutput configure(RpcInput rpcInput) {
+        DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
+
+        try {
+            for (ModelObject modelObject : tenantService.getModelObjects(rpcInput.data(), configureResourceId)) {
+                DefaultConfigureInput input = (DefaultConfigureInput) modelObject;
+                switch (input.opType()) {
+                    case CREATE:
+                        configureOutput = tenantService.configureCreate(
+                                (CreateOrUpdate) input.opBody(),
+                                input.clientId(),
+                                input.opId()
+                        );
+                        break;
+                    case UPDATE:
+                        configureOutput = tenantService.configureUpdate(
+                                (CreateOrUpdate) input.opBody(),
+                                input.clientId(),
+                                input.opId()
+                        );
+                        break;
+                    case QUERY:
+                        break;
+                    case DELETE:
+                        configureOutput = tenantService.configureDelete(
+                                (DeleteOrQuery) input.opBody(),
+                                input.clientId(),
+                                input.opId()
+                        );
+                        break;
+                }
+                configureOutput.opId(input.opId());
+            }
+            // TODO fix DELETE to update the NODE correctly.
+            tenantService.getTenants().ifPresent(tenants -> tenantService.updateNode(tenants));
+        } catch (Exception e) {
+            DefaultErr defaultErr = new DefaultErr();
+            defaultErr.errorInfo(ExceptionUtils.getFullStackTrace(e));
+            defaultErr.errorTypeId(ErrorTypeId.of(0));
+            configureOutput.resultType(defaultErr);
+            configureOutput.result(Result.of(ResultEnum.ERR));
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+
+        ResourceData dataNode = modelConverter.createDataNode(
+                DefaultModelObjectData.builder()
+                        .addModelObject(configureOutput)
+                        .build()
+        );
+        return new RpcOutput(RpcOutput.Status.RPC_SUCCESS, dataNode.dataNodes().get(0));
+    }
+
+    @Override
+    public RpcOutput configureBundles(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput eventRegister(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput eventDeregister(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput probe(RpcInput rpcInput) {
+        return null;
+    }
+
+    private class InternalNetworkConfigListener implements NetworkConfigListener {
+
+        @Override
+        public void event(NetworkConfigEvent event) {
+            switch (event.type()) {
+                case CONFIG_REGISTERED:
+                case CONFIG_UNREGISTERED: {
+                    break;
+                }
+                case CONFIG_REMOVED: {
+                    if (event.configClass() == CONFIG_CLASS) {
+                        fpcConfig = null;
+                    }
+                    break;
+                }
+                case CONFIG_UPDATED:
+                case CONFIG_ADDED: {
+                    if (event.configClass() == CONFIG_CLASS) {
+                        event.config().ifPresent(config -> {
+                            fpcConfig = (FpcConfig) config;
+                            init();
+                        });
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+        }
+
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java
new file mode 100644
index 0000000..5e4e152
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java
@@ -0,0 +1,10 @@
+package org.onosproject.fpcagent;
+
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+
+import java.util.Optional;
+
+public interface FpcService {
+
+    Optional<ConfigHelper> getConfig();
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcUtil.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcUtil.java
new file mode 100644
index 0000000..6f1ebf1
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcUtil.java
@@ -0,0 +1,246 @@
+/*
+ * 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.onosproject.fpcagent;
+
+import com.google.common.collect.Maps;
+import org.onosproject.restconf.utils.RestconfUtils;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.OpIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DefaultDownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpcidentity.FpcIdentityUnion;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.DefaultResourceData;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.AbstractMap;
+import java.util.Arrays;
+import java.util.Map;
+
+import static org.onosproject.fpcagent.helpers.Converter.fromIntToLong;
+import static org.onosproject.fpcagent.helpers.Converter.toBigInt;
+
+/**
+ * Helper class which stores all the static variables.
+ */
+public class FpcUtil {
+    protected static final Logger log = LoggerFactory.getLogger(FpcUtil.class);
+
+    public static final int MAX_EVENTS = 1000;
+    public static final int MAX_BATCH_MS = 5000;
+    public static final int MAX_IDLE_MS = 1000;
+    public static final String TIMER = "dynamic-config-fpcagent-timer";
+    public static final String UNKNOWN_EVENT = "FPC Agent listener: unknown event: {}";
+    public static final String EVENT_NULL = "Event cannot be null";
+    public static final String FPC_APP_ID = "org.onosproject.fpcagent";
+
+    private static final Map<String, FpcDpnId> uplinkDpnMap = Maps.newConcurrentMap();
+    private static final Map<String, Short> nodeToTopicMap = Maps.newConcurrentMap();
+
+    private static byte DPN_HELLO = 0b0000_0001;
+    private static byte DPN_BYE = 0b0000_0010;
+    private static byte DOWNLINK_DATA_NOTIFICATION = 0b0000_0101;
+    private static byte DPN_STATUS_INDICATION = 0b0000_1100;
+    private static byte DPN_OVERLOAD_INDICATION = 0b0000_0101;
+    private static byte DPN_REPLY = 0b0000_0100;
+    private static String DOWNLINK_DATA_NOTIFICATION_STRING = "Downlink-Data-Notification";
+
+    // Resource ID for Configure DPN RPC command
+    public static ResourceId configureDpnResourceId;
+    // Resource ID for Configure RPC command
+    public static ResourceId configureResourceId;
+    // Resource ID for tenants data
+    public static ResourceId tenantsResourceId;
+    public static ResourceId registerClientResourceId;
+    public static ResourceId deregisterClientResourceId;
+
+    static {
+        try {
+            configureDpnResourceId = RestconfUtils.convertUriToRid(
+                    new URI("/onos/restconf/operations/ietf-dmm-fpcagent:configure-dpn")
+            );
+            configureResourceId = RestconfUtils.convertUriToRid(
+                    new URI("/onos/restconf/operations/ietf-dmm-fpcagent:configure")
+            );
+            tenantsResourceId = RestconfUtils.convertUriToRid(
+                    new URI("/onos/restconf/data/ietf-dmm-fpcagent:tenants")
+            );
+            registerClientResourceId = RestconfUtils.convertUriToRid(
+                    new URI("/onos/restconf/data/fpc:register-client")
+            );
+            deregisterClientResourceId = RestconfUtils.convertUriToRid(
+                    new URI("/onos/restconf/data/fpc:deregister-client")
+            );
+        } catch (URISyntaxException ignored) {
+        }
+    }
+
+    /**
+     * Returns the resource data from the data node and the resource id.
+     *
+     * @param dataNode data node
+     * @param resId    resource id
+     * @return resource data
+     */
+    static ResourceData getResourceData(DataNode dataNode, ResourceId resId) {
+        if (resId != null) {
+            return DefaultResourceData.builder()
+                    .addDataNode(dataNode)
+                    .resourceId(resId)
+                    .build();
+        } else {
+            return DefaultResourceData.builder()
+                    .addDataNode(dataNode)
+                    .build();
+        }
+    }
+
+    /**
+     * Ensures the session id is an unsigned 64 bit integer
+     *
+     * @param sessionId - session id received from the DPN
+     * @return unsigned session id
+     */
+    private static BigInteger checkSessionId(BigInteger sessionId) {
+        if (sessionId.compareTo(BigInteger.ZERO) < 0) {
+            sessionId = sessionId.add(BigInteger.ONE.shiftLeft(64));
+        }
+        return sessionId;
+    }
+
+    /**
+     * Decodes a DownlinkDataNotification
+     *
+     * @param buf - message buffer
+     * @param key - Concatenation of node id + / + network id
+     * @return DownlinkDataNotification or null if it could not be successfully decoded
+     */
+    private static DownlinkDataNotification processDDN(byte[] buf, String key) {
+        DownlinkDataNotification ddnB = new DefaultDownlinkDataNotification();
+        ddnB.sessionId(checkSessionId(toBigInt(buf, 2)));
+        ddnB.notificationMessageType(DOWNLINK_DATA_NOTIFICATION_STRING);
+        ddnB.clientId(ClientIdentifier.of(FpcIdentity.of(FpcIdentityUnion.of(fromIntToLong(buf, 10)))));
+        ddnB.opId(OpIdentifier.of(BigInteger.valueOf(fromIntToLong(buf, 14))));
+        ddnB.notificationDpnId(uplinkDpnMap.get(key));
+        return ddnB;
+    }
+
+    /**
+     * Decodes a DPN message.
+     *
+     * @param buf - message buffer
+     * @return - A pair with the DPN Id and decoded Object
+     */
+    public static Map.Entry<FpcDpnId, Object> decode(byte[] buf) {
+        if (buf[1] == DPN_REPLY) {
+            return null;
+        } else if (buf[1] == DOWNLINK_DATA_NOTIFICATION) {
+            short nodeIdLen = buf[18];
+            short networkIdLen = buf[19 + nodeIdLen];
+            String key = new String(Arrays.copyOfRange(buf, 19, 19 + nodeIdLen)) + "/" + new String(Arrays.copyOfRange(buf, 20 + nodeIdLen, 20 + nodeIdLen + networkIdLen));
+            return uplinkDpnMap.get(key) == null ? null : new AbstractMap.SimpleEntry<>(uplinkDpnMap.get(key), processDDN(buf, key));
+        } else if (buf[1] == DPN_STATUS_INDICATION) {
+            DPNStatusIndication.Status status = null;
+
+            short nodeIdLen = buf[8];
+            short networkIdLen = buf[9 + nodeIdLen];
+            String key = new String(Arrays.copyOfRange(buf, 9, 9 + nodeIdLen)) + "/" + new String(Arrays.copyOfRange(buf, 10 + nodeIdLen, 10 + nodeIdLen + networkIdLen));
+            if (buf[3] == DPN_OVERLOAD_INDICATION) {
+                status = DPNStatusIndication.Status.OVERLOAD_INDICATION;
+            } else if (buf[3] == DPN_HELLO) {
+                status = DPNStatusIndication.Status.HELLO;
+                log.info("Hello {} on topic {}", key, buf[2]);
+                nodeToTopicMap.put(key, (short) buf[2]);
+            } else if (buf[3] == DPN_BYE) {
+                status = DPNStatusIndication.Status.BYE;
+                log.info("Bye {}", key);
+                nodeToTopicMap.remove(key);
+            }
+            return new AbstractMap.SimpleEntry<>(uplinkDpnMap.get(key), new DPNStatusIndication(status, key));
+        }
+        return null;
+    }
+
+    /**
+     * Gets the mapping for node id / network id to ZMQ Topic
+     *
+     * @param Key - Concatenation of node id + / + network id
+     * @return - ZMQ Topic
+     */
+    public static Short getTopicFromNode(String Key) {
+        return nodeToTopicMap.get(Key);
+    }
+
+    /**
+     * Provides basic status changes,
+     */
+    public static class DPNStatusIndication {
+        private final Status status;
+        private final String key; //nodeId +"/"+ networkId
+        /**
+         * Node Reference of the DPN
+         */
+        public Short nodeRef;
+
+        /**
+         * Constructor providing the DPN and its associated Status.
+         *
+         * @param status - DPN Status
+         * @param key    - Combination of node id and network id
+         */
+        public DPNStatusIndication(Status status,
+                                   String key) {
+            this.status = status;
+            this.key = key;
+        }
+
+        /**
+         * Provides DPN Status
+         *
+         * @return Status associated to the DPN.
+         */
+        public Status getStatus() {
+            return status;
+        }
+
+        /**
+         * Provides the DPN key - nodeId +"/"+ networkId
+         *
+         * @return FpcDpnId
+         */
+        public String getKey() {
+            return this.key;
+        }
+
+        /**
+         * Basic DPN Status
+         */
+        public enum Status {
+            HELLO,
+            BYE,
+            OVERLOAD_INDICATION
+        }
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
new file mode 100644
index 0000000..8b72165
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
@@ -0,0 +1,683 @@
+package org.onosproject.fpcagent;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.felix.scr.annotations.*;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.util.AbstractAccumulator;
+import org.onlab.util.Accumulator;
+import org.onosproject.config.DynamicConfigEvent;
+import org.onosproject.config.DynamicConfigListener;
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.config.Filter;
+import org.onosproject.fpcagent.helpers.DpnCommunicationService;
+import org.onosproject.fpcagent.helpers.DpnNgicCommunicator;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.IetfDmmFpcagentOpParam;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.*;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.DefaultConfigureOutput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.instructions.instructions.instrtype.Instr3GppMob;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.CreateOrUpdate;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.DeleteOrQuery;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.payload.Contexts;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.result.ResultEnum;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbody.resulttype.DefaultCommonSuccess;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbody.resulttype.DefaultDeleteSuccess;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbody.resulttype.DefaultErr;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.DefaultTenant;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.Tenant;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.DefaultFpcMobility;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.DefaultFpcPolicy;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.DefaultFpcTopology;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Dpns;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.mobilityinfo.mobprofileparameters.ThreegppTunnel;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.targetsvalue.Targets;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.ietfdmmthreegpp.threegppinstr.Bits;
+import org.onosproject.yang.model.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.fpcagent.FpcUtil.*;
+import static org.onosproject.fpcagent.helpers.Converter.convertContext;
+import static org.onosproject.fpcagent.helpers.Converter.getFpcIdentity;
+
+@Component(immediate = true)
+@Service
+public class TenantManager implements TenantService {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private final IetfDmmFpcagentOpParam fpcAgentData = new IetfDmmFpcagentOpParam();
+
+    private final Map<ClientIdentifier, Tenant> clientIdMap = Maps.newHashMap();
+
+    private final InternalConfigListener listener = new InternalConfigListener();
+
+    private final Accumulator<DynamicConfigEvent> accumulator = new InternalEventAccumulator();
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private ModelConverter modelConverter;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private DynamicConfigService dynamicConfigService;
+
+    private DpnCommunicationService dpnCommunicationService;
+
+    @Activate
+    protected void activate() {
+        dpnCommunicationService = new DpnNgicCommunicator();
+
+        dynamicConfigService.addListener(listener);
+
+        // Create the Default Tenant on activate
+        DefaultTenants tenants = new DefaultTenants();
+
+        DefaultTenant tenant = new DefaultTenant();
+        tenant.tenantId(getFpcIdentity.apply("default"));
+
+        tenant.fpcTopology(new DefaultFpcTopology());
+
+        tenant.fpcPolicy(new DefaultFpcPolicy());
+
+        tenant.fpcMobility(new DefaultFpcMobility());
+
+        tenants.addToTenant(tenant);
+
+        DefaultFpcAgentInfo fpcAgentInfo = new DefaultFpcAgentInfo();
+
+        fpcAgentData.tenants(tenants);
+        fpcAgentData.fpcAgentInfo(fpcAgentInfo);
+
+        createNode(tenants);
+        createNode(fpcAgentInfo);
+
+        log.info("Tenant Service Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        dynamicConfigService.removeListener(listener);
+        log.info("Tenant Service Stopped");
+    }
+
+    @Override
+    public Optional<Tenant> getDefaultTenant() {
+        return fpcAgentData.tenants().tenant().stream()
+                .filter(tenant -> tenant.tenantId().equals(getFpcIdentity.apply("default")))
+                .findFirst();
+    }
+
+    @Override
+    public Optional<DefaultTenants> getTenants() {
+        if (fpcAgentData.tenants() instanceof DefaultTenants) {
+            return Optional.ofNullable((DefaultTenants) fpcAgentData.tenants());
+        }
+        return Optional.empty();
+    }
+
+    public Optional<Tenant> getTenant(FpcIdentity tenantId) {
+        return fpcAgentData.tenants().tenant().stream()
+                .filter(tenant -> tenant.tenantId().equals(tenantId))
+                .findFirst();
+    }
+
+    public Optional<Tenant> getTenant(ClientIdentifier clientId) {
+        return Optional.ofNullable(clientIdMap.get(clientId));
+    }
+
+    public Optional<Tenant> registerClient(ClientIdentifier clientId, FpcIdentity tenantId) {
+        return getTenant(tenantId).map(tenant -> clientIdMap.put(clientId, tenant));
+    }
+
+    public Optional<Tenant> deregisterClient(ClientIdentifier clientId) {
+        return Optional.ofNullable(clientIdMap.remove(clientId));
+    }
+
+    private ResourceData getResourceData(DataNode dataNode, ResourceId resId) {
+        if (resId != null) {
+            return DefaultResourceData.builder()
+                    .addDataNode(dataNode)
+                    .resourceId(resId)
+                    .build();
+        } else {
+            return DefaultResourceData.builder()
+                    .addDataNode(dataNode)
+                    .build();
+        }
+    }
+
+    public List<ModelObject> getModelObjects(DataNode dataNode, ResourceId resourceId) {
+        ResourceData data = getResourceData(dataNode, resourceId);
+        ModelObjectData modelData = modelConverter.createModel(data);
+        return modelData.modelObjects();
+    }
+
+    public void createNode(InnerModelObject innerModelObject) {
+        ResourceData dataNode = modelConverter.createDataNode(
+                DefaultModelObjectData.builder()
+                        .addModelObject(innerModelObject)
+                        .build()
+        );
+        dataNode.dataNodes().forEach(
+                node -> dynamicConfigService.createNode(dataNode.resourceId(), node)
+        );
+    }
+
+    public void updateNode(InnerModelObject innerModelObject) {
+        ResourceData dataNode = modelConverter.createDataNode(
+                DefaultModelObjectData.builder()
+                        .addModelObject(innerModelObject)
+                        .build()
+        );
+        dataNode.dataNodes().forEach(
+                node -> dynamicConfigService.updateNode(dataNode.resourceId(), node)
+        );
+    }
+
+    public DefaultConfigureOutput configureCreate(
+            CreateOrUpdate create,
+            ClientIdentifier clientId,
+            OpIdentifier operationId
+    ) {
+        DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
+        Collection<Callable<Object>> tasks = new ArrayList<>();
+        DefaultCommonSuccess defaultCommonSuccess = new DefaultCommonSuccess();
+        try {
+            for (Contexts context : create.contexts()) {
+                defaultCommonSuccess.addToContexts(context);
+
+                if (getDefaultTenant().map(
+                        tenant -> tenant.fpcMobility().contexts() != null && tenant.fpcMobility()
+                                .contexts()
+                                .stream()
+                                .anyMatch(contexts -> contexts.contextId().equals(context.contextId()))
+                ).orElse(false)) {
+                    throw new IllegalStateException("Context already exists.");
+                }
+
+                for (Dpns dpn : context.dpns()) {
+                    if (getDefaultTenant().map(
+                            tenant -> tenant.fpcTopology().dpns() == null ||
+                                    tenant.fpcTopology().dpns().stream()
+                                            .noneMatch(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+                    ).orElse(false)) {
+                        throw new IllegalStateException("DPN ID is not registered to the topology.");
+                    }
+
+                    if (context.instructions().instrType() instanceof Instr3GppMob) {
+                        Instr3GppMob instr3GppMob = (Instr3GppMob) context.instructions().instrType();
+                        String commands = Bits.toString(instr3GppMob.instr3GppMob().bits());
+
+                        Ip4Address ulLocalAddress = Ip4Address.valueOf(context.ul().tunnelLocalAddress().toString()),
+                                dlRemoteAddress = Ip4Address.valueOf(context.dl().tunnelRemoteAddress().toString());
+
+                        long s1u_sgw_gtpu_teid, s1u_enb_gtpu_teid,
+                                cId = clientId.fpcIdentity().union().int64(),
+                                contextId = context.contextId().fpcIdentity().union().int64();
+
+                        BigInteger opId = operationId.uint64(),
+                                imsi = context.imsi().uint64();
+
+                        short ebi = context.ebi().uint8(),
+                                lbi = context.lbi().uint8();
+
+                        Optional<String> key = getDefaultTenant().flatMap(tenant ->
+                                tenant.fpcTopology()
+                                        .dpns()
+                                        .stream()
+                                        .filter(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+                                        .findFirst().map(node -> node.nodeId() + "/" + node.networkId())
+                        );
+
+                        if (key.isPresent()) {
+                            Short dpnTopic = FpcUtil.getTopicFromNode(key.get());
+
+                            if (dpnTopic != null) {
+                                if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+                                    s1u_sgw_gtpu_teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+                                } else {
+                                    throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+                                }
+                                if (context.dl().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+                                    s1u_enb_gtpu_teid = ((ThreegppTunnel) context.dl().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+                                } else {
+                                    throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+                                }
+
+
+                                if (commands.contains("session")) {
+                                    tasks.add(Executors.callable(() -> {
+                                        dpnCommunicationService.create_session(
+                                                dpnTopic,
+                                                imsi,
+                                                Ip4Prefix.valueOf(context.delegatingIpPrefixes().get(0).toString()).address(),
+                                                ebi,
+                                                ulLocalAddress,
+                                                s1u_sgw_gtpu_teid,
+                                                cId,
+                                                opId,
+                                                contextId
+                                        );
+
+                                        getDefaultTenant().ifPresent(
+                                                tenant -> tenant.fpcMobility().addToContexts(convertContext(context))
+                                        );
+                                    }));
+
+                                    if (commands.contains("downlink")) {
+                                        tasks.add(Executors.callable(() -> {
+                                            dpnCommunicationService.modify_bearer_dl(
+                                                    dpnTopic,
+                                                    dlRemoteAddress,
+                                                    s1u_enb_gtpu_teid,
+                                                    s1u_sgw_gtpu_teid,
+                                                    cId,
+                                                    opId
+                                            );
+
+                                            getDefaultTenant().ifPresent(
+                                                    tenant -> tenant.fpcMobility().addToContexts(convertContext(context))
+                                            );
+                                        }));
+                                    }
+                                } else if (commands.contains("indirect-forward")) {
+                                    // TODO - Modify API for Indirect Forwarding to/from another SGW
+                                } else if (commands.contains("uplink")) {
+                                    tasks.add(Executors.callable(() -> {
+                                        dpnCommunicationService.create_bearer_ul(
+                                                dpnTopic,
+                                                imsi,
+                                                lbi,
+                                                ebi,
+                                                ulLocalAddress,
+                                                s1u_sgw_gtpu_teid
+                                        );
+
+                                        getDefaultTenant().ifPresent(
+                                                tenant -> tenant.fpcMobility().addToContexts(convertContext(context))
+                                        );
+                                    }));
+                                }
+                            } else {
+                                throw new IllegalArgumentException("Could not find Topic ID");
+                            }
+                        } else {
+                            throw new IllegalArgumentException("DPN does not have node and network ID defined.");
+                        }
+                    }
+                }
+            }
+
+            ExecutorService executor = Executors.newWorkStealingPool();
+            executor.invokeAll(tasks).forEach(
+                    future -> {
+                        try {
+                            future.get();
+                        } catch (Exception e) {
+                            throw new IllegalStateException(e);
+                        }
+                    }
+            );
+
+            configureOutput.resultType(defaultCommonSuccess);
+            configureOutput.result(Result.of(ResultEnum.OK));
+        } catch (Exception e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+            DefaultErr defaultErr = new DefaultErr();
+            configureOutput.resultType(defaultErr);
+            defaultErr.errorInfo(ExceptionUtils.getFullStackTrace(e));
+            defaultErr.errorTypeId(ErrorTypeId.of(0));
+        }
+
+        return configureOutput;
+    }
+
+    public DefaultConfigureOutput configureUpdate(
+            CreateOrUpdate update,
+            ClientIdentifier clientId,
+            OpIdentifier operationId
+    ) {
+        DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
+        Collection<Callable<Object>> tasks = new ArrayList<>();
+
+        try {
+            DefaultCommonSuccess defaultCommonSuccess = new DefaultCommonSuccess();
+            for (Contexts context : update.contexts()) {
+                defaultCommonSuccess.addToContexts(context);
+
+                if (getDefaultTenant().map(
+                        tenant -> tenant.fpcMobility().contexts() == null ||
+                                tenant.fpcMobility()
+                                        .contexts()
+                                        .parallelStream()
+                                        .noneMatch(contexts -> contexts.contextId().equals(context.contextId()))
+                ).orElse(false)) {
+                    throw new IllegalStateException("Context doesn't exist.");
+                }
+
+                for (Dpns dpn : context.dpns()) {
+                    if (getDefaultTenant().map(
+                            tenant -> tenant.fpcTopology().dpns() == null ||
+                                    tenant.fpcTopology().dpns()
+                                            .stream()
+                                            .noneMatch(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+                    ).orElse(false)) {
+                        throw new IllegalStateException("DPN ID is not registered to the topology.");
+                    }
+
+                    if (context.instructions().instrType() instanceof Instr3GppMob) {
+                        Instr3GppMob instr3GppMob = (Instr3GppMob) context.instructions().instrType();
+                        String commands = Bits.toString(instr3GppMob.instr3GppMob().bits());
+
+                        Ip4Address ulLocalAddress = Ip4Address.valueOf(context.ul().tunnelLocalAddress().toString()),
+                                dlRemoteAddress = Ip4Address.valueOf(context.dl().tunnelRemoteAddress().toString()),
+                                dlLocalAddress = Ip4Address.valueOf(context.dl().tunnelLocalAddress().toString());
+
+                        long s1u_sgw_gtpu_teid, s1u_enb_gtpu_teid,
+                                cId = clientId.fpcIdentity().union().int64(),
+                                contextId = context.contextId().fpcIdentity().union().int64();
+
+                        BigInteger opId = operationId.uint64();
+
+                        Optional<String> key = getDefaultTenant().flatMap(tenant ->
+                                tenant.fpcTopology()
+                                        .dpns()
+                                        .stream()
+                                        .filter(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+                                        .findFirst().map(node -> node.nodeId() + "/" + node.networkId())
+                        );
+
+                        if (key.isPresent()) {
+                            Short dpnTopic = FpcUtil.getTopicFromNode(key.get());
+
+                            if (dpnTopic != null) {
+                                if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+                                    s1u_sgw_gtpu_teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+                                } else {
+                                    throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+                                }
+                                if (context.dl().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+                                    s1u_enb_gtpu_teid = ((ThreegppTunnel) context.dl().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+                                } else {
+                                    throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+                                }
+
+                                if (commands.contains("downlink")) {
+                                    if (context.dl().lifetime() >= 0L) {
+                                        tasks.add(Executors.callable(() ->
+                                                dpnCommunicationService.modify_bearer_dl(
+                                                        dpnTopic,
+                                                        dlRemoteAddress,
+                                                        s1u_enb_gtpu_teid,
+                                                        dlLocalAddress,
+                                                        contextId,
+                                                        cId,
+                                                        opId
+                                                )
+                                        ));
+                                    } else {
+                                        tasks.add(Executors.callable(() ->
+                                                dpnCommunicationService.delete_bearer(
+                                                        dpnTopic,
+                                                        s1u_enb_gtpu_teid
+                                                )
+                                        ));
+                                    }
+                                }
+                                if (commands.contains("uplink")) {
+                                    if (context.ul().lifetime() >= 0L) {
+                                        tasks.add(Executors.callable(() ->
+                                                dpnCommunicationService.modify_bearer_ul(
+                                                        dpnTopic,
+                                                        ulLocalAddress,
+                                                        s1u_enb_gtpu_teid,
+                                                        s1u_sgw_gtpu_teid
+                                                )
+                                        ));
+                                    } else {
+                                        tasks.add(Executors.callable(() ->
+                                                dpnCommunicationService.delete_bearer(
+                                                        dpnTopic,
+                                                        s1u_sgw_gtpu_teid
+                                                )
+                                        ));
+                                    }
+                                }
+                            } else {
+                                throw new IllegalArgumentException("Could not find Topic ID");
+                            }
+                        } else {
+                            throw new IllegalArgumentException("DPN does not have node and network ID defined.");
+                        }
+                    }
+                }
+            }
+
+            ExecutorService executor = Executors.newWorkStealingPool();
+            executor.invokeAll(tasks).forEach(
+                    future -> {
+                        try {
+                            future.get();
+                        } catch (Exception e) {
+                            throw new IllegalStateException(e);
+                        }
+                    }
+            );
+
+            configureOutput.resultType(defaultCommonSuccess);
+            configureOutput.result(Result.of(ResultEnum.OK));
+
+            update.contexts().forEach(
+                    contexts -> getDefaultTenant().ifPresent(
+                            tenant -> tenant.fpcMobility().addToContexts(convertContext(contexts))
+                    )
+            );
+        } catch (Exception e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+            DefaultErr defaultErr = new DefaultErr();
+            defaultErr.errorInfo(ExceptionUtils.getFullStackTrace(e));
+            defaultErr.errorTypeId(ErrorTypeId.of(0));
+            configureOutput.resultType(defaultErr);
+            configureOutput.result(Result.of(ResultEnum.ERR));
+        }
+
+        return configureOutput;
+    }
+
+    public DefaultConfigureOutput configureDelete(
+            DeleteOrQuery delete,
+            ClientIdentifier clientId,
+            OpIdentifier operationId
+    ) {
+        DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
+        Collection<Callable<Object>> tasks = new ArrayList<>();
+        DefaultDeleteSuccess defaultDeleteSuccess = new DefaultDeleteSuccess();
+        try {
+            for (Targets target : delete.targets()) {
+                defaultDeleteSuccess.addToTargets(target);
+                String targetStr = target.target().toString(),
+                        s = StringUtils.substringBetween(targetStr, "contexts=", "/"),
+                        trgt = s != null ? s : StringUtils.substringAfter(targetStr, "contexts=");
+
+                getDefaultTenant().map(
+                        tenant -> {
+                            if (tenant.fpcMobility().contexts() != null) {
+                                return tenant.fpcMobility()
+                                        .contexts()
+                                        .stream()
+                                        .filter(contexts -> contexts.contextId().toString().equals(trgt))
+                                        .findFirst()
+                                        .orElseThrow(
+                                                () -> new IllegalArgumentException("Context doesn't exist.")
+                                        );
+                            }
+                            throw new IllegalArgumentException("Contexts are empty.");
+                        }
+                ).ifPresent(
+                        context -> context.dpns().forEach(
+                                dpn -> {
+                                    Optional<String> key = getDefaultTenant().flatMap(tenant ->
+                                            tenant.fpcTopology()
+                                                    .dpns()
+                                                    .stream()
+                                                    .filter(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+                                                    .findFirst().map(node -> node.nodeId() + "/" + node.networkId())
+                                    );
+
+                                    if (key.isPresent()) {
+                                        Short dpnTopic = FpcUtil.getTopicFromNode(key.get());
+
+                                        if (dpnTopic != null) {
+                                            Long teid;
+                                            if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+                                                teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+                                            } else {
+                                                throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+                                            }
+
+                                            long cId = clientId.fpcIdentity().union().int64();
+                                            BigInteger opId = operationId.uint64();
+
+                                            if (targetStr.endsWith("ul") || targetStr.endsWith("dl")) {
+                                                tasks.add(Executors.callable(() -> {
+                                                    dpnCommunicationService.delete_bearer(
+                                                            dpnTopic,
+                                                            teid
+                                                    );
+
+                                                    context.dl(null);
+                                                    context.ul(null);
+                                                }));
+                                            } else {
+                                                tasks.add(Executors.callable(() -> {
+                                                    dpnCommunicationService.delete_session(
+                                                            dpnTopic,
+                                                            context.lbi().uint8(),
+                                                            teid,
+                                                            cId,
+                                                            opId,
+                                                            context.contextId().fpcIdentity().union().int64()
+                                                    );
+
+                                                    getDefaultTenant().ifPresent(
+                                                            tenant -> tenant.fpcMobility()
+                                                                    .contexts()
+                                                                    .remove(context)
+                                                    );
+                                                }));
+                                            }
+
+                                        } else {
+                                            throw new IllegalArgumentException("Could not find Topic ID");
+                                        }
+                                    } else {
+                                        throw new IllegalArgumentException("DPN does not have node and network ID defined.");
+                                    }
+                                }
+                        )
+                );
+
+            }
+
+            ExecutorService executor = Executors.newWorkStealingPool();
+            executor.invokeAll(tasks).forEach(
+                    future -> {
+                        try {
+                            future.get();
+                        } catch (Exception e) {
+                            throw new IllegalStateException(e);
+                        }
+                    }
+            );
+
+            configureOutput.resultType(defaultDeleteSuccess);
+            configureOutput.result(Result.of(ResultEnum.OK));
+
+        } catch (Exception e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+            DefaultErr defaultErr = new DefaultErr();
+            configureOutput.resultType(defaultErr);
+            defaultErr.errorInfo(ExceptionUtils.getFullStackTrace(e));
+            defaultErr.errorTypeId(ErrorTypeId.of(0));
+        }
+
+        return configureOutput;
+    }
+
+    /**
+     * Accumulates events to allow processing after a desired number of
+     * events were accumulated.
+     */
+    private class InternalEventAccumulator extends AbstractAccumulator<DynamicConfigEvent> {
+
+        /**
+         * Constructs the event accumulator with timer and event limit.
+         */
+        private InternalEventAccumulator() {
+            super(new Timer(TIMER), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
+        }
+
+        @Override
+        public void processItems(List<DynamicConfigEvent> events) {
+            events.forEach(
+                    event -> {
+                        checkNotNull(event, EVENT_NULL);
+                        switch (event.type()) {
+                            case NODE_ADDED:
+                            case NODE_DELETED:
+                                Filter filter = Filter.builder().build();
+                                DataNode node = dynamicConfigService.readNode(tenantsResourceId, filter);
+                                getModelObjects(node, null).forEach(
+                                        modelObject -> fpcAgentData.tenants((DefaultTenants) modelObject)
+                                );
+                                break;
+                            case NODE_UPDATED:
+                            case NODE_REPLACED:
+                                break;
+                            default:
+                                log.warn(UNKNOWN_EVENT, event.type());
+                                break;
+                        }
+                    }
+            );
+        }
+
+    }
+
+    /**
+     * Representation of internal listener, listening for dynamic config event.
+     */
+    private class InternalConfigListener implements DynamicConfigListener {
+        /**
+         * Returns true if the event resource id points to the root level node
+         * only and event is for addition and deletion; false otherwise.
+         *
+         * @param event config event
+         * @return true if event is supported; false otherwise
+         */
+        private boolean isSupported(DynamicConfigEvent event) {
+            ResourceId rsId = event.subject();
+            List<NodeKey> storeKeys = rsId.nodeKeys();
+            List<NodeKey> tenantKeys = tenantsResourceId.nodeKeys();
+            return storeKeys.size() >= 2 && storeKeys.get(0).equals(tenantKeys.get(1));
+        }
+
+        @Override
+        public boolean isRelevant(DynamicConfigEvent event) {
+            return isSupported(event);
+        }
+
+        @Override
+        public void event(DynamicConfigEvent event) {
+            accumulator.add(event);
+        }
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java
new file mode 100644
index 0000000..4b88510
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java
@@ -0,0 +1,57 @@
+package org.onosproject.fpcagent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.DefaultTenants;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.OpIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.DefaultConfigureOutput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.CreateOrUpdate;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.DeleteOrQuery;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.Tenant;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.InnerModelObject;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ResourceId;
+
+import java.util.List;
+import java.util.Optional;
+
+@Beta
+public interface TenantService {
+    Optional<DefaultTenants> getTenants();
+
+    void createNode(InnerModelObject innerModelObject);
+
+    void updateNode(InnerModelObject innerModelObject);
+
+    List<ModelObject> getModelObjects(DataNode dataNode, ResourceId appId);
+
+    Optional<Tenant> getDefaultTenant();
+
+    Optional<Tenant> getTenant(FpcIdentity tenantId);
+
+    Optional<Tenant> getTenant(ClientIdentifier clientId);
+
+    Optional<Tenant> registerClient(ClientIdentifier clientId, FpcIdentity tenantId);
+
+    Optional<Tenant> deregisterClient(ClientIdentifier clientId);
+
+    DefaultConfigureOutput configureCreate(
+            CreateOrUpdate create,
+            ClientIdentifier clientId,
+            OpIdentifier operationId
+    );
+
+    DefaultConfigureOutput configureUpdate(
+            CreateOrUpdate create,
+            ClientIdentifier clientId,
+            OpIdentifier operationId
+    );
+
+    DefaultConfigureOutput configureDelete(
+            DeleteOrQuery delete,
+            ClientIdentifier clientId,
+            OpIdentifier operationId
+    );
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java
new file mode 100644
index 0000000..5a91d52
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java
@@ -0,0 +1,315 @@
+package org.onosproject.fpcagent.helpers;
+
+import com.fasterxml.jackson.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+        "monitor-threads",
+        "scheduled-monitors-poolsize",
+        "dpn-subscriber-uri",
+        "dpn-listener-id",
+        "dpn-publisher-uri",
+        "dpn-client-threads",
+        "metricsupdate-ms",
+        "mobilityupdate-ms",
+        "activation-threads",
+        "target-read-limit",
+        "http-notifier-clients",
+        "zmq-nbi-server-poolsize",
+        "zmq-nbi-server-uri",
+        "zmq-nbi-inproc-uri",
+        "zmq-nbi-handler-poolsize",
+        "http-nio2-nb-poolsize",
+        "http-nio2-nb-port",
+        "node-id",
+        "network-id",
+        "zmq-broadcast-controllers",
+        "zmq-broadcast-dpns",
+        "zmq-broadcast-all"
+})
+public class ConfigHelper {
+    @JsonProperty("monitor-threads")
+    private Integer monitorThreads;
+    @JsonProperty("scheduled-monitors-poolsize")
+    private Integer scheduledMonitorsPoolsize;
+    @JsonProperty("dpn-subscriber-uri")
+    private String dpnSubscriberUri;
+    @JsonProperty("dpn-listener-id")
+    private Integer dpnListenerId;
+    @JsonProperty("dpn-publisher-uri")
+    private String dpnPublisherUri;
+    @JsonProperty("dpn-client-threads")
+    private Integer dpnClientThreads;
+    @JsonProperty("metricsupdate-ms")
+    private Integer metricsupdateMs;
+    @JsonProperty("mobilityupdate-ms")
+    private Integer mobilityupdateMs;
+    @JsonProperty("activation-threads")
+    private Integer activationThreads;
+    @JsonProperty("target-read-limit")
+    private Integer targetReadLimit;
+    @JsonProperty("http-notifier-clients")
+    private Integer httpNotifierClients;
+    @JsonProperty("zmq-nbi-server-poolsize")
+    private Integer zmqNbiServerPoolsize;
+    @JsonProperty("zmq-nbi-server-uri")
+    private String zmqNbiServerUri;
+    @JsonProperty("zmq-nbi-inproc-uri")
+    private String zmqNbiInprocUri;
+    @JsonProperty("zmq-nbi-handler-poolsize")
+    private Integer zmqNbiHandlerPoolsize;
+    @JsonProperty("http-nio2-nb-poolsize")
+    private Integer httpNio2NbPoolsize;
+    @JsonProperty("http-nio2-nb-port")
+    private Integer httpNio2NbPort;
+    @JsonProperty("node-id")
+    private String nodeId;
+    @JsonProperty("network-id")
+    private String networkId;
+    @JsonProperty("zmq-broadcast-controllers")
+    private String zmqBroadcastControllers;
+    @JsonProperty("zmq-broadcast-dpns")
+    private String zmqBroadcastDpns;
+    @JsonProperty("zmq-broadcast-all")
+    private String zmqBroadcastAll;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<>();
+
+    /**
+     * No args constructor for use in serialization
+     */
+    public ConfigHelper() {
+    }
+
+
+    public Integer monitorThreads() {
+        return monitorThreads;
+    }
+
+
+    public void setMonitorThreads(Integer monitorThreads) {
+        this.monitorThreads = monitorThreads;
+    }
+
+
+    public Integer scheduledMonitorsPoolsize() {
+        return scheduledMonitorsPoolsize;
+    }
+
+
+    public void setScheduledMonitorsPoolsize(Integer scheduledMonitorsPoolsize) {
+        this.scheduledMonitorsPoolsize = scheduledMonitorsPoolsize;
+    }
+
+
+    public String dpnSubscriberUri() {
+        return dpnSubscriberUri;
+    }
+
+
+    public void setDpnSubscriberUri(String dpnSubscriberUri) {
+        this.dpnSubscriberUri = dpnSubscriberUri;
+    }
+
+
+    public Integer dpnListenerId() {
+        return dpnListenerId;
+    }
+
+
+    public void setDpnListenerId(Integer dpnListenerId) {
+        this.dpnListenerId = dpnListenerId;
+    }
+
+
+    public String dpnPublisherUri() {
+        return dpnPublisherUri;
+    }
+
+    public void setDpnPublisherUri(String dpnPublisherUri) {
+        this.dpnPublisherUri = dpnPublisherUri;
+    }
+
+
+    public Integer dpnClientThreads() {
+        return dpnClientThreads;
+    }
+
+
+    public void setDpnClientThreads(Integer dpnClientThreads) {
+        this.dpnClientThreads = dpnClientThreads;
+    }
+
+
+    public Integer metricUpdateMs() {
+        return metricsupdateMs;
+    }
+
+
+    public void setMetricsupdateMs(Integer metricsupdateMs) {
+        this.metricsupdateMs = metricsupdateMs;
+    }
+
+
+    public Integer mobilityUpdateMs() {
+        return mobilityupdateMs;
+    }
+
+
+    public void setMobilityupdateMs(Integer mobilityupdateMs) {
+        this.mobilityupdateMs = mobilityupdateMs;
+    }
+
+
+    public Integer activationThreads() {
+        return activationThreads;
+    }
+
+
+    public void setActivationThreads(Integer activationThreads) {
+        this.activationThreads = activationThreads;
+    }
+
+
+    public Integer targetReadLimit() {
+        return targetReadLimit;
+    }
+
+
+    public void setTargetReadLimit(Integer targetReadLimit) {
+        this.targetReadLimit = targetReadLimit;
+    }
+
+
+    public Integer httpNotifierClients() {
+        return httpNotifierClients;
+    }
+
+
+    public void setHttpNotifierClients(Integer httpNotifierClients) {
+        this.httpNotifierClients = httpNotifierClients;
+    }
+
+
+    public Integer zmqServerPoolsize() {
+        return zmqNbiServerPoolsize;
+    }
+
+
+    public void setZmqNbiServerPoolsize(Integer zmqNbiServerPoolsize) {
+        this.zmqNbiServerPoolsize = zmqNbiServerPoolsize;
+    }
+
+
+    public String zmqServerUri() {
+        return zmqNbiServerUri;
+    }
+
+
+    public void setZmqNbiServerUri(String zmqNbiServerUri) {
+        this.zmqNbiServerUri = zmqNbiServerUri;
+    }
+
+
+    public String zmqInprocUri() {
+        return zmqNbiInprocUri;
+    }
+
+
+    public void setZmqNbiInprocUri(String zmqNbiInprocUri) {
+        this.zmqNbiInprocUri = zmqNbiInprocUri;
+    }
+
+
+    public Integer zmqHandlerPoolsize() {
+        return zmqNbiHandlerPoolsize;
+    }
+
+
+    public void setZmqNbiHandlerPoolsize(Integer zmqNbiHandlerPoolsize) {
+        this.zmqNbiHandlerPoolsize = zmqNbiHandlerPoolsize;
+    }
+
+
+    public Integer httpNio2Poolsize() {
+        return httpNio2NbPoolsize;
+    }
+
+
+    public void setHttpNio2NbPoolsize(Integer httpNio2NbPoolsize) {
+        this.httpNio2NbPoolsize = httpNio2NbPoolsize;
+    }
+
+
+    public Integer httpNio2Port() {
+        return httpNio2NbPort;
+    }
+
+
+    public void setHttpNio2NbPort(Integer httpNio2NbPort) {
+        this.httpNio2NbPort = httpNio2NbPort;
+    }
+
+
+    public String nodeId() {
+        return nodeId;
+    }
+
+
+    public void setNodeId(String node_id) {
+        this.nodeId = node_id;
+    }
+
+
+    public String networkId() {
+        return networkId;
+    }
+
+
+    public void setNetworkId(String network_id) {
+        this.networkId = network_id;
+    }
+
+
+    public String zmqBroadcastControllers() {
+        return zmqBroadcastControllers;
+    }
+
+
+    public void setZmqBroadcastControllers(String zmqBroadcastControllers) {
+        this.zmqBroadcastControllers = zmqBroadcastControllers;
+    }
+
+    public String zmqBroadcastDpns() {
+        return zmqBroadcastDpns;
+    }
+
+
+    public void setZmqBroadcastDpns(String zmqBroadcastDpns) {
+        this.zmqBroadcastDpns = zmqBroadcastDpns;
+    }
+
+
+    public String zmqBroadcastAll() {
+        return zmqBroadcastAll;
+    }
+
+
+    public void setZmqBroadcastAll(String zmqBroadcastAll) {
+        this.zmqBroadcastAll = zmqBroadcastAll;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java
new file mode 100644
index 0000000..d023cb8
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java
@@ -0,0 +1,167 @@
+package org.onosproject.fpcagent.helpers;
+
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.fpcmobility.Contexts;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.fpcmobility.DefaultContexts;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcContextId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnGroupId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcPortId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Dl;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Dpns;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Ul;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpcidentity.FpcIdentityUnion;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.ietfdmmthreegpp.EbiType;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.ietfdmmthreegpp.ImsiType;
+import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.IpPrefix;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+
+public class Converter {
+    /**
+     * Short to Byte
+     *
+     * @param value - Short
+     * @return byte value
+     */
+    public static byte toUint8(Short value) {
+        return value.byteValue();
+    }
+
+    /**
+     * Short to byte array
+     *
+     * @param value - Short
+     * @return byte array
+     */
+    public static byte[] toUint16(Short value) {
+        return new byte[]{(byte) (value >>> 8), (byte) (value & 0xFF)};
+    }
+
+    /**
+     * Lower two bytes of an integer to byte array
+     *
+     * @param value - integer value
+     * @return byte array
+     */
+    public static byte[] toUint16(Integer value) {
+        return new byte[]{(byte) (value >>> 8), (byte) (value & 0xFF)};
+    }
+
+    /**
+     * Long to byte array.
+     *
+     * @param value - long
+     * @return byte array
+     */
+    public static byte[] toUint32(long value) {
+        return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) (value & 0xFF)};
+    }
+
+    /**
+     * BigInteger to byte array.
+     *
+     * @param value - BigInteger
+     * @return byte array
+     */
+    public static byte[] toUint64(BigInteger value) {
+        return new byte[]{value.shiftRight(56).byteValue(), value.shiftRight(48).byteValue(), value.shiftRight(40).byteValue(),
+                value.shiftRight(32).byteValue(), value.shiftRight(24).byteValue(), value.shiftRight(16).byteValue(),
+                value.shiftRight(8).byteValue(), value.and(BigInteger.valueOf(0xFF)).byteValue()};
+    }
+
+    /**
+     * Decodes a 32 bit value
+     *
+     * @param source - byte array
+     * @param offset - offset in the array where the 8 bytes begins
+     * @return integer
+     */
+    public static int toInt(byte[] source, int offset) {
+        return new BigInteger(Arrays.copyOfRange(source, offset, offset + 4)).intValue();
+    }
+
+    /**
+     * Converts a byte array to BigInteger
+     *
+     * @param source - byte array
+     * @param offset - offset in the array where the 8 bytes begins
+     * @return BigInteger representing a Uint64
+     */
+    public static BigInteger toBigInt(byte[] source, int offset) {
+        return new BigInteger(Arrays.copyOfRange(source, offset, offset + 8));
+    }
+
+    /**
+     * Converts an integer to a long (used for larger unsigned integers)
+     *
+     * @param source - message buffer (byte array)
+     * @param offset - offset in the array where the 4 bytes begins
+     * @return Long value of the unsigned integer
+     */
+    public static long fromIntToLong(byte[] source, int offset) {
+        long value = 0;
+        for (int i = offset; i < offset + 4; i++) {
+            value = (value << 8) + (source[i] & 0xff);
+        }
+        return value;
+    }
+
+    public static Function<String, FpcIdentity> getFpcIdentity = (v) -> new FpcIdentity(new FpcIdentityUnion(v));
+    public static Function<String, ClientIdentifier> getClientIdentity = (v) -> new ClientIdentifier(getFpcIdentity.apply(v));
+
+    public static Contexts convertContext(org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.payload.Contexts contexts) {
+        Contexts ctx = new DefaultContexts();
+        FpcContextId fpcContextId = contexts.contextId();
+        List<IpPrefix> ipPrefixes = contexts.delegatingIpPrefixes();
+        Dl dl = contexts.dl();
+        Ul ul = contexts.ul();
+        boolean dormant = contexts.dormant();
+        FpcDpnGroupId fpcDpnGroupId = contexts.dpnGroup();
+        List<Dpns> dpns = contexts.dpns();
+        EbiType ebi = contexts.ebi();
+        EbiType lbi = contexts.lbi();
+        ImsiType imsi = contexts.imsi();
+        FpcContextId fpcContextId1 = contexts.parentContext();
+        List<FpcPortId> ports = contexts.ports();
+
+        if (fpcContextId != null) {
+            ctx.contextId(fpcContextId);
+        }
+        if (ipPrefixes != null) {
+            ctx.delegatingIpPrefixes(ipPrefixes);
+        }
+        if (dl != null) {
+            ctx.dl(dl);
+        }
+        if (ul != null) {
+            ctx.ul(ul);
+        }
+        ctx.dormant(dormant);
+        if (fpcDpnGroupId != null) {
+            ctx.dpnGroup(fpcDpnGroupId);
+        }
+        if (dpns != null) {
+            ctx.dpns(dpns);
+        }
+        if (ebi != null) {
+            ctx.ebi(ebi);
+        }
+        if (lbi != null) {
+            ctx.lbi(lbi);
+        }
+        if (imsi != null) {
+            ctx.imsi(imsi);
+        }
+        if (fpcContextId1 != null) {
+            ctx.parentContext(fpcContextId1);
+        }
+        if (ports != null) {
+            ctx.ports(ports);
+        }
+        return ctx;
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnCommunicationService.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnCommunicationService.java
new file mode 100644
index 0000000..415e475
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnCommunicationService.java
@@ -0,0 +1,167 @@
+/*
+ * 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.onosproject.fpcagent.helpers;
+
+import org.onlab.packet.Ip4Address;
+
+import java.math.BigInteger;
+
+public interface DpnCommunicationService {
+    /**
+     * Creates Mobility Session
+     *
+     * @param topicId           - DPN
+     * @param imsi              - IMSI
+     * @param ue_ip             - Session IP Address
+     * @param default_ebi       - Default EBI
+     * @param s1u_sgw_gtpu_ipv4 - SGW GTP-U IPv4 Address
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     * @param clientIdentifier  - Client Identifier
+     * @param opIdentifier      - Operation Identifier
+     * @param sessionId         - Session Id
+     */
+    void create_session(
+            Short topicId,
+            BigInteger imsi,
+            Ip4Address ue_ip,
+            Short default_ebi,
+            Ip4Address s1u_sgw_gtpu_ipv4,
+            Long s1u_sgw_gtpu_teid,
+            Long clientIdentifier,
+            BigInteger opIdentifier,
+            Long sessionId
+    );
+
+    /**
+     * DeleteOrQuery Mobility Session.
+     *
+     * @param dpn               - DPN
+     * @param del_default_ebi   - Default EBI
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     * @param clientIdentifier  - Client Identifier
+     * @param opIdentifier      - Operation Identifier
+     * @param sessionId         - Session Id
+     */
+    void delete_session(
+            Short dpn,
+            Short del_default_ebi,
+            Long s1u_sgw_gtpu_teid,
+            Long clientIdentifier,
+            BigInteger opIdentifier,
+            Long sessionId
+    );
+
+    /**
+     * Create Uplink Bearer.
+     *
+     * @param dpn               - DPN
+     * @param imsi              - IMSI
+     * @param default_ebi       - Default EBI
+     * @param dedicated_ebi     - Dedicated EBI
+     * @param s1u_sgw_gtpu_ipv4 - SGW GTP-U IPv4 Address
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     */
+    void create_bearer_ul(
+            Short dpn,
+            BigInteger imsi,
+            Short default_ebi,
+            Short dedicated_ebi,
+            Ip4Address s1u_sgw_gtpu_ipv4,
+            Long s1u_sgw_gtpu_teid
+    );
+
+    /**
+     * Create Downlink Bearer.
+     *
+     * @param dpn               - DPN
+     * @param dedicated_ebi     - Default EBI
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     * @param s1u_enb_gtpu_ipv4 - ENodeB GTP-U IPv4 Address
+     * @param s1u_enb_gtpu_teid - ENodeB GTP-U TEID
+     */
+    void create_bearer_dl(
+            Short dpn,
+            Short dedicated_ebi,
+            Long s1u_sgw_gtpu_teid,
+            Ip4Address s1u_enb_gtpu_ipv4,
+            Long s1u_enb_gtpu_teid
+    );
+
+    /**
+     * Modify Downlink Bearer.
+     *  @param topicId               - DPN
+     * @param s1u_enodeb_ipv4 - ENodeB GTP-U IPv4 Address
+     * @param s1u_enodeb_teid - ENodeB TEID
+     * @param s1u_sgw_ipv4 - SGW GTP-U IPv4 Address
+     * @param sessionId         - Session Id
+     * @param clientId      - Operation Identifier
+     * @param opId         - Session Id
+     */
+    void modify_bearer_dl(
+            Short topicId,
+            Ip4Address s1u_enodeb_ipv4,
+            Long s1u_enodeb_teid,
+            Ip4Address s1u_sgw_ipv4,
+            Long sessionId,
+            Long clientId,
+            BigInteger opId
+    );
+
+    /**
+     * Modify Uplink Bearer.
+     *
+     * @param dpn               - DPN
+     * @param s1u_enb_gtpu_ipv4 - ENodeB GTP-U IPv4 Address
+     * @param s1u_enb_gtpu_teid - ENodeB GTP-U TEID
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     */
+    void modify_bearer_ul(
+            Short dpn,
+            Ip4Address s1u_enb_gtpu_ipv4,
+            Long s1u_enb_gtpu_teid,
+            Long s1u_sgw_gtpu_teid
+    );
+
+    /**
+     * DeleteOrQuery Bearer.
+     *
+     * @param dpnTopic          - DPN
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     */
+    void delete_bearer(
+            Short dpnTopic,
+            Long s1u_sgw_gtpu_teid
+    );
+
+    /**
+     * Creates the byte buffer to send ADC rules over ZMQ
+     *
+     * @param topic        - DPN Topic
+     * @param domain_name  - domain
+     * @param ip           - ipaddress/ipprefix (i.e. 127.0.0.1/32)
+     * @param drop         - Drop if 1
+     * @param rating_group - Rating Group
+     * @param service_ID   - Service ID
+     * @param sponsor_ID   - Sponsor ID
+     */
+    void send_ADC_rules(
+            Short topic,
+            String domain_name, String ip,
+            Short drop, Long rating_group,
+            Long service_ID, String sponsor_ID
+    );
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnNgicCommunicator.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnNgicCommunicator.java
new file mode 100644
index 0000000..b12945c
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnNgicCommunicator.java
@@ -0,0 +1,281 @@
+package org.onosproject.fpcagent.helpers;
+
+
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onosproject.fpcagent.workers.ZMQSBPublisherManager;
+import org.onosproject.fpcagent.workers.ZMQSBSubscriberManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
+import static org.onosproject.fpcagent.helpers.Converter.*;
+
+/**
+ * DPDK DPN API over ZeroMQ.
+ */
+public class DpnNgicCommunicator implements DpnCommunicationService {
+    protected static final Logger log = LoggerFactory.getLogger(DpnNgicCommunicator.class);
+    /**
+     * Topic for broadcasting
+     */
+    private static byte BROADCAST_TOPIC = 0b0000_0000;
+    private static byte CREATE_SESSION_TYPE = 0b0000_0001;
+    private static byte MODIFY_DL_BEARER_TYPE = 0b0000_0010;
+    private static byte DELETE_SESSION_TYPE = 0b0000_0011;
+    private static byte MODIFY_UL_BEARER_TYPE = 0b0000_0100;
+    private static byte CREATE_UL_BEARER_TYPE = 0b0000_0101;
+    private static byte CREATE_DL_BEARER_TYPE = 0b0000_0110;
+    private static byte DELETE_BEARER_TYPE = 0b0000_0110;
+    private static byte HELLO = 0b0000_1000;
+    private static byte BYE = 0b0000_1001;
+    private static byte SEND_ADC_TYPE = 0b001_0001;
+    private static byte DDN_ACK = 0b0000_0110;
+
+    enum s11MsgType {
+        CREATE_SESSION(1),
+        MODIFY_BEARER(2),
+        DELETE_SESSION(3),
+        DPN_RESPONSE(4),
+        DDN(5),
+        ASSIGN_TOPIC(10),
+        ASSIGN_CONFLICT(11),
+        DPN_STATUS_INDICATION(12),
+        DPN_STATUS_ACK(13),
+        CONTROLLER_STATUS_INDICATION(14),
+        ADC_RULE(17),
+        PCC_RULE(18),
+        METER_RULE(19),
+        SDF_RULE(20);
+
+        private byte type;
+
+        s11MsgType(int type) {
+            this.type = (byte) type;
+        }
+
+        public byte getType() {
+            return type;
+        }
+    }
+
+    @Override
+    public void create_session(
+            Short topicId,
+            BigInteger imsi,
+            Ip4Address ue_ip,
+            Short default_ebi,
+            Ip4Address s1u_sgw_gtpu_ipv4,
+            Long s1u_sgw_gtpu_teid,
+            Long clientIdentifier,
+            BigInteger opIdentifier,
+            Long sessionId
+    ) {
+        /* NGIC Create Session expected buffer:
+            value: topic_id          bytes: 8
+            value: type              bytes: 8
+            value: imsi              bytes: 64
+            value: default_ebi       bytes: 8
+            value: ue_ipv4           bytes: 32
+            value: s1u_sgw_teid      bytes: 32
+            value: s1u_sgw_ipv4      bytes: 32
+            value: session_id        bytes: 64
+            value: controller_topic  bytes: 32
+            value: client_id         bytes: 32
+            value: op_id             bytes: 32
+         */
+        // TODO: check if subscriber is open.
+        ByteBuffer bb = ByteBuffer.allocate(41)
+                .put(toUint8(topicId))
+                .put(s11MsgType.CREATE_SESSION.getType())
+                .put(toUint64(imsi))
+                .put(toUint8(default_ebi))
+                .put(toUint32(ue_ip.toInt()))
+                .put(toUint32(s1u_sgw_gtpu_teid))
+                .put(toUint32(s1u_sgw_gtpu_ipv4.toInt()))
+                .put(toUint64(BigInteger.valueOf(sessionId)))
+                .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+                .put(toUint32(clientIdentifier))
+                .put(toUint32(opIdentifier.longValue()));
+
+        log.info("create_session: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    @Override
+    public void delete_session(
+            Short dpn,
+            Short del_default_ebi,
+            Long s1u_sgw_gtpu_teid,
+            Long clientIdentifier,
+            BigInteger opIdentifier,
+            Long sessionId
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(19)
+                .put(toUint8(dpn))
+                .put(s11MsgType.DELETE_SESSION.getType())
+                .put(toUint64(BigInteger.valueOf(sessionId)))
+                .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+                .put(toUint32(clientIdentifier))
+                .put(toUint32(opIdentifier.longValue()));
+
+        log.info("delete_session: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    @Override
+    public void create_bearer_ul(
+            Short dpn,
+            BigInteger imsi,
+            Short default_ebi,
+            Short dedicated_ebi,
+            Ip4Address s1u_sgw_gtpu_ipv4,
+            Long s1u_sgw_gtpu_teid
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(21)
+                .put(toUint8(dpn))
+                .put(CREATE_UL_BEARER_TYPE)
+                .put(toUint64(imsi))
+                .put(toUint8(default_ebi))
+                .put(toUint8(dedicated_ebi))
+                .put(toUint32(s1u_sgw_gtpu_ipv4.toInt()))
+                .put(toUint32(s1u_sgw_gtpu_teid));
+
+        log.info("create_bearer_ul: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    @Override
+    public void create_bearer_dl(
+            Short dpn,
+            Short dedicated_ebi,
+            Long s1u_sgw_gtpu_teid,
+            Ip4Address s1u_enb_gtpu_ipv4,
+            Long s1u_enb_gtpu_teid
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(16)
+                .put(toUint8(dpn))
+                .put(CREATE_DL_BEARER_TYPE)
+                .put(toUint8(dedicated_ebi))
+                .put(toUint32(s1u_sgw_gtpu_teid))
+                .put(toUint32(s1u_enb_gtpu_ipv4.toInt()))
+                .put(toUint32(s1u_enb_gtpu_teid));
+
+        log.info("create_bearer_dl: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    @Override
+    public void modify_bearer_dl(
+            Short topicId,
+            Ip4Address s1u_enodeb_ipv4,
+            Long s1u_enodeb_teid,
+            Ip4Address s1u_sgw_ipv4,
+            Long sessionId,
+            Long clientId,
+            BigInteger opId
+    ) {
+        /* NGIC Modify Session expected buffer:
+            value: topic_id          bytes: 8
+            value: type              bytes: 8
+            value: s1u_enodeb_ipv4   bytes: 32
+            value: s1u_enodeb_teid   bytes: 32
+            value: s1u_sgw_ipv4      bytes: 32
+            value: session_id        bytes: 64
+            value: controller_topic  bytes: 8
+            value: client_id         bytes: 32
+            value: op_id             bytes: 32
+         */
+        ByteBuffer bb = ByteBuffer.allocate(32)
+                .put(toUint8(topicId))
+                .put(MODIFY_DL_BEARER_TYPE)
+                .put(toUint32(s1u_sgw_ipv4.toInt()))
+                .put(toUint32(s1u_enodeb_teid))
+                .put(toUint32(s1u_enodeb_ipv4.toInt()))
+                .put(toUint64(BigInteger.valueOf(sessionId)))
+                .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+                .put(toUint32(clientId))
+                .put(toUint32(opId.longValue()));
+
+        log.info("modify_bearer_dl: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    @Override
+    public void modify_bearer_ul(
+            Short dpn,
+            Ip4Address s1u_enb_gtpu_ipv4,
+            Long s1u_enb_gtpu_teid,
+            Long s1u_sgw_gtpu_teid
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(15)
+                .put(toUint8(dpn))
+                .put(MODIFY_UL_BEARER_TYPE)
+                .put(toUint32(s1u_enb_gtpu_ipv4.toInt()))
+                .put(toUint32(s1u_enb_gtpu_teid))
+                .put(toUint32(s1u_sgw_gtpu_teid));
+
+        log.info("modify_bearer_ul: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    @Override
+    public void delete_bearer(
+            Short dpnTopic,
+            Long s1u_sgw_gtpu_teid) {
+        ByteBuffer bb = ByteBuffer.allocate(7)
+                .put(toUint8(dpnTopic))
+                .put(DELETE_BEARER_TYPE)
+                .put(toUint32(s1u_sgw_gtpu_teid));
+
+        log.info("delete_bearer: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    @Override
+    public void send_ADC_rules(Short topic,
+                               String domain_name, String ip,
+                               Short drop, Long rating_group,
+                               Long service_ID, String sponsor_ID) {
+        Ip4Prefix ip_prefix = null;
+        if (ip != null) {
+            ip_prefix = Ip4Prefix.valueOf(ip);
+        }
+        Short selector_type = (short) (domain_name != null ? 0 : ip_prefix != null ? 2 : ip_prefix.address() != null ? 1 : 255);
+        if (selector_type == 255) {
+            log.warn("Domain/IP not found, failed to send rules");
+            return;
+        }
+        ByteBuffer bb = ByteBuffer.allocate(200);
+        bb.put(toUint8(topic))
+                .put(SEND_ADC_TYPE)
+                .put(toUint8(selector_type));
+        if (selector_type == 0) {
+            bb.put(toUint8((short) domain_name.length()))
+                    .put(domain_name.getBytes());
+        }
+        if ((selector_type == 1) || (selector_type == 2)) {
+            int ip_address_long = ip_prefix.address().toInt();
+            bb.put(toUint32(ip_address_long));
+        }
+        if (selector_type == 2) {
+            bb.put(toUint16(ip_prefix.prefixLength()));
+        }
+        if (drop != null)
+            bb.put(toUint8(drop));
+        if (rating_group != null)
+            bb.put(toUint32(rating_group));
+        if (service_ID != null)
+            bb.put(toUint32(service_ID));
+        if (sponsor_ID != null && (short) sponsor_ID.length() > 0) {
+            bb.put(toUint8((short) sponsor_ID.length()))
+                    .put(sponsor_ID.getBytes());
+        }
+        bb.put(toUint8(ZMQSBSubscriberManager.getControllerTopic()));
+
+        log.info("send_ADC_rules: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+}
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/package-info.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/package-info.java
new file mode 100644
index 0000000..45fe96c
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/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.
+ */
+
+/**
+ * FPC Agent.
+ */
+package org.onosproject.fpcagent;
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java
new file mode 100644
index 0000000..541d7f5
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java
@@ -0,0 +1,69 @@
+package org.onosproject.fpcagent.workers;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZContext;
+import org.zeromq.ZMQ;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.*;
+
+public class ZMQSBPublisherManager implements AutoCloseable {
+    private static final Logger log = LoggerFactory.getLogger(ZMQSBPublisherManager.class);
+    private static ZMQSBPublisherManager _instance = null;
+    private final ZContext ctx;
+    private final String address;
+    private final BlockingQueue<ByteBuffer> blockingQueue;
+    private final int poolSize;
+    private boolean run;
+
+    protected ZMQSBPublisherManager(String address, int poolSize) {
+        this.ctx = new ZContext();
+        this.address = address;
+        this.run = true;
+        this.blockingQueue = new LinkedBlockingQueue<>();
+        this.poolSize = poolSize;
+    }
+
+    public static ZMQSBPublisherManager createInstance(String address, int poolSize) {
+        if (_instance == null) {
+            _instance = new ZMQSBPublisherManager(address, poolSize);
+        }
+        return _instance;
+    }
+
+    public static ZMQSBPublisherManager getInstance() {
+        return _instance;
+    }
+
+    public void send(ByteBuffer buf) {
+        try {
+            blockingQueue.put(buf);
+        } catch (InterruptedException e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+    }
+
+    public void open() {
+        ExecutorService executorService = Executors.newFixedThreadPool(this.poolSize);
+        executorService.submit(() -> {
+            ZMQ.Socket socket = ctx.createSocket(ZMQ.PUB);
+            socket.connect(address);
+            log.debug("Publisher at {}", address);
+            while ((!Thread.currentThread().isInterrupted()) && run) {
+                try {
+                    byte[] array = blockingQueue.take().array();
+                    socket.send(array);
+                } catch (InterruptedException e) {
+                    log.error(ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+        });
+    }
+
+    @Override
+    public void close() {
+        run = false;
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java
new file mode 100644
index 0000000..f259883
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java
@@ -0,0 +1,320 @@
+package org.onosproject.fpcagent.workers;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onosproject.fpcagent.FpcUtil;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZContext;
+import org.zeromq.ZMQ;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadLocalRandom;
+
+import static org.onosproject.fpcagent.helpers.Converter.*;
+
+public class ZMQSBSubscriberManager implements AutoCloseable {
+    private static final Logger log = LoggerFactory.getLogger(ZMQSBSubscriberManager.class);
+    private static int MIN_TOPIC_VAL = 4;
+    private static int MAX_TOPIC_VAL = 255;
+    private static byte ASSIGN_ID = 0b0000_1010;
+    private static byte ASSIGN_CONFLICT = 0b0000_1011;
+    private static byte HELLO_REPLY = 0b0000_1101;
+    private static byte CONTROLLER_STATUS_INDICATION = 0b0000_1110;
+    private static byte HELLO = 0b0000_0001;
+    private static byte GOODBYE = 0b0000_0010;
+    private static ZMQSBSubscriberManager _instance = null;
+    private static Long controllerSourceId;
+    private static Short subscriberId;
+    private final String address;
+    private final Short broadcastAllId;
+    private final Short broadcastControllersId;
+    private final Short broadcastDpnsId;
+    private final String nodeId;
+    private final String networkId;
+    private boolean run;
+    private boolean conflictingTopic;
+    private Future<?> broadcastAllWorker;
+    private Future<?> broadcastControllersWorker;
+    private Future<?> broadcastTopicWorker;
+    private Future<?> generalWorker;
+
+    protected ZMQSBSubscriberManager(String address, String broadcastAllId, String broadcastControllersId,
+                                     String broadcastDpnsId, String nodeId, String networkId) {
+        this.address = address;
+        this.run = true;
+
+        this.nodeId = nodeId;
+        this.networkId = networkId;
+        this.broadcastAllId = Short.parseShort(broadcastAllId);
+        this.broadcastControllersId = Short.parseShort(broadcastControllersId);
+        this.broadcastDpnsId = Short.parseShort(broadcastDpnsId);
+
+        this.conflictingTopic = false;
+        controllerSourceId = (long) ThreadLocalRandom.current().nextInt(0, 65535);
+    }
+
+    public static ZMQSBSubscriberManager createInstance(String address, String broadcastAllId,
+                                                        String broadcastControllersId, String broadcastDpnsId,
+                                                        String nodeId, String networkId) {
+        if (_instance == null) {
+            _instance = new ZMQSBSubscriberManager(address, broadcastAllId, broadcastControllersId,
+                    broadcastDpnsId, nodeId, networkId);
+        }
+        return _instance;
+    }
+
+    public static ZMQSBSubscriberManager getInstance() {
+        return _instance;
+    }
+
+    public static Short getControllerTopic() {
+        return subscriberId;
+    }
+
+    public static Long getControllerSourceId() {
+        return controllerSourceId;
+    }
+
+    public void open() {
+        short subscriberId = (short) ThreadLocalRandom.current().nextInt(MIN_TOPIC_VAL, MAX_TOPIC_VAL + 1);
+
+        broadcastAllWorker = Executors.newSingleThreadExecutor()
+                .submit(new ZMQSubscriberWorker(broadcastAllId));
+
+        broadcastControllersWorker = Executors.newSingleThreadExecutor()
+                .submit(new ZMQSubscriberWorker(broadcastControllersId));
+
+        broadcastTopicWorker = Executors.newSingleThreadExecutor()
+                .submit(new BroadcastTopic(subscriberId));
+    }
+
+    @Override
+    public void close() {
+        run = false;
+    }
+
+    /**
+     * Interrupts the BroadcastTopicworker if there is an Assign topic Conflict
+     *
+     * @param conflict - Flag to indicate conflict
+     * @param subId    - Topic Id that caused the conflict
+     */
+    protected void BroadcastAllSubIdCallBack(boolean conflict, Short subId) {
+        if (conflict && subscriberId.equals(subId)) {
+            this.conflictingTopic = true;
+            broadcastTopicWorker.cancel(true);
+        }
+    }
+
+    /**
+     * Broadcasts the GOODBYE message to all the DPNs
+     */
+    public void sendGoodbyeToDpns() {
+        ByteBuffer bb = ByteBuffer.allocate(10 + nodeId.length() + networkId.length());
+        bb.put(toUint8(broadcastDpnsId))
+                .put(CONTROLLER_STATUS_INDICATION)
+                .put(toUint8(subscriberId))
+                .put(GOODBYE)
+                .put(toUint32(controllerSourceId))
+                .put(toUint8((short) nodeId.length()))
+                .put(nodeId.getBytes())
+                .put(toUint8((short) networkId.length()))
+                .put(networkId.getBytes());
+
+        log.info("sendGoodbyeToDpns: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Broadcasts an Assign Conflict message
+     *
+     * @param contents - byte array received over the southbound.
+     */
+    protected void SendAssignConflictMessage(byte[] contents) {
+        byte topic = contents[2];
+        short nodeIdLen = contents[7];
+        short networkIdLen = contents[8 + nodeIdLen];
+        String node_id = new String(Arrays.copyOfRange(contents, 8, 8 + nodeIdLen));
+        String network_id = new String(Arrays.copyOfRange(contents, 9 + nodeIdLen, 9 + nodeIdLen + networkIdLen));
+
+        if (toUint8(subscriberId) == topic || nodeId.equals(node_id) || networkId.equals(network_id)) {
+            ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length());
+            bb.put(toUint8(broadcastAllId))
+                    .put(ASSIGN_CONFLICT)
+                    .put(topic)
+                    .put(toUint32(controllerSourceId))
+                    .put(toUint8((short) nodeId.length()))
+                    .put(nodeId.getBytes())
+                    .put(toUint8((short) networkId.length()))
+                    .put(networkId.getBytes());
+
+            log.info("SendAssignConflictMessage: {}", bb.array());
+            ZMQSBPublisherManager.getInstance().send(bb);
+        }
+    }
+
+    protected class ZMQSubscriberWorker implements Runnable {
+        private final Short subscriberId;
+        private ZContext ctx;
+
+        ZMQSubscriberWorker(Short subscriberId) {
+            this.subscriberId = subscriberId;
+            this.ctx = new ZContext();
+        }
+
+        /**
+         * Sends a reply to a DPN Hello
+         *
+         * @param dpnStatus - DPN Status Indication message received from the DPN
+         */
+        protected void sendHelloReply(FpcUtil.DPNStatusIndication dpnStatus) {
+            if (FpcUtil.getTopicFromNode(dpnStatus.getKey()) != null) {
+                ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length())
+                        .put(toUint8(FpcUtil.getTopicFromNode(dpnStatus.getKey())))
+                        .put(HELLO_REPLY)
+                        .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+                        .put(toUint32(ZMQSBSubscriberManager.getControllerSourceId()))
+                        .put(toUint8((short) nodeId.length()))
+                        .put(nodeId.getBytes())
+                        .put(toUint8((short) networkId.length()))
+                        .put(networkId.getBytes());
+
+                log.info("sendHelloReply: {}", bb.array());
+                ZMQSBPublisherManager.getInstance().send(bb);
+            }
+        }
+
+        @Override
+        public void run() {
+            ZMQ.Socket subscriber = this.ctx.createSocket(ZMQ.SUB);
+            subscriber.connect(address);
+            subscriber.subscribe(new byte[]{toUint8(subscriberId)});
+            log.debug("Subscriber at {} / {}", address, subscriberId);
+            while ((!Thread.currentThread().isInterrupted()) && run) {
+                byte[] contents = subscriber.recv();
+                byte topic = contents[0];
+                byte messageType = contents[1];
+                log.debug("Received {}", contents);
+                switch (topic) {
+                    case 1:
+                        if (messageType == ASSIGN_CONFLICT && toInt(contents, 3) != controllerSourceId) {
+                            BroadcastAllSubIdCallBack(true, (short) contents[2]);
+                        } else if (messageType == ASSIGN_ID && toInt(contents, 3) != controllerSourceId) {
+                            SendAssignConflictMessage(contents);
+                        }
+                        break;
+                    default:
+                        Map.Entry<FpcDpnId, Object> entry = FpcUtil.decode(contents);
+                        if (entry != null) {
+                            if (entry.getValue() instanceof DownlinkDataNotification) {
+                                // TODO handle DL notification
+                            } else if (entry.getValue() instanceof FpcUtil.DPNStatusIndication) {
+                                FpcUtil.DPNStatusIndication dpnStatus = (FpcUtil.DPNStatusIndication) entry.getValue();
+                                if (dpnStatus.getStatus() == FpcUtil.DPNStatusIndication.Status.HELLO) {
+                                    sendHelloReply(dpnStatus);
+                                }
+                            }
+                        }
+                }
+            }
+            subscriber.disconnect(address);
+            subscriber.close();
+            ctx.destroySocket(subscriber);
+            try {
+                Thread.currentThread().join();
+            } catch (InterruptedException e) {
+                log.error(ExceptionUtils.getFullStackTrace(e));
+            }
+        }
+    }
+
+    /**
+     * Class to broadcast a topic for the controller
+     */
+    protected class BroadcastTopic implements Runnable {
+        private Short topic;
+
+        /**
+         * Constructor
+         *
+         * @param topic - Topic to broadcast
+         */
+        public BroadcastTopic(Short topic) {
+            this.topic = topic;
+        }
+
+        /**
+         * Broadcasts the topic
+         */
+        private void broadcastTopic() {
+            ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length());
+            bb.put(toUint8(broadcastAllId))
+                    .put(ASSIGN_ID)
+                    .put(toUint8(this.topic))
+                    .put(toUint32(controllerSourceId))
+                    .put(toUint8((short) nodeId.length()))
+                    .put(nodeId.getBytes())
+                    .put(toUint8((short) networkId.length()))
+                    .put(networkId.getBytes());
+
+            log.info("broadcastTopic: {}", bb.array());
+            ZMQSBPublisherManager.getInstance().send(bb);
+        }
+
+        /**
+         * Broadcasts the HELLO message to all the DPNs
+         */
+        private void sendHelloToDpns() {
+            ByteBuffer bb = ByteBuffer.allocate(10 + nodeId.length() + networkId.length());
+            bb.put(toUint8(broadcastDpnsId))
+                    .put(CONTROLLER_STATUS_INDICATION)
+                    .put(toUint8(subscriberId))
+                    .put(HELLO)
+                    .put(toUint32(controllerSourceId))
+                    .put(toUint8((short) nodeId.length()))
+                    .put(nodeId.getBytes())
+                    .put(toUint8((short) networkId.length()))
+                    .put(networkId.getBytes());
+
+
+            log.info("sendHelloToDpns: {}", bb.array());
+            ZMQSBPublisherManager.getInstance().send(bb);
+        }
+
+        @Override
+        public void run() {
+            try {
+                this.broadcastTopic();
+                log.debug("Thread sleeping: " + Thread.currentThread().getName());
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                if (conflictingTopic) {
+                    conflictingTopic = false;
+                    this.topic = (short) ThreadLocalRandom.current().nextInt(MIN_TOPIC_VAL, MAX_TOPIC_VAL + 1);
+                    subscriberId = this.topic;
+                    this.run();
+                    return;
+                } else {
+                    log.error(ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+            subscriberId = this.topic;
+            log.info("Topic Id: " + this.topic);
+            generalWorker = Executors.newSingleThreadExecutor().submit(new ZMQSubscriberWorker(this.topic));
+
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                log.error(ExceptionUtils.getFullStackTrace(e));
+            }
+            sendHelloToDpns();
+        }
+
+    }
+}
diff --git a/models/fpcagent/BUCK b/models/fpcagent/BUCK
new file mode 100644
index 0000000..70f780a
--- /dev/null
+++ b/models/fpcagent/BUCK
@@ -0,0 +1,16 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//models/common:onos-models-common',
+]
+
+APPS = [
+    'org.onosproject.models.common',
+]
+
+yang_model(
+    app_name = 'org.onosproject.models.fpcagent',
+    title = 'FPC Agent YANG Models',
+    custom_registrator = True,
+    deps = COMPILE_DEPS,
+    required_apps = APPS,
+)
diff --git a/models/fpcagent/pom.xml b/models/fpcagent/pom.xml
new file mode 100644
index 0000000..a82844e
--- /dev/null
+++ b/models/fpcagent/pom.xml
@@ -0,0 +1,165 @@
+<?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.onosproject</groupId>
+        <artifactId>onos-models</artifactId>
+        <version>1.13.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>onos-models-fpcagent</artifactId>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <onos.app.name>org.onosproject.models.fpcagent</onos.app.name>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-model</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-models-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-apps-yang</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions combine.children="append">
+                        <Include-Resource>yang/resources/YangMetaData.ser=target/classes/yang/resources/YangMetaData.ser</Include-Resource>
+                    </instructions>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.onosproject</groupId>
+                <artifactId>onos-yang-compiler-maven-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.onosproject</groupId>
+                <artifactId>onos-maven-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>3.0.0</version>
+                <executions>
+                  <execution>
+                    <id>add-source</id>
+                    <phase>generate-sources</phase>
+                    <goals>
+                      <goal>add-source</goal>
+                    </goals>
+                    <configuration>
+                      <sources>
+                        <source>${project.build.directory}/generated-sources</source>
+                      </sources>
+                    </configuration>
+                  </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-clean-plugin</artifactId>
+                <version>3.0.0</version>
+                <executions>
+                    <execution>
+                        <id>onos-yang-plugin-workaround</id>
+                        <!-- yang plugin cannot handle non-clean compilation -->
+                        <phase>initialize</phase>
+                        <goals>
+                            <goal>clean</goal>
+                        </goals>
+                        <configuration>
+                            <excludeDefaultDirectories>true</excludeDefaultDirectories>
+                            <filesets>
+                                <fileset>
+                                    <directory>target/generated-sources</directory>
+                                </fileset>
+                            </filesets>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+
+        </plugins>
+
+        <pluginManagement>
+            <plugins>
+                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            org.apache.maven.plugins
+                                        </groupId>
+                                        <artifactId>
+                                            maven-clean-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [3.0.0,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>clean</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+</project>
diff --git a/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/FpcAgentModelRegistrator.java b/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/FpcAgentModelRegistrator.java
new file mode 100644
index 0000000..64ea413
--- /dev/null
+++ b/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/FpcAgentModelRegistrator.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.onosproject.models.fpcagent;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.yang.AbstractYangModelRegistrator;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.FpcService;
+import org.onosproject.yang.gen.v1.fpcconfig.rev20160927.FpcConfig;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.IetfDmmFpcagent;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.IetfDmmFpcbase;
+import org.onosproject.yang.gen.v1.ietfdmmfpcpmip.rev20160119.IetfDmmFpcPmip;
+import org.onosproject.yang.gen.v1.ietfdmmfpcpolicyext.rev20160803.IetfDmmFpcPolicyext;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.IetfDmmThreegpp;
+import org.onosproject.yang.gen.v1.ietfpmipqos.rev20160210.IetfPmipQos;
+import org.onosproject.yang.gen.v1.ietftrafficselectortypes.rev20160114.IetfTrafficSelectorTypes;
+import org.onosproject.yang.model.DefaultYangModuleId;
+import org.onosproject.yang.model.YangModuleId;
+import org.onosproject.yang.runtime.AppModuleInfo;
+import org.onosproject.yang.runtime.DefaultAppModuleInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component(immediate = true)
+public class FpcAgentModelRegistrator extends AbstractYangModelRegistrator {
+    static final Logger log = LoggerFactory.getLogger(FpcAgentModelRegistrator.class);
+
+    public FpcAgentModelRegistrator() {
+        super(FpcAgentModelRegistrator.class, getAppInfo());
+    }
+
+    private static Map<YangModuleId, AppModuleInfo> getAppInfo() {
+        Map<YangModuleId, AppModuleInfo> appInfo = new HashMap<>();
+        appInfo.put(new DefaultYangModuleId("ietf-dmm-fpcagent", "2016-08-03"),
+                new DefaultAppModuleInfo(IetfDmmFpcagent.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-dmm-fpcbase", "2016-08-03"),
+                new DefaultAppModuleInfo(IetfDmmFpcbase.class, null));
+        appInfo.put(new DefaultYangModuleId("fpc", "2015-01-05"),
+                new DefaultAppModuleInfo(FpcService.class, null));
+        appInfo.put(new DefaultYangModuleId("fpc-config", "2016-09-27"),
+                new DefaultAppModuleInfo(FpcConfig.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-dmm-fpc-pmip", "2016-01-19"),
+                new DefaultAppModuleInfo(IetfDmmFpcPmip.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-dmm-fpc-policyext", "2016-08-03"),
+                new DefaultAppModuleInfo(IetfDmmFpcPolicyext.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-dmm-threegpp", "2016-08-03"),
+                new DefaultAppModuleInfo(IetfDmmThreegpp.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-pmip-qos", "2016-02-10"),
+                new DefaultAppModuleInfo(IetfPmipQos.class, null));
+        appInfo.put(new DefaultYangModuleId("ietf-traffic-selector-types", "2016-01-14"),
+                new DefaultAppModuleInfo(IetfTrafficSelectorTypes.class, null));
+
+        return ImmutableMap.copyOf(appInfo);
+    }
+}
diff --git a/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/package-info.java b/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/package-info.java
new file mode 100644
index 0000000..3a46d78
--- /dev/null
+++ b/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/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.
+ */
+
+/**
+ * FPC Agent YANG models.
+ */
+package org.onosproject.models.fpcagent;
\ No newline at end of file
diff --git a/models/fpcagent/src/main/yang/fpc-config.yang b/models/fpcagent/src/main/yang/fpc-config.yang
new file mode 100644
index 0000000..9e28370
--- /dev/null
+++ b/models/fpcagent/src/main/yang/fpc-config.yang
@@ -0,0 +1,106 @@
+module fpc-config {
+    yang-version 1;
+    namespace "urn:onos:fpc:config";
+    prefix fpc-config;
+
+    description
+      "Configuration for ...";
+
+    revision "2016-09-27" {
+        description
+            "Initial revision.";
+    }
+
+    container fpc-config {
+    	leaf use-memcached {
+    	  type boolean;
+    	}
+    	leaf memcached-uri {
+    	  type string;
+    	}
+    	leaf memcached-threads {
+    	  type uint16;
+    	}
+        leaf scheduled-monitors-poolsize {
+          type uint16;
+        }
+        leaf monitor-threads  {
+          type uint16;
+        }
+        leaf dpn-listener-uri {
+          type string;
+        }
+        leaf dpn-listener-id {
+          type string;
+        }
+        leaf dpn-client-uri {
+          type string;
+        }
+        leaf dpn-message-processor-threads{
+          type uint16;
+        }
+        leaf dpn-client-threads {
+          type uint16;
+        }
+        leaf metricsupdate-ms {
+          type uint32;
+        }
+        leaf mobilityupdate-ms {
+          type uint32;
+        }
+        leaf node-id {
+          type string;
+        }
+        leaf network-id {
+          type string;
+        }
+        leaf activation-threads {
+          type uint16;
+        }
+        leaf target-read-limit {
+          type uint16;
+        }
+        leaf default-tenant-id {
+          type string;
+        }
+        leaf default-group-id {
+          type string;
+        }
+        leaf prefers-fast-clients {
+          type boolean;
+        }
+        leaf http-notifier-clients {
+          type uint16;
+        }
+        leaf zmq-nbi-server-poolsize {
+          type uint16;
+        }
+        leaf zmq-nbi-server-uri {
+          type string;
+        }
+        leaf zmq-nbi-inproc-uri {
+          type string;
+        }
+        leaf zmq-nbi-handler-poolsize {
+          type uint16;
+        }
+        leaf zmq-broadcast-all {
+       	  type string;
+       	}
+       	leaf zmq-broadcast-controllers {
+       	  type string;
+       	}
+       	leaf zmq-broadcast-dpns {
+       	  type string;
+       	}
+        leaf http-nio2-nb-poolsize {
+          type uint16;
+        }
+        leaf http-nio2-nb-port {
+          type uint16;
+        }
+        leaf max-trans-rate {
+          type uint16;
+        }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/fpc.yang b/models/fpcagent/src/main/yang/fpc.yang
new file mode 100644
index 0000000..2996283
--- /dev/null
+++ b/models/fpcagent/src/main/yang/fpc.yang
@@ -0,0 +1,169 @@
+module fpc {
+    yang-version 1;
+    namespace "urn:onos:params:xml:ns:yang:fpc";
+    prefix "fpc";
+
+    import ietf-dmm-fpcagent { prefix fpcagent; }
+    import ietf-dmm-fpcbase { prefix fpcbase; }
+    import ietf-inet-types { prefix inet; }
+    import ietf-dmm-fpc-pmip { prefix fpc-pmip; }
+    import ietf-dmm-threegpp { prefix threegpp; }
+
+    revision "2015-01-05" {
+        description "Initial revision of fpc model";
+    }
+
+   // grouping zmq-dpn-config {
+   //   leaf topic {
+   //     type string;
+  //    }
+   // }
+
+   // augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-topology/fpcagent:dpns" {
+  //    uses zmq-dpn-config;
+   // }
+
+    // New DPN Type
+    identity zmq-dpn-control-protocol {
+      base "fpcbase:fpc-dpn-control-protocol";
+    }
+
+    typedef membership-match-type {
+      type enumeration {
+        enum eq { value 0; }
+        enum super { value 1; }
+        enum psuper { value 2; }
+        enum sub { value 3; }
+        enum psub { value 4; }
+        enum overlap { value 5; }
+        enum nonoverlap { value 6; }
+      }
+    }
+
+    grouping membership-value {
+      leaf policy-membership {
+        type string;
+      }
+    }
+
+    augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-policy/fpcagent:descriptors/fpcagent:descriptor-value" {
+      case tft-plusplus {
+          uses fpc:membership-value;
+          leaf membership-match-type {
+            type fpc:membership-match-type;
+          }
+      }
+    }
+
+    augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-mobility/fpcagent:contexts" {
+      uses fpc:membership-value;
+    }
+    augment "/fpcagent:configure/fpcagent:input/fpcagent:op_body/fpcagent:create_or_update/fpcagent:contexts" {
+      uses fpc:membership-value;
+    }
+    augment "/fpcagent:configure-bundles/fpcagent:input/fpcagent:bundles/fpcagent:op_body/fpcagent:create_or_update/fpcagent:contexts" {
+       uses fpc:membership-value;
+    }
+    augment "/fpcagent:configure/fpcagent:output/fpcagent:result-type/fpcagent:common-success/fpcagent:contexts" {
+       uses fpc:membership-value;
+    }
+    augment "/fpcagent:configure-bundles/fpcagent:output/fpcagent:bundles/fpcagent:result-type/fpcagent:common-success/fpcagent:contexts" {
+       uses fpc:membership-value;
+    }
+    // TODO - Add Notification Augments for membership-value
+
+      container tx-stats {
+        config false;
+        leaf last-ts {
+          type string;
+        }
+        leaf total-txs {
+          type uint64;
+        }
+        list states {
+          key state;
+          leaf state {
+            type string;
+          }
+          leaf entries {
+            type uint64;
+          }
+          container total-time {
+            leaf mantissa {
+              type uint64;
+            }
+            leaf exponent {
+              type int32;
+            }
+          }
+          container average-time {
+            leaf mantissa {
+              type uint64;
+            }
+            leaf exponent {
+              type int32;
+            }
+          }
+        }
+      }
+
+    grouping connection-config {
+        leaf client-id {
+          type fpcagent:client-identifier;
+        }
+        leaf tenant-id {
+          type fpcbase:fpc-identity;
+        }
+        leaf-list supported-features {
+          type string;
+        }
+        leaf endpoint-uri {
+          type inet:uri;
+        }
+        leaf supports-oknotify-model {
+          type boolean;
+        }
+        leaf supports-ack-model {
+          type boolean;
+        }
+    }
+
+
+    container connection-info {
+      list connections {
+          config false;
+          key client-id;
+          leaf client-id {
+            type string;
+          }
+          container requested-info {
+            uses fpc:connection-config;
+          }
+          container assigned-info {
+            uses fpc:connection-config;
+          }
+      }
+    }
+
+    rpc register-client {
+      input {
+        uses fpc:connection-config;
+      }
+      output {
+        uses fpc:connection-config;
+      }
+    }
+
+    rpc deregister-client {
+      input {
+        leaf client-id {
+          type fpcagent:client-identifier;
+        }
+      }
+      output {
+      	leaf client-id {
+          type fpcagent:client-identifier;
+        }
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang
new file mode 100644
index 0000000..c44aaab
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang
@@ -0,0 +1,71 @@
+module ietf-dmm-fpc-pmip {
+    namespace "urn:ietf:params:xml:ns:yang:ietf-dmm-fpc-pmip";
+    prefix fpc-pmip;
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     Forwarding Policy Configuration Protocol.(FPCP)";
+
+    revision 2016-01-19 {
+        description "Changes based on -01 version of FPCP draft.";
+        reference "draft-ietf-dmm-fpc-cpdp-01";
+    }
+
+    identity pmip-tunnel-type {
+        description "PMIP Tunnel Type";
+    }
+    identity grev1 {
+        base "fpc-pmip:pmip-tunnel-type";
+    }
+    identity grev2 {
+        base "fpc-pmip:pmip-tunnel-type";
+    }
+    identity ipinip {
+        base "fpc-pmip:pmip-tunnel-type";
+    }
+    grouping pmip-mobility {
+        leaf type {
+            type identityref {
+                base "fpc-pmip:pmip-tunnel-type";
+            }
+        }
+        choice value {
+            case gre {
+                leaf key {
+                    type uint32;
+                    description "GRE_KEY";
+                }
+            }
+        }
+    }
+
+    typedef pmip-instr {
+      description "Instruction Set for PMIP";
+      type bits {
+        bit assign-ip {
+          position 0;
+        }
+        bit assign-dpn {
+          position 1;
+        }
+        bit session {
+          position 2;
+        }
+        bit uplink {
+          position 3;
+        }
+        bit downlink {
+          position 4;
+        }
+      }
+    }
+
+    grouping pmip-commandset {
+      leaf instr-pmip-mob {
+        type fpc-pmip:pmip-instr;
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang
new file mode 100644
index 0000000..3845591
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang
@@ -0,0 +1,95 @@
+module ietf-dmm-fpc-policyext {
+    namespace "urn:ietf:params:xml:ns:yang:fpcpolicyext";
+    prefix fpcpolicyext;
+
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     Forwarding Policy Configuration Protocol (FPCP)
+     common Policy Action and Descriptor extensions";
+
+    revision 2016-08-03 {
+        description "Changes based on -04 version of FPC draft.";
+        reference "draft-ietf-dmm-fpc-cpdp-04";
+    }
+
+    grouping simple-nat {
+      leaf outbound-nat-address {
+        type inet:ip-address;
+      }
+    }
+
+    grouping simple-napt {
+      leaf source-port {
+        type inet:port-number;
+      }
+      leaf outbound-napt-address {
+        type inet:ip-address;
+      }
+      leaf destination-port {
+        type inet:port-number;
+      }
+    }
+
+    grouping prefix-traffic-descriptor {
+        description
+        "Traffic descriptor group collects parameters to
+         identify target traffic flow.  It represents
+         source/destination as IP prefixes";
+
+        leaf destination-ip {
+            type inet:ip-prefix;
+            description "Rule of destination IP";
+        }
+        leaf source-ip {
+            type inet:ip-prefix;
+            description "Rule of source IP";
+        }
+    }
+
+    grouping rating-action {
+      description "Rudimentary rating action applied based upon RFC 4006 attributes";
+      leaf service-context-id {
+        type string;
+        description "Per RFC 4006 - Contains a unique identifier of the Diameter credit-control service
+           specific document that applies to the request.  The format of the Service-Context-Id is:
+
+           <service-context>@<domain>
+
+           service-context = Token
+
+         The Token is an arbitrary string of characters and digits.
+
+         'domain' represents the entity that allocated the Service-Context-Id.";
+      }
+      leaf service-identifier {
+        type uint32;
+        description "From RFC 4006 - Contains the identifier of a service.  The specific service the
+           request relates to is uniquely identified by the combination of
+           Service-Context-Id and Service-Identifier AVPs.";
+      }
+      leaf rating-group {
+        type uint32;
+        description "From RFC 4006 - Contains the identifier of a rating group.  All the services subject
+           to the same rating type are part of the same rating group.  The
+           specific rating group the request relates to is uniquely identified
+           by the combination of Service-Context-Id and Rating-Group AVPs.";
+      }
+    }
+
+    grouping domain-descriptor-list {
+      description "Descriptors for list of domains";
+      leaf-list source-domains {
+          type inet:domain-name;
+          description "Source Domain Names";
+      }
+      leaf-list destination-domains {
+          type inet:domain-name;
+          description "Destination Domain Names";
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang
new file mode 100644
index 0000000..1e5a7fc
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang
@@ -0,0 +1,663 @@
+module ietf-dmm-fpcagent {
+    namespace "urn:ietf:params:xml:ns:yang:fpcagent";
+    prefix fpcagent;
+
+    import ietf-dmm-fpcbase { prefix fpcbase; revision-date 2016-08-03; }
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+    import ietf-dmm-fpc-pmip { prefix fpc-pmip; revision-date 2016-01-19; }
+    import ietf-dmm-threegpp { prefix threegpp; }
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     Forwarding Policy Configuration Protocol.(FPCP)";
+
+    revision 2016-08-03 {
+        description "Changes based on -04 version of FPC draft.";
+        reference "draft-ietf-dmm-fpc-cpdp-04";
+    }
+    feature fpc-cloning {
+      description "An ability to support cloning in the RPC.";
+    }
+    feature fpc-basename-registry {
+      description "Ability to track Base Names already provisioned on the Agent";
+    }
+    feature fpc-bundles {
+      description "Ability for Client to send multiple bundles of actions to
+        an Agent";
+    }
+    feature fpc-client-binding {
+      description "Allows a FPC Client to bind a DPN to an Topology Object";
+    }
+    feature fpc-auto-binding {
+      description "Allows a FPC Agent to advertise Topology Objects that could be DPNs";
+    }
+    feature instruction-bitset {
+      description "Allows the expression of instructions (bit sets) over FPC.";
+    }
+    feature operation-ref-scope {
+      description "Provides the scope of refeneces in an operation.  Used to optmize
+        the Agent processing.";
+    }
+
+    typedef agent-identifier {
+        type fpcbase:fpc-identity;
+    }
+
+    typedef client-identifier {
+        type fpcbase:fpc-identity;
+    }
+
+    grouping basename-info {
+          leaf basename {
+            if-feature fpcagent:fpc-basename-registry;
+            description "Rules Basename";
+            type fpcbase:fpc-identity;
+          }
+          leaf base-state {
+            if-feature fpcagent:fpc-basename-registry;
+            type string;
+          }
+          leaf base-checkpoint {
+            if-feature fpcagent:fpc-basename-registry;
+            type string;
+          }
+    }
+
+    // Top Level Structures
+    container tenants {
+        description "";
+
+        list tenant {
+            description "";
+            key "tenant-id";
+            leaf tenant-id {
+                type fpcbase:fpc-identity;
+            }
+
+            container fpc-policy {
+              list policy-groups {
+                  key "policy-group-id";
+                  uses fpcbase:fpc-policy-group;
+              }
+              list policies {
+                  key "policy-id";
+                  uses fpcbase:fpc-policy;
+              }
+              list descriptors {
+                key descriptor-id;
+                uses fpcbase:fpc-descriptor;
+              }
+              list actions {
+                  key action-id;
+                  uses fpcbase:fpc-action;
+              }
+            }
+
+            container fpc-mobility {
+              config false;
+              list contexts {
+                  key context-id;
+                  uses fpcbase:fpc-context;
+              }
+              list ports {
+                  key port-id;
+                  uses fpcbase:fpc-port;
+              }
+              list monitors {
+                  key monitor-id;
+                  uses fpcbase:monitor-config;
+              }
+            }
+            container fpc-topology {
+              // Basic Agent Topology Structures
+              list domains {
+                key domain-id;
+                uses fpcbase:fpc-domain;
+                uses fpcagent:basename-info;
+              }
+
+              list dpn-group-peers {
+                  if-feature fpcbase:fpc-basic-agent;
+                  key "remote-dpn-group-id";
+                  uses fpcbase:fpc-dpn-peer-group;
+              }
+              leaf topology-dpn-id {
+                if-feature fpcbase:fpc-basic-agent;
+                type fpcbase:fpc-dpn-id;
+              }
+              leaf-list control-protocols {
+                if-feature fpcbase:fpc-basic-agent;
+                type identityref {
+                  base "fpcbase:fpc-dpn-control-protocol";
+                }
+              }
+
+              list dpn-groups {
+                  if-feature fpcbase:fpc-multi-dpn;
+                  key dpn-group-id;
+                  uses fpcagent:fpc-dpn-group;
+                  list domains {
+                    key domain-id;
+                    uses fpcbase:fpc-domain;
+                    uses fpcagent:basename-info;
+                  }
+              }
+              list dpns {
+                  if-feature fpcbase:fpc-multi-dpn;
+                  key dpn-id;
+                  uses fpcbase:fpc-dpn;
+              }
+            }
+
+        }
+    }
+
+    container fpc-agent-info {
+      // General Agent Structures
+      leaf-list supported-features {
+        type string;
+      }
+
+      // Common Agent Info
+      list supported-events {
+        key event;
+        leaf event {
+          type identityref {
+            base "fpcbase:event-type";
+          }
+        }
+        leaf event-id {
+          type fpcbase:event-type-id;
+        }
+      }
+
+      list supported-error-types {
+        key error-type;
+        leaf error-type {
+          type identityref {
+            base "fpcagent:error-type";
+          }
+        }
+        leaf error-type-id {
+          type fpcagent:error-type-id;
+        }
+      }
+    }
+
+
+    // Multi-DPN Agent Structures
+    grouping fpc-dpn-group {
+        leaf dpn-group-id {
+            type fpcbase:fpc-dpn-group-id;
+        }
+        leaf data-plane-role {
+            type identityref {
+                base "fpcbase:fpc-forwaridingplane-role";
+            }
+        }
+        leaf access-type {
+            type identityref {
+                base "fpcbase:fpc-access-type";
+            }
+        }
+        leaf mobility-profile {
+            type identityref {
+                base "fpcbase:fpc-mobility-profile-type";
+            }
+        }
+        list dpn-group-peers {
+            key "remote-dpn-group-id";
+            uses fpcbase:fpc-dpn-peer-group;
+        }
+    }
+
+
+    // RPC
+    // RPC Specific Structures
+    //Input Structures
+    typedef admin-status {
+        type enumeration {
+            enum enabled { value 0; }
+            enum disabled { value 1; }
+            enum virtual { value 2; }
+        }
+    }
+
+    typedef session-status {
+        type enumeration {
+            enum complete { value 0; }
+            enum incomplete { value 1; }
+            enum outdated { value 2; }
+        }
+    }
+
+    typedef op-delay {
+        type uint32;
+    }
+
+    typedef op-identifier {
+        type uint64;
+    }
+
+    typedef ref-scope {
+      description "Search scope for references in the operation.
+        op - All references are contained in the operation body (intra-op)
+        bundle - All references in exist in bundle (inter-operation/intra-bundle).
+          NOTE - If this value comes in CONFIG call it is equivalen to 'op'.
+        storage - One or more references exist outside of the operation and bundle.
+          A lookup to a cache / storage is required.
+        unknown - the location of the references are unknown.  This is treated as
+          a 'storage' type.";
+      type enumeration {
+        enum none { value 0; }
+        enum op { value 1; }
+        enum bundle { value 2; }
+        enum storage { value 3; }
+        enum unknown { value 4; }
+      }
+    }
+
+    grouping instructions {
+      container instructions {
+        if-feature instruction-bitset;
+        choice instr-type {
+          case pmip-instr {
+            uses fpc-pmip:pmip-commandset;
+          }
+          case instr-3gpp-mob {
+            uses threegpp:threegpp-commandset;
+          }
+        }
+      }
+    }
+
+    grouping op-header {
+      leaf client-id {
+        type fpcagent:client-identifier;
+      }
+      leaf delay {
+        type op-delay;
+      }
+      leaf session-state {
+        type session-status;
+      }
+      leaf admin-state {
+        type admin-status;
+      }
+      leaf op-type {
+        type enumeration {
+          enum create { value 0; }
+          enum update { value 1; }
+          enum query { value 2; }
+          enum delete { value 3; }
+        }
+      }
+      leaf op-ref-scope {
+          if-feature operation-ref-scope;
+          type fpcagent:ref-scope;
+      }
+      uses fpcagent:instructions;
+    }
+
+    grouping clone-ref {
+      leaf entity {
+        type fpcbase:fpc-identity;
+      }
+      leaf source {
+        type fpcbase:fpc-identity;
+      }
+    }
+
+    identity command-set {
+      description "protocol specific commands";
+    }
+
+    grouping context-operation {
+      uses fpcbase:fpc-context;
+      uses fpcagent:instructions;
+    }
+
+    grouping port-operation {
+      uses fpcbase:fpc-port;
+      uses fpcagent:instructions;
+    }
+
+    // Output Structure
+    grouping payload {
+      list ports {
+        uses fpcagent:port-operation;
+      }
+      list contexts {
+        uses fpcagent:context-operation;
+      }
+    }
+
+    grouping op-input {
+      uses fpcagent:op-header;
+      leaf op-id {
+        type op-identifier;
+      }
+      choice op_body {
+        case create_or_update {
+          list clones {
+            if-feature fpc-cloning;
+            key entity;
+            uses fpcagent:clone-ref;
+          }
+          uses fpcagent:payload;
+        }
+        case delete_or_query {
+          uses fpcbase:targets-value;
+        }
+      }
+    }
+
+    typedef result {
+      type enumeration {
+        enum ok { value 0; }
+        enum err { value 1; }
+        enum ok-notify-follows { value 2; }
+      }
+    }
+
+    identity error-type {
+      description "Base Error Type";
+    }
+    identity name-already-exists {
+      description "Notification that an entity of the same name already exists";
+    }
+
+    typedef error-type-id {
+      description "Integer form of the Error Type";
+      type uint32;
+    }
+
+    grouping op-status-value {
+      leaf op-status {
+        type enumeration {
+          enum ok { value 0; }
+          enum err { value 1; }
+        }
+      }
+    }
+
+    grouping result-body {
+      leaf op-id {
+        type op-identifier;
+      }
+      leaf result {
+        type result;
+      }
+      choice result-type {
+        case err {
+          leaf error-type-id {
+            type fpcagent:error-type-id;
+          }
+          leaf error-info {
+            type string {
+              length "1..1024";
+            }
+          }
+        }
+        case common-success {
+          uses fpcagent:payload;
+        }
+        case delete-success {
+          uses fpcbase:targets-value;
+        }
+        case empty-case {
+        }
+      }
+    }
+
+    grouping result-body-dpn {
+      leaf result {
+        type result;      }
+      choice result-type {
+        case err {
+          leaf error-type-id {
+            type fpcagent:error-type-id;
+          }
+          leaf error-info {
+            type string {
+              length "1..1024";
+            }
+          }
+        }
+        case common-delete-success {
+          uses fpcbase:fpc-dpn;
+        }
+        case empty-case {
+        }
+      }
+    }
+
+    typedef dpn-operation {
+        type enumeration {
+            enum add { value 0; }
+            enum remove { value 1; }
+        }
+    }
+
+    grouping dpn-input {
+      leaf abstract-dpn-id {
+        type fpcbase:fpc-dpn-id;
+      }
+      leaf input-dpn-id {
+        type fpcbase:fpc-dpn-id;
+      }
+      leaf operation {
+        type fpcagent:dpn-operation;
+      }
+    }
+
+    // Common RPCs
+    rpc configure-dpn {
+      input {
+        uses fpcagent:dpn-input;
+      }
+      output {
+        uses fpcagent:result-body-dpn;
+      }
+    }
+
+    rpc configure {
+      input {
+        uses fpcagent:op-input;
+      }
+      output {
+        uses fpcagent:result-body;
+      }
+    }
+
+    rpc configure-bundles {
+      if-feature fpcagent:fpc-bundles;
+      input {
+        leaf client-id {
+          type fpcagent:client-identifier;
+        }
+        leaf highest-op-ref-scope {
+            if-feature operation-ref-scope;
+            type fpcagent:ref-scope;
+        }
+        list bundles {
+          key op-id;
+          uses fpcagent:op-input;
+        }
+      }
+      output {
+        list bundles {
+          key op-id;
+          uses fpcagent:result-body;
+        }
+      }
+    }
+
+    // Notification Messages & Structures
+    typedef notification-id {
+      type uint32;
+    }
+
+    grouping notification-header {
+      leaf notification-id {
+          type fpcagent:notification-id;
+      }
+      leaf timestamp {
+          type uint64;
+      }
+    }
+    
+    grouping cause-values {
+      leaf cause-value {
+        type uint32;
+      }
+    }
+
+    notification config-result-notification {
+      uses fpcagent:notification-header;
+      choice value {
+        case config-result {
+          uses fpcagent:op-status-value;
+          uses fpcagent:cause-values;
+          uses fpcagent:result-body;
+        }
+        case config-bundle-result {
+          list bundles {
+            uses fpcagent:op-status-value;
+            uses fpcagent:cause-values;
+            uses fpcagent:result-body;
+          }
+        }
+      }
+    }
+
+    rpc event_register {
+        description "Used to register monitoring of parameters/events";
+        input {
+          uses fpcbase:monitor-config;
+          leaf client-id {
+            type fpcagent:client-identifier;
+          }
+        }
+        output {
+          leaf monitor-result {
+            type fpcagent:result;
+          }
+        }
+    }
+
+    rpc event_deregister {
+        description "Used to de-register monitoring of parameters/events";
+        input {
+          list monitors {
+            uses fpcbase:monitor-id;
+          }
+          leaf client-id {
+            type fpcagent:client-identifier;
+          }
+        }
+        output {
+          leaf monitor-result {
+            type fpcagent:result;
+          }
+        }
+    }
+
+    rpc probe {
+        description "Probe the status of a registered monitor";
+        input {
+          uses fpcbase:targets-value;
+          leaf client-id {
+            type fpcagent:client-identifier;
+          }
+        }
+        output {
+          leaf monitor-result {
+            type fpcagent:result;
+          }
+        }
+    }
+    
+   grouping dpn-status-value {
+      leaf dpn-status {
+        type enumeration {
+          enum available { value 0; }
+          enum unavailable { value 1; }
+        }
+      }
+    }
+
+    notification notify {
+        uses fpcagent:notification-header;
+        choice value {
+            case dpn-candidate-available {
+              if-feature fpcagent:fpc-auto-binding;
+              leaf candidate-node-id {
+                type inet:uri;
+              }
+              leaf-list access-types {
+                type identityref {
+                  base "fpcbase:fpc-access-type";
+                }
+              }
+              leaf-list mobility-profiles {
+                type identityref {
+                  base "fpcbase:fpc-mobility-profile-type";
+                }
+              }
+              leaf-list forwarding-plane-roles {
+                type identityref {
+                  base "fpcbase:fpc-forwaridingplane-role";
+                }
+              }
+            }
+            
+            case dpn-availability {
+              leaf availability-message-type {
+                type string;
+              }
+              uses fpcagent:dpn-status-value;
+              leaf load {
+              	description "A percentage value (between 0 and 100) of the system load.  This is a combined measurement.";
+              	type int8;
+              }
+              uses fpcbase:fpc-dpn;
+            }
+            
+            case monitor-notification {
+              choice monitor-notification-value {
+                case simple-monitor {
+                  uses fpcbase:report;
+                }
+                case bulk-monitors {
+                  list reports {
+                    uses fpcbase:report;
+                  }
+                }
+              }
+            }
+            // Added as part of the augment issue
+            // TODO - Remove once resolved
+            case downlink-data-notification {
+              leaf notification-message-type {
+                type string;
+              }
+              leaf notification-dpn-id {
+                type fpcbase:fpc-dpn-id;
+              }
+              leaf session-id {
+                type uint64;
+              }
+              leaf client-id {
+              	type fpcagent:client-identifier;
+              }
+              leaf op-id {
+              	type fpcagent:op-identifier;
+              }
+            }
+        }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
new file mode 100644
index 0000000..8785850
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
@@ -0,0 +1,706 @@
+module ietf-dmm-fpcbase {
+    namespace "urn:ietf:params:xml:ns:yang:fpcbase";
+    prefix fpcbase;
+
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+    import ietf-dmm-fpc-pmip { prefix fpc-pmip; revision-date 2016-01-19; }
+    import ietf-traffic-selector-types { prefix traffic-selectors; }
+    import ietf-dmm-fpc-policyext { prefix fpcpolicyext; }
+    import ietf-dmm-threegpp { prefix threegpp; }
+    import ietf-pmip-qos { prefix qos-pmip; }
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     Forwarding Policy Configuration Protocol.(FPCP)";
+
+    revision 2016-08-03 {
+        description "Changes based on -04 version of FPC draft.";
+        reference "draft-ietf-dmm-fpc-cpdp-04";
+    }
+
+    feature fpc-basic-agent {
+        description "This is an agent co-located with a DPN.  In this case
+        only DPN Peer Groups, the DPN Id and Control Protocols are exposed
+        along with the core structures.";
+    }
+    feature fpc-multi-dpn {
+        description "The agent supports multiple DPNs.";
+    }
+    
+    typedef fpc-identity {
+        type union {
+            type int64;
+            type string;
+        }
+    }
+
+    grouping target-value {
+      leaf target {
+          type fpc-identity;
+      }
+    }
+
+    grouping targets-value {
+      list targets {
+          key "target";
+          leaf target {
+            type fpc-identity;
+          }
+          leaf-list dpn-id {
+                type fpcbase:fpc-dpn-id;
+          }
+      }
+    }
+
+    // Descriptor Structure
+    typedef fpc-descriptor-id-type {
+        type fpcbase:fpc-identity;
+        description "Descriptor-ID";
+    }
+    identity fpc-descriptor-type {
+        description "A traffic descriptor";
+    }
+    grouping fpc-descriptor-id {
+      leaf descriptor-id {
+        type fpcbase:fpc-identity;
+      }
+    }
+
+    identity pmip-selector-descriptor {
+      base "fpcbase:fpc-descriptor-type";
+    }
+    identity prefix-descriptor {
+      base "fpcbase:fpc-descriptor-type";
+    }
+    identity threegpp-tft-decriptor {
+      base "fpcbase:fpc-descriptor-type";
+    }
+    identity domain-descriptor {
+      base "fpcbase:fpc-descriptor-type";
+    }
+
+    grouping fpc-descriptor {
+        uses fpcbase:fpc-descriptor-id;
+        leaf descriptor-type {
+          mandatory true;
+          type identityref {
+            base "fpc-descriptor-type";
+          }
+          description "Descriptor Type";
+        }
+        choice descriptor-value {
+          case all-traffic {
+            leaf all-traffic {
+              type empty;
+            }
+          }
+          case pmip-selector {
+            uses traffic-selectors:traffic-selector;
+          }
+          case prefix-descriptor {
+              uses fpcpolicyext:prefix-traffic-descriptor;
+          }
+          case threegpp-tft {
+              uses threegpp:tft;
+          }
+          case domain-descriptor {
+              uses fpcpolicyext:domain-descriptor-list;
+          }
+        }
+    }
+
+    // Action Structure
+    typedef fpc-action-id-type {
+        type fpcbase:fpc-identity;
+        description "Action-ID";
+    }
+    identity fpc-action-type {
+        description "Action Type";
+    }
+    grouping fpc-action-id {
+      leaf action-id {
+        type fpcbase:fpc-action-id-type;
+      }
+    }
+
+    identity simple-nat-action {
+      base "fpcbase:fpc-action-type";
+    }
+    identity simple-napt-action {
+      base "fpcbase:fpc-action-type";
+    }
+    identity copy-action {
+      base "fpcbase:fpc-action-type";
+    }
+    identity drop-action {
+      base "fpcbase:fpc-action-type";
+    }
+    identity rate-action {
+      base "fpcbase:fpc-action-type";
+    }
+
+    grouping fpc-action {
+        uses fpcbase:fpc-action-id;
+        leaf action-type {
+          mandatory true;
+          type identityref {
+            base "fpc-action-type";
+          }
+          description "Action Type";
+        }
+        choice action-value {
+          case drop {
+            leaf drop {
+              mandatory true;
+              type empty;
+            }
+            container rate-info{
+              leaf sponsor-identity {
+                type threegpp:sponsor-identity-type;
+              }
+              uses fpcpolicyext:rating-action;
+            }
+          }
+          case simple-nat {
+              uses fpcpolicyext:simple-nat;
+          }
+          case simple-napt {
+              uses fpcpolicyext:simple-napt;
+          }
+          case copy-forward {
+              uses fpcbase:copy-forward;
+          }
+          case rate {
+              leaf sponsor-identity {
+                type threegpp:sponsor-identity-type;
+              }
+              uses fpcpolicyext:rating-action;
+          }
+        }
+    }
+
+    // Rule Structure
+    grouping fpc-rule {
+        description
+          "FPC Rule.  When no actions are present the action is DROP.
+          When no Descriptors are empty the default is 'all traffic'.";
+        list descriptors {
+          key descriptor-id;
+          uses fpcbase:fpc-descriptor-id;
+          leaf direction {
+            type fpc-direction;
+          }
+        }
+        list actions {
+          key action-id;
+          leaf order {
+              type uint32;
+          }
+          uses fpcbase:fpc-action-id;
+        }
+    }
+
+    // Policy Structures
+    typedef fpc-policy-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-policy {
+        leaf policy-id {
+            type fpcbase:fpc-policy-id;
+        }
+        list rules {
+            key order;
+            leaf order {
+              type uint32;
+            }
+            uses fpcbase:fpc-rule;
+        }
+    }
+
+    // Policy Group
+    typedef fpc-policy-group-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-policy-group {
+      leaf policy-group-id {
+        type fpcbase:fpc-policy-group-id;
+      }
+      leaf-list policies {
+        type fpcbase:fpc-policy-id;
+      }
+    }
+
+    // Mobility Structures
+    // Port Group
+    typedef fpc-port-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-port {
+        leaf port-id {
+            type fpcbase:fpc-port-id;
+        }
+        leaf-list policy-groups {
+            type fpcbase:fpc-policy-group-id;
+        }
+    }
+
+    // Context Group
+    typedef fpc-context-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-context-profile {
+        description "A profile that applies to a specific direction";
+        leaf tunnel-local-address {
+            type inet:ip-address;
+            description "Uplink endpoint address of the DPN which agent exists.";
+        }
+        leaf tunnel-remote-address {
+            type inet:ip-address;
+            description "Uplink endpoint address of the DPN which agent exists.";
+        }
+        leaf lifetime {
+            type uint32;
+        }
+        leaf tunnel-mtu-size {
+            type uint32;
+            description "Tunnel MTU size";
+        }
+        container mobility-tunnel-parameters {
+            description "Specifies profile specific uplink tunnel parameters to the DPN which the agent exists. The profiles includes GTP/TEID for 3gpp profile, GRE/Key for ietf-pmip profile, or new profile if anyone will define it.";
+            uses fpcbase:mobility-info;
+        }
+        container nexthop {
+            uses fpcbase:fpc-nexthop;
+        }
+        container qos-profile-parameters {
+            uses fpcbase:fpc-qos-profile;
+        }
+        container dpn-parameters {
+        }
+        list vendor-parameters {
+            key "vendor-id vendor-type";
+            uses fpcbase:vendor-attributes;
+        }
+    }
+
+    typedef fpc-direction {
+       type enumeration {
+         enum uplink;
+         enum downlink;
+       }
+    }
+
+    grouping fpc-context {
+        leaf context-id {
+            type fpcbase:fpc-context-id;
+        }
+        leaf dormant {
+            type boolean;
+        }
+        leaf-list ports {
+            type fpcbase:fpc-port-id;
+        }
+        leaf dpn-group {
+          type fpcbase:fpc-dpn-group-id;
+        }
+        leaf-list delegating-ip-prefixes {
+            type inet:ip-prefix;
+        }
+        container ul {
+            if-feature fpcbase:fpc-basic-agent;
+            uses fpcbase:fpc-context-profile;
+        }
+        container dl {
+            if-feature fpcbase:fpc-basic-agent;
+            uses fpcbase:fpc-context-profile;
+        }
+        list dpns {
+            if-feature fpcbase:fpc-multi-dpn;
+            key "dpn-id direction";
+            leaf dpn-id {
+                type fpcbase:fpc-dpn-id;
+            }
+            leaf direction {
+                mandatory true;
+                type fpcbase:fpc-direction;
+            }
+            uses fpcbase:fpc-context-profile;
+        }
+        leaf parent-context {
+            type fpcbase:fpc-context-id;
+        }
+        uses threegpp:threegpp-properties;
+    }
+
+    // Mobility (Tunnel) Information
+    grouping mobility-info {
+        choice mobprofile-parameters {
+            case nothing {
+              leaf none {
+                type empty;
+              }
+            }
+            case pmip-tunnel {
+              uses fpc-pmip:pmip-mobility;
+              choice pmiptunnel-or-ref {
+                  case defined-selector {
+                    uses traffic-selectors:traffic-selector;
+                  }
+                  case predefined-selector {
+                     leaf selector-reference {
+                        type fpcbase:fpc-identity;
+                     }
+                  }
+              }
+            }
+            case threegpp-tunnel {
+              uses threegpp:threeGPP-tunnel;
+              choice tft-or-ref {
+                  case defined-tft {
+                    uses threegpp:tft;
+                  }
+                  case predefined-tft {
+                     leaf tft-reference {
+                        type fpcbase:fpc-identity;
+                     }
+                  }
+              }
+            }
+        }
+    }
+
+    // Next Hop Structures
+    typedef fpcp-service-path-id {
+        type uint32 {
+            range "0..33554431";
+        }
+        description "SERVICE_PATH_ID";
+    }
+
+    identity fpc-nexthop-type {
+        description "Next Hop Type";
+    }
+    identity fpc-nexthop-ip {
+        base "fpcbase:fpc-nexthop-type";
+    }
+    identity fpc-nexthop-servicepath {
+        base "fpcbase:fpc-nexthop-type";
+    }
+    grouping fpc-nexthop {
+        leaf nexthop-type {
+            type identityref {
+              base "fpcbase:fpc-nexthop-type";
+            }
+        }
+        choice nexthop-value {
+            case ip {
+                leaf ip {
+                  type inet:ip-address;
+                }
+            }
+            case servicepath {
+                leaf servicepath {
+                    type fpcbase:fpcp-service-path-id;
+                }
+            }
+        }
+    }
+
+    // QoS Information
+    identity fpc-qos-type {
+        description "Base identity from which specific uses of QoS types are derived.";
+    }
+    grouping fpc-qos-profile {
+        leaf qos-type {
+            type identityref {
+                base fpcbase:fpc-qos-type;
+            }
+            description "the profile type";
+        }
+        choice value {
+          case qos-pmip {
+              uses qos-pmip:qosattribute;
+          }
+          case threegpp-qos {
+            uses threegpp:threeGPP-QoS;
+          }
+        }
+    }
+
+    // Vendor Specific Attributes
+    identity vendor-specific-type {
+        description "Vendor Specific Attribute Type";
+    }
+    grouping vendor-attributes {
+        leaf vendor-id {
+            type fpcbase:fpc-identity;
+        }
+        leaf vendor-type {
+            type identityref {
+                base "fpcbase:vendor-specific-type";
+            }
+        }
+        choice value {
+            case empty-type {
+                leaf empty-type {
+                    type empty;
+                }
+            }
+        }
+    }
+
+    // Topology
+    typedef fpc-domain-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-domain {
+      leaf domain-id {
+        type fpcbase:fpc-domain-id;
+      }
+      leaf domain-name {
+        type string;
+      }
+      leaf domain-type {
+        type string;
+      }
+    }
+
+    typedef fpc-dpn-id {
+        type fpcbase:fpc-identity;
+        description "DPN Identifier";
+    }
+    identity fpc-dpn-control-protocol {
+        description "DPN Control Protocol";
+    }
+    grouping fpc-dpn {
+        leaf dpn-id {
+          type fpcbase:fpc-dpn-id;
+        }
+        leaf dpn-name {
+          type string;
+        }
+        leaf-list dpn-groups {
+          type fpcbase:fpc-dpn-group-id;
+        }
+        leaf node-reference {
+          type instance-identifier;
+        }
+        leaf abstract {
+          type boolean;
+        }
+        leaf strategy {
+          type string;
+        }
+        leaf-list dpn-ids {
+          type fpcbase:fpc-dpn-id;
+        }
+        leaf node-id {
+          type string;
+        }
+        leaf network-id {
+          type string;
+        }
+    }
+
+    typedef fpc-dpn-group-id {
+        type fpcbase:fpc-identity;
+        description "DPN Group Identifier";
+    }
+    identity fpc-forwaridingplane-role {
+        description "Role of DPN Group in the Forwarding Plane";
+    }
+    identity fpc-access-type {
+        description "Access Type of the DPN Group";
+    }
+    identity fpc-mobility-profile-type {
+        description "Mobility Profile Type";
+    }
+
+    grouping fpc-dpn-peer-group {
+        leaf remote-dpn-group-id {
+            type fpcbase:fpc-dpn-group-id;
+        }
+        leaf remote-mobility-profile {
+            type identityref {
+                base "fpcbase:fpc-mobility-profile-type";
+            }
+        }
+        leaf remote-data-plane-role {
+            type identityref {
+                base "fpcbase:fpc-forwaridingplane-role";
+            }
+        }
+        leaf remote-endpoint-address {
+            type inet:ip-address;
+        }
+        leaf local-endpoint-address {
+            type inet:ip-address;
+        }
+        leaf tunnel-mtu-size {
+            type uint32;
+        }
+    }
+
+    // Events, Probes & Notifications
+    identity event-type {
+        description "Base Event Type";
+    }
+
+    typedef event-type-id {
+        type uint32;
+    }
+
+    grouping monitor-id {
+      leaf monitor-id {
+        type fpcbase:fpc-identity;
+      }
+    }
+
+    identity report-type {
+      description "Type of Report";
+    }
+    identity periodic-report {
+      base "fpcbase:report-type";
+    }
+    identity threshold-report {
+      base "fpcbase:report-type";
+    }
+    identity scheduled-report {
+      base "fpcbase:report-type";
+    }
+    identity events-report {
+      base "fpcbase:report-type";
+    }
+
+    grouping report-config {
+      choice event-config-value {
+        case periodic-config {
+            leaf period {
+              type uint32;
+            }
+        }
+        case threshold-config {
+            leaf lo-thresh {
+              type uint32;
+            }
+            leaf hi-thresh {
+              type uint32;
+            }
+        }
+        case scheduled-config {
+            leaf report-time {
+              type uint32;
+            }
+        }
+        case events-config-ident {
+            leaf-list event-identities {
+              type identityref {
+                base "fpcbase:event-type";
+              }
+            }
+        }
+        case events-config {
+            leaf-list event-ids {
+              type uint32;
+            }
+        }
+      }
+    }
+
+    grouping monitor-config {
+      uses fpcbase:monitor-id;
+      uses fpcbase:target-value;
+      uses fpcbase:report-config;
+    }
+
+    grouping report {
+      uses fpcbase:monitor-config;
+      choice report-value {
+        leaf trigger {
+          type fpcbase:event-type-id;
+        }
+        case simple-empty {
+          leaf nothing {
+            type empty;
+          }
+        }
+        case simple-val32 {
+          leaf val32 {
+            type uint32;
+          }
+        }
+        case any-data {
+          leaf data {
+            type string;
+          }
+        }
+      }
+    }
+
+    // PMIP Identities
+    identity ietf-pmip-access-type {
+      base "fpcbase:fpc-access-type";
+    }
+
+    identity fpcp-qos-index-pmip {
+        base "fpcbase:fpc-qos-type";
+    }
+    identity traffic-selector-mip6 {
+        base "fpcbase:fpc-descriptor-type";
+    }
+    identity ietf-pmip {
+        base "fpcbase:fpc-mobility-profile-type";
+    }
+
+    // Threegpp
+    identity threeGPP-qos-profile-parameters {
+        base "fpcbase:fpc-qos-type";
+    }
+
+    identity threeGPP-access-type {
+      base "fpcbase:fpc-access-type";
+    }
+
+    // Profile Type
+    identity threeGPP-mobility {
+         base "fpcbase:fpc-mobility-profile-type";
+    }
+
+    // Policy Extensions
+    identity service-function {
+        base "fpcbase:fpc-descriptor-type";
+        description "Base Identifier for Service Functions.";
+    }
+
+    identity napt-service {
+        base "service-function";
+    }
+
+    identity nat-service {
+        base "service-function";
+    }
+
+    identity copy-forward {
+      base "fpcbase:fpc-descriptor-type";
+      description "Copies a packet then forwards to a specific destination";
+    }
+    grouping copy-forward {
+      container destination {
+        choice value {
+          case port-ref {
+            leaf port-ref {
+              type fpcbase:fpc-port-id;
+            }
+          }
+          case context-ref {
+            leaf context-ref {
+              type fpcbase:fpc-context-id;
+            }
+          }
+        }
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang b/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang
new file mode 100644
index 0000000..1439224
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang
@@ -0,0 +1,330 @@
+module ietf-dmm-threegpp {
+    namespace "urn:ietf:params:xml:ns:yang:threegpp";
+    prefix threegpp;
+
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+    import ietf-traffic-selector-types { prefix traffic-selectors; revision-date 2016-01-14; }
+    import ietf-pmip-qos { prefix pmipqos; revision-date 2016-02-10; }
+
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     3GPP Related Mobility Structures";
+
+    revision 2016-08-03 {
+        description "Initial";
+        reference "draft-ietf-dmm-fpc-cpdp-04";
+    }
+
+    // Tunnel Types
+    identity threeGPP-tunnel-type {
+        description "Base Tunnel Type";
+    }
+
+    identity gtpv1 {
+        base "threegpp:threeGPP-tunnel-type";
+    }
+
+    identity gtpv2 {
+        base "threegpp:threeGPP-tunnel-type";
+    }
+
+    grouping teid-value {
+         leaf tunnel-identifier {
+            description "TEID";
+            type uint32;
+        }
+    }
+
+    grouping threeGPP-tunnel {
+        leaf tunnel-type {
+            type identityref  {
+              base "threegpp:threeGPP-tunnel-type";
+            }
+        }
+        uses threegpp:teid-value;
+    }
+
+    // QoS Profile
+    typedef fpc-qos-class-identifier {
+        type uint8 {
+            range "1..9";
+        }
+        description "QCI";
+    }
+
+    grouping threeGPP-QoS {
+        leaf qci {
+            type fpc-qos-class-identifier;
+        }
+        leaf gbr {
+            type uint32;
+        }
+        leaf mbr {
+            type uint32;
+        }
+        leaf apn-ambr {
+            type uint32;
+        }
+        leaf ue-ambr {
+            type uint32;
+        }
+        container arp {
+            uses pmipqos:Allocation-Retention-Priority-Value;
+        }
+    }
+
+    typedef ebi-type {
+      type uint8 {
+        range "0..15";
+      }
+    }
+
+   // From 3GPP TS 24.008 version 13.5.0 Release 13
+   typedef component-type-enum {
+        type enumeration {
+            enum ipv4RemoteAddress { value 16; }
+            enum ipv4LocalAddress  { value 17; }
+            enum ipv6RemoteAddress { value 32; }
+            enum ipv6RemoteAddressPrefix { value 33; }
+            enum ipv6LocalAddressPrefix { value 35; }
+            enum protocolNextHeader { value 48; }
+            enum localPort { value 64; }
+            enum localPortRange { value 65; }
+            enum reomotePort { value 80; }
+            enum remotePortRange { value 81; }
+            enum secParamIndex { value 96; }
+            enum tosTraffClass { value 112; }
+            enum flowLabel { value 128; }
+        }
+    }
+
+    typedef packet-filter-direction {
+        type enumeration {
+          enum preRel7Tft { value 0; }
+          enum uplink { value 1; }
+          enum downlink { value 2; }
+          enum bidirectional { value 3; }
+        }
+    }
+
+    typedef component-type-id {
+        type uint8 {
+          range "16 | 17 | 32 | 33 | 35 | 48 | 64 | 65 | 80 | 81 | 96 | 112 | 128";
+        }
+    }
+
+    typedef sponsor-identity-type {
+        type string;
+    }
+
+    grouping packet-filter {
+      leaf direction {
+          type threegpp:packet-filter-direction;
+      }
+      leaf identifier {
+          type uint8 {
+            range "1..15";
+          }
+      }
+      leaf evaluation-precedence {
+          type uint8;
+      }
+      list contents {
+        key component-type-identifier;
+        leaf component-type-identifier {
+            type threegpp:component-type-id;
+        }
+        choice value {
+          case ipv4-local {
+            leaf ipv4-local {
+              type inet:ipv4-address;
+            }
+            leaf ipv4-local-mask {
+              type inet:ipv4-address;
+            }
+          }
+          case ipv6-address-local {
+            leaf ipv6-address-local {
+              type inet:ipv6-prefix;
+            }
+            leaf ipv6-address-local-mask {
+              type inet:ipv6-prefix;
+            }
+          }
+          case ipv6-prefix-local {
+            leaf ipv6-prefix-local {
+              type inet:ipv6-prefix;
+            }
+          }
+
+          case ipv4-ipv6-remote {
+            leaf ipv4-ipv6-remote {
+              type inet:ip-address;
+            }
+            leaf ipv4-ipv6-remote-mask {
+              type inet:ip-address;
+            }
+          }
+
+          case ipv4-remote {
+            leaf ipv4-remote {
+              type inet:ipv4-address;
+            }
+            leaf ipv4-remote-mask {
+              type inet:ipv4-address;
+            }
+          }
+          case ipv6-address-remote {
+            leaf ipv6-address-remote {
+              type inet:ipv6-prefix;
+            }
+            leaf ipv6-address-remote-mask {
+              type inet:ipv6-prefix;
+            }
+          }
+          case ipv6-prefix-remote {
+            leaf ipv6-prefix-remote {
+              type inet:ipv6-prefix;
+            }
+          }
+
+          case protocol-next-header {
+            leaf next-header {
+              type uint8;
+            }
+          }
+
+          case local-port {
+            leaf local-port {
+              type inet:port-number;
+            }
+          }
+          case local-port-range {
+            leaf local-port-lo {
+              type inet:port-number;
+            }
+            leaf local-port-hi {
+              type inet:port-number;
+            }
+          }
+          case remote-port {
+            leaf remote-port {
+              type inet:port-number;
+            }
+          }
+          case remote-port-range {
+            leaf remote-port-lo {
+              type inet:port-number;
+            }
+            leaf remote-port-hi {
+              type inet:port-number;
+            }
+          }
+          case ipsec-index {
+            leaf ipsec-index {
+              type traffic-selectors:ipsec-spi;
+            }
+          }
+          case traffic-class {
+            leaf traffic-class {
+              type inet:dscp;
+            }
+          }
+          case traffic-class-range {
+              leaf traffic-class-lo {
+                type inet:dscp;
+              }
+              leaf traffic-class-hi {
+                type inet:dscp;
+              }
+          }
+          case flow-label-type {
+            leaf-list flow-label-type {
+              type inet:ipv6-flow-label;
+            }
+          }
+        }
+      }
+    }
+
+    grouping tft {
+      list packet-filters {
+          key identifier;
+          uses threegpp:packet-filter;
+      }
+    }
+
+    typedef imsi-type {
+        type uint64;
+    }
+
+    typedef threegpp-instr {
+      description "Instruction Set for 3GPP R11";
+      type bits {
+        bit assign-ip {
+          position 0;
+        }
+        bit assign-fteid-ip {
+          position 1;
+        }
+        bit assign-fteid-teid {
+          position 2;
+        }
+        bit session {
+          position 3;
+        }
+        bit uplink {
+          position 4;
+        }
+        bit downlink {
+          position 5;
+        }
+        bit assign-dpn {
+          position 6;
+        }
+        bit indirect-forward {
+          position 7;
+        }
+        bit create_new_tft {
+          position 8;
+        }
+        bit delete_existing_tft {
+          position 9;
+        }
+        bit add_filters_to_existing_tft {
+          position 10;
+        }
+        bit replace_filters_in_existing_tft {
+          position 11;
+        }
+        bit delete_filters_from_existing_tft {
+          position 12;
+        }
+        bit no_tft_op {
+          position 13;
+        }
+      }
+    }
+
+    grouping threegpp-properties {
+      leaf imsi {
+        type threegpp:imsi-type;
+      }
+      leaf ebi {
+        type threegpp:ebi-type;
+      }
+      leaf lbi {
+        type threegpp:ebi-type;
+      }
+    }
+
+    grouping threegpp-commandset {
+      leaf instr-3gpp-mob {
+        type threegpp:threegpp-instr;
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-pmip-qos.yang b/models/fpcagent/src/main/yang/ietf-pmip-qos.yang
new file mode 100644
index 0000000..4a22355
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-pmip-qos.yang
@@ -0,0 +1,564 @@
+module ietf-pmip-qos {
+    yang-version 1;
+
+    namespace
+      "urn:ietf:params:xml:ns:yang:ietf-pmip-qos";
+
+    prefix "qos-pmip";
+
+    import ietf-inet-types {
+    	prefix inet;
+    	revision-date 2013-07-15;
+    }
+    import ietf-traffic-selector-types { prefix traffic-selectors; }
+
+    organization
+      "IETF DMM (Dynamic Mobility Management) Working Group";
+
+    contact
+      "WG Web:   <https://datatracker.ietf.org/wg/dmm/>
+     WG List:  <mailto:dmm@ietf.org>
+
+     WG Chair: Dapeng Liu
+               <mailto:maxpassion@gmail.com>
+
+     WG Chair: Jouni Korhonen
+               <mailto:jouni.nospam@gmail.com>
+
+     Editor:
+               <mailto:>";
+
+    description
+      "This module contains a collection of YANG definitions for
+     quality of service paramaters used in Proxy Mobile IPv6.
+
+     Copyright (c) 2015 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module was created as part of the IETF
+    	DMM FPC YANG modules; see the RFC itself for full legal notices.";
+
+    revision 2016-02-10 {
+        description "Initial revision";
+        reference
+         "RFC 7222: Quality-of-Service Option for Proxy Mobile IPv6";
+    }
+
+    // Type Definitions
+
+    // QoS Option Field Type Definitions
+	typedef sr-id {
+		type uint8;
+	    description
+	     "An 8-bit unsigned integer used
+	      for identifying the QoS Service Request.  Its uniqueness is within
+	      the scope of a mobility session.  The local mobility anchor always
+	      allocates the Service Request Identifier.  When a new QoS Service
+	      Request is initiated by a mobile access gateway, the Service
+	      Request Identifier in the initial request message is set to a
+	      value of (0), and the local mobility anchor allocates a Service
+	      Request Identifier and includes it in the response.  For any new
+	      QoS Service Requests initiated by a local mobility anchor, the
+	      Service Request Identifier is set to the allocated value.";
+	  }
+
+    typedef traffic-class {
+    	type inet:dscp;
+    	description
+    		"Traffic Class consists of a 6-bit DSCP field followed by a 2-bit
+    		reserved field.";
+	   reference
+		     "RFC 3289: Management Information Base for the Differentiated
+		                Services Architecture
+		      RFC 2474: Definition of the Differentiated Services Field
+		                (DS Field) in the IPv4 and IPv6 Headers
+		      RFC 2780: IANA Allocation Guidelines For Values In
+		                the Internet Protocol and Related Headers";
+    }
+
+    typedef operational-code {
+    	type enumeration {
+    		enum RESPONSE { value 0; }
+    		enum ALLOCATE { value 1; }
+    		enum DE-ALLOCATE { value 2; }
+    		enum MODIFY { value 3; }
+    		enum QUERY { value 4; }
+    		enum NEGOTIATE { value 5; }
+    	}
+    	description
+    		"1-octet Operational code indicates the type of QoS request.
+
+    	      RESPONSE:   (0)
+    	         Response to a QoS request
+
+    	      ALLOCATE:   (1)
+    	         Request to allocate QoS resources
+
+    	      DE-ALLOCATE:   (2)
+    	         Request to de-Allocate QoS resources
+
+    	      MODIFY:   (3)
+    	         Request to modify QoS parameters for a previously negotiated
+    	         QoS Service Request
+
+    	      QUERY:   (4)
+    	         Query to list the previously negotiated QoS Service Requests
+    	         that are still active
+
+    	      NEGOTIATE:   (5)
+                Response to a QoS Service Request with a counter QoS proposal
+
+              Reserved:   (6) to (255)
+                Currently not used.  Receiver MUST ignore the option received
+                with any value in this range.";
+    }
+
+    // QoS Attribute Types
+
+    //The enumeration value for mapping - don't confuse with the identities
+    typedef qos-attrubite-type-enum {
+    	type enumeration {
+    		enum Reserved { value 0; }
+    		enum Per-MN-Agg-Max-DL-Bit-Rate { value 1; }
+	        enum Per-MN-Agg-Max-UL-Bit-Rate { value 2; }
+	        enum Per-Session-Agg-Max-DL-Bit-Rate { value 3; }
+	        enum Per-Session-Agg-Max-UL-Bit-Rate { value 4; }
+          enum Allocation-Retention-Priority { value 5; }
+	      	enum Aggregate-Max-DL-Bit-Rate { value 6; }
+	        enum Aggregate-Max-UL-Bit-Rate { value 7; }
+	        enum Guaranteed-DL-Bit-Rate { value 8; }
+	        enum Guaranteed-UL-Bit-Rate { value 9; }
+	        enum QoS-Traffic-Selector { value 10; }
+	        enum QoS-Vendor-Specific-Attribute { value 11; }
+    	}
+ 		description
+		"8-bit unsigned integer indicating the type of the QoS
+	      attribute.  This specification reserves the following values.
+	      (0) -  Reserved
+	         This value is reserved and cannot be used
+
+	      (1) -  Per-MN-Agg-Max-DL-Bit-Rate
+	         Per-Mobile-Node Aggregate Maximum Downlink Bit Rate.
+
+	      (2) -  Per-MN-Agg-Max-UL-Bit-Rate
+	         Per-Mobile-Node Aggregate Maximum Uplink Bit Rate.
+
+	      (3) -  Per-Session-Agg-Max-DL-Bit-Rate
+	         Per-Mobility-Session Aggregate Maximum Downlink Bit Rate.
+
+		    (4) -  Per-Session-Agg-Max-UL-Bit-Rate
+              Per-Mobility-Session Aggregate Maximum Uplink Bit Rate.
+
+ 	      (5) -  Allocation-Retention-Priority
+ 	         Allocation and Retention Priority.
+
+ 	      (6) -  Aggregate-Max-DL-Bit-Rate
+ 	         Aggregate Maximum Downlink Bit Rate.
+
+ 	      (7) -  Aggregate-Max-UL-Bit-Rate
+ 	         Aggregate Maximum Uplink Bit Rate.
+
+ 	      (8) -  Guaranteed-DL-Bit-Rate
+ 	         Guaranteed Downlink Bit Rate.
+
+ 	      (9) -  Guaranteed-UL-Bit-Rate
+ 	         Guaranteed Uplink Bit Rate.
+
+ 	      (10) -  QoS-Traffic-Selector
+ 	         QoS Traffic Selector.
+
+ 	      (11) -  QoS-Vendor-Specific-Attribute
+ 	        QoS Vendor-Specific Attribute.
+
+ 	      (12) to (254) -  Reserved
+ 	         These values are reserved for future allocation.
+
+ 	      (255) -  Reserved
+ 	         This value is reserved and cannot be used.";
+    }
+
+    // Attribute Type as Identities
+    // Added for convenience of inclusion and extension in other YANG modules.
+    identity qos-attribute-type {
+    	description
+    		"Base type for Quality of Service Attributes";
+    }
+
+    identity Per-MN-Agg-Max-DL-Bit-Rate-type {
+    	base qos-attribute-type;
+    	description
+    		"Per-Mobile-Node Aggregate Maximum Downlink Bit Rate.";
+	}
+
+ 	identity Per-MN-Agg-Max-UL-Bit-Rate-type {
+    	base qos-attribute-type;
+    	description
+    		"Per-Mobile-Node Aggregate Maximum Uplink Bit Rate";
+ 	}
+
+ 	identity Per-Session-Agg-Max-DL-Bit-Rate-type {
+    	base qos-attribute-type;
+    	description
+    		"Per-Mobility-Session Aggregate Maximum Downlink Bit Rate.";
+ 	}
+
+ 	identity Per-Session-Agg-Max-UL-Bit-Rate-type {
+    	base qos-attribute-type;
+    	description
+    		"Per-Mobility-Session Aggregate Maximum Uplink Bit Rate.";
+ 	}
+
+ 	identity Allocation-Retention-Priority-type {
+    	base qos-attribute-type;
+    	description
+    		"Allocation and Retention Priority.";
+ 	}
+
+ 	identity Aggregate-Max-DL-Bit-Rate-type {
+	  	base qos-attribute-type;
+	  	description "Aggregate Maximum Downlink Bit Rate.";
+ 	}
+
+  identity Aggregate-Max-UL-Bit-Rate-type {
+      base qos-attribute-type;
+      description "Aggregate Maximum Uplink Bit Rate.";
+  }
+
+  identity Guaranteed-DL-Bit-Rate-type {
+      base qos-attribute-type;
+      description "Guaranteed Downlink Bit Rate.";
+  }
+
+  identity Guaranteed-UL-Bit-Rate-type {
+      base qos-attribute-type;
+      description "Guaranteed Uplink Bit Rate.";
+  }
+
+  identity QoS-Traffic-Selector-type {
+      base qos-attribute-type;
+      description "QoS Traffic Selector.";
+  }
+
+  identity QoS-Vendor-Specific-Attribute-type {
+      base qos-attribute-type;
+      description "QoS Vendor-Specific Attribute.";
+  }
+
+  //value definitions
+  typedef Per-MN-Agg-Max-DL-Bit-Rate-Value {
+      type uint32;
+      description
+          "This is a 32-bit unsigned integer that
+          indicates the aggregate maximum downlink bit rate that is
+          requested/allocated for all the mobile node's IP flows.  The
+          measurement units for Per-MN-Agg-Max-DL-Bit-Rate are bits per
+          second.";
+	}
+
+ 	typedef Per-MN-Agg-Max-UL-Bit-Rate-Value {
+    	type uint32;
+    	description
+    		"This is a 32-bit unsigned integer that
+    	      indicates the aggregate maximum uplink bit rate that is requested/
+    	      allocated for the mobile node's IP flows.  The measurement units
+    	      for Per-MN-Agg-Max-UL-Bit-Rate are bits per second.";
+ 	}
+
+ 	// Generic Structure for the uplink and downlink
+ 	grouping Per-Session-Agg-Max-Bit-Rate-Value {
+ 		leaf max-rate {
+ 			type uint32;
+ 			mandatory true;
+ 			description
+ 				"This is a 32-bit unsigned integer
+ 			      that indicates the aggregate maximum bit rate that is requested/allocated
+ 				  for all the IP flows associated with that mobility session.  The measurement
+ 				  units for Per-Session-Agg-Max-UL/DL-Bit-Rate are bits per second.";
+ 		}
+ 		leaf service-flag {
+			type boolean;
+			mandatory true;
+			description
+				"This flag is used for extending the scope of the
+			      target flows for Per-Session-Agg-Max-UL/DL-Bit-Rate from(UL)/to(DL) the mobile
+			      node's other mobility sessions sharing the same Service
+			      Identifier. 3GPP Access Point Name (APN) is an example of a
+			      Service Identifier, and that identifier is carried using the
+			      Service Selection mobility option [RFC5149].
+
+			      *  When the (S) flag is set to a value of (1), then the Per-
+			         Session-Agg-Max-Bit-Rate is measured as an aggregate across
+			         all the mobile node's other mobility sessions sharing the same
+			         Service Identifier associated with this mobility session.
+
+			      *  When the (S) flag is set to a value of (0), then the target
+			         flows are limited to the current mobility session.
+
+			      *  The (S) flag MUST NOT be set to a value of (1) when there is no
+			         Service Identifier associated with the mobility session.";
+			reference
+				"RFC 5149 - Service Selection mobility option";
+ 		}
+ 		leaf exclude-flag {
+ 			type boolean;
+ 			mandatory true;
+ 			description
+ 				"This flag is used to request that the uplink/downlink
+ 			      flows for which the network is providing Guaranteed-Bit-Rate
+ 			      service be excluded from the target IP flows for which Per-
+ 			      Session-Agg-Max-UL/DL-Bit-Rate is measured.
+
+ 			      *  When the (E) flag is set to a value of (1), then the request is
+ 			         to exclude the IP flows for which Guaranteed-UL/DL-Bit-Rate
+ 			         is negotiated from the flows for which Per-Session-Agg-Max-UL/DL-Bit-Rate
+ 				     is measured.
+
+ 			      *  When the (E) flag is set to a value of (0), then the request is
+ 			         not to exclude any IP flows from the target IP flows for which
+ 			         Per-Session-Agg-Max-UL/DL-Bit-Rate is measured.
+
+ 			      *  When the (S) flag and (E) flag are both set to a value of (1),
+ 			         then the request is to exclude all the IP flows sharing the
+ 			         Service Identifier associated with this mobility session from
+ 			         the target flows for which Per-Session-Agg-Max-UL/DL-Bit-Rate is
+ 			         measured.";
+ 		}
+ 	}
+
+ 	grouping Allocation-Retention-Priority-Value {
+ 		leaf prioirty-level {
+ 			type uint8 {
+ 				range "0..15";
+ 			}
+ 			mandatory true;
+ 			description
+ 				"This is a 4-bit unsigned integer value.  It
+ 			      is used to decide whether a mobility session establishment or
+ 			      modification request can be accepted; this is typically used for
+ 			      admission control of Guaranteed Bit Rate traffic in case of
+ 			      resource limitations.  The priority level can also be used to
+
+ 			      decide which existing mobility session to preempt during resource
+ 			      limitations.  The priority level defines the relative timeliness
+ 			      of a resource request.
+
+ 			      Values 1 to 15 are defined, with value 1 as the highest level of
+ 			      priority.
+
+ 			      Values 1 to 8 should only be assigned for services that are
+ 			      authorized to receive prioritized treatment within an operator
+ 			      domain.  Values 9 to 15 may be assigned to resources that are
+ 			      authorized by the home network and thus applicable when a mobile
+ 			      node is roaming.";
+ 		}
+ 		leaf premption-capability {
+ 			type enumeration {
+				enum enabled { value 0; }
+				enum disabled { value 1; }
+				enum reserved1 { value 2; }
+				enum reserved2 { value 3; }
+ 			}
+ 			mandatory true;
+ 			description
+ 				"This is a 2-bit unsigned integer
+ 			      value.  It defines whether a service data flow can get resources
+ 			      that were already assigned to another service data flow with a
+ 			      lower priority level.  The following values are defined:
+
+ 			         Enabled (0): This value indicates that the service data flow is
+ 			         allowed to get resources that were already assigned to another
+ 			         IP data flow with a lower priority level.
+
+ 			         Disabled (1): This value indicates that the service data flow
+ 			         is not allowed to get resources that were already assigned to
+ 			         another IP data flow with a lower priority level.  The values
+ 			         (2) and (3) are reserved.";
+ 		}
+ 		leaf premption-vulnerability {
+ 			type enumeration {
+				enum enabled { value 0; }
+				enum disabled { value 1; }
+				enum reserved1 { value 2; }
+				enum reserved2 { value 3; }
+ 			}
+ 			mandatory true;
+ 			description
+				"This is a 2-bit unsigned integer
+ 			      value.  It defines whether a service data flow can lose the
+ 			      resources assigned to it in order to admit a service data flow
+ 			      with a higher priority level.  The following values are defined:
+
+ 			         Enabled (0): This value indicates that the resources assigned
+ 			         to the IP data flow can be preempted and allocated to a service
+ 			         data flow with a higher priority level.
+
+ 			         Disabled (1): This value indicates that the resources assigned
+ 			         to the IP data flow shall not be preempted and allocated to a
+ 			         service data flow with a higher priority level.  The values (2)
+ 			         and (3) are reserved.";
+ 		}
+ 	}
+
+ 	typedef Aggregate-Max-DL-Bit-Rate-Value {
+	  	type uint32;
+	  	description
+	  		"This is a 32-bit unsigned integer that
+	        indicates the aggregate maximum downlink bit rate that is
+	        requested/allocated for downlink IP flows.  The measurement units
+	        for Aggregate-Max-DL-Bit-Rate are bits per second.";
+ 	}
+
+  	typedef Aggregate-Max-UL-Bit-Rate-Value {
+    	type uint32;
+    	description
+    		"This is a 32-bit unsigned integer that
+    	      indicates the aggregate maximum downlink bit rate that is
+    	      requested/allocated for downlink IP flows.  The measurement units
+    	      for Aggregate-Max-DL-Bit-Rate are bits per second.";
+  	}
+
+  	typedef Guaranteed-DL-Bit-Rate-Value {
+	  	type uint32;
+	  	description
+	  		"This is a 32-bit unsigned integer that
+	        indicates the guaranteed bandwidth in bits per second for downlink
+	        IP flows.  The measurement units for Guaranteed-DL-Bit-Rate are
+	        bits per second.";
+  	}
+
+  	typedef Guaranteed-UL-Bit-Rate-Value {
+    	type uint32;
+    	description
+    		"This is a 32-bit unsigned integer that
+    	      indicates the guaranteed bandwidth in bits per second for uplink
+    	      IP flows.  The measurement units for Guaranteed-UL-Bit-Rate are
+    	      bits per second.";
+  	}
+
+  	grouping QoS-Vendor-Specific-Attribute-Value-Base {
+  		leaf vendorid {
+  			type uint32;
+  			mandatory true;
+  			description
+  				"The Vendor ID is the SMI (Structure of Management
+  		      Information) Network Management Private Enterprise Code of the
+  		      IANA-maintained 'Private Enterprise Numbers' registry [SMI].";
+  			reference
+  				"'PRIVATE ENTERPRISE NUMBERS', SMI Network Management
+                Private Enterprise Codes, April 2014,
+                <http://www.iana.org/assignments/enterprise-numbers>";
+  		}
+  		leaf subtype {
+  			type uint8;
+  			mandatory true;
+  			description
+  				"An 8-bit field indicating the type of vendor-specific
+  		      information carried in the option.  The namespace for this sub-
+  		      type is managed by the vendor identified by the Vendor ID field.";
+  		}
+    	description
+    		"QoS Vendor-Specific Attribute.";
+  	}
+
+    //NOTE - We do NOT add the Status Codes or other changes in PMIP in this module
+
+  	//Primary Structures (groupings)
+    grouping qosattribute {
+        leaf attributetype {
+            type identityref {
+                base qos-attribute-type;
+            }
+            mandatory true;
+            description "the attribute type";
+        }
+
+  		  //All of the sub-types by constraint
+        choice attribute-choice {
+            case per-mn-agg-max-dl-case {
+                when "../attributetype = 'Per-MN-Agg-Max-DL-Bit-Rate-type'";
+                leaf per-mn-agg-max-dl {
+                    type qos-pmip:Per-MN-Agg-Max-DL-Bit-Rate-Value;
+                }
+            }
+            case per-mn-agg-max-ul-case {
+                when "../attributetype = 'Per-MN-Agg-Max-UL-Bit-Rate-type'";
+                leaf per-mn-agg-max-ul {
+                    type qos-pmip:Per-MN-Agg-Max-UL-Bit-Rate-Value;
+                }
+            }
+            case per-session-agg-max-dl-case {
+                when "../attributetype = 'Per-Session-Agg-Max-DL-Bit-Rate-type'";
+                container per-session-agg-max-dl {
+                    uses qos-pmip:Per-Session-Agg-Max-Bit-Rate-Value;
+                }
+            }
+            case per-session-agg-max-ul-case {
+                when "../attributetype = 'Per-Session-Agg-Max-UL-Bit-Rate-type'";
+                container per-session-agg-max-ul {
+                    uses qos-pmip:Per-Session-Agg-Max-Bit-Rate-Value;
+                }
+            }
+            case allocation-retention-priority-case {
+                when "../attributetype = 'Allocation-Retention-Priority-type'";
+                uses qos-pmip:Allocation-Retention-Priority-Value;
+            }
+            case agg-max-dl-case {
+                when "../attributetype = 'Aggregate-Max-DL-Bit-Rate-type'";
+                leaf agg-max-dl {
+                    type qos-pmip:Aggregate-Max-DL-Bit-Rate-Value;
+                }
+            }
+            case agg-max-ul-case {
+                when "../attributetype = 'Aggregate-Max-UL-Bit-Rate-type'";
+                leaf agg-max-ul {
+                    type qos-pmip:Aggregate-Max-UL-Bit-Rate-Value;
+                }
+            }
+            case gbr-dl-case {
+                when "../attributetype = 'Guaranteed-DL-Bit-Rate-type'";
+                leaf gbr-dl {
+                    type qos-pmip:Guaranteed-DL-Bit-Rate-Value;
+                }
+            }
+            case gbr-ul-case {
+                when "../attributetype = 'Guaranteed-UL-Bit-Rate-type'";
+                leaf gbr-ul {
+                    type qos-pmip:Guaranteed-UL-Bit-Rate-Value;
+                }
+            }
+            case traffic-selector-case {
+                when "../attributetype = 'QoS-Traffic-Selector-type'";
+                container traffic-selector {
+                    uses traffic-selectors:traffic-selector;
+                }
+            }
+        }
+    }
+
+  	grouping qosoption {
+        leaf srid {
+            type sr-id;
+            mandatory true;
+        }
+        leaf trafficclass {
+            type traffic-class;
+            mandatory true;
+        }
+        leaf operationcode {
+            type operational-code;
+            mandatory true;
+        }
+        list attributes {
+            unique "attributetype";
+            uses qosattribute;
+            min-elements 1;
+        }
+  	}
+}
diff --git a/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang b/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang
new file mode 100644
index 0000000..029f3ec
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang
@@ -0,0 +1,508 @@
+module ietf-traffic-selector-types {
+    yang-version 1;
+
+    namespace
+      "urn:ietf:params:xml:ns:yang:ietf-traffic-selector-types";
+
+    prefix "ietf-traffic-selectors";
+
+    import ietf-inet-types {
+    	prefix inet;
+    	revision-date 2013-07-15;
+    }
+
+    organization
+      "IETF DMM (Dynamic Mobility Management) Working Group";
+
+    contact
+      "WG Web:   <https://datatracker.ietf.org/wg/dmm/>
+     WG List:  <mailto:dmm@ietf.org>
+
+     WG Chair: Dapeng Liu
+               <mailto:maxpassion@gmail.com>
+
+     WG Chair: Jouni Korhonen
+               <mailto:jouni.nospam@gmail.com>
+
+     Editor:
+               <mailto:>";
+
+    description
+      "This module contains a collection of YANG definitions for
+     traffic selectors for flow bindings.
+
+     Copyright (c) 2015 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module was created as part of the IETF
+    	DMM FPC YANG modules; see the RFC itself for full legal notices.";
+
+    revision 2016-01-14 {
+    	description "Updated for IETF-PACKET-FIELDS module alignment";
+    	reference
+    		"draft-ietf-netmod-acl-model-06";
+    }
+
+    revision 2016-01-12 {
+        description "Initial revision";
+        reference
+        	"RFC 6088: Traffic Selectors for Flow Bindings";
+    }
+
+    // Identities
+  	identity traffic-selector-format {
+  		description "The base type for Traffic-Selector Formats";
+  	}
+
+  	identity ipv4-binary-selector-format {
+  		base traffic-selector-format;
+  		description
+  			"IPv4 Binary Traffic Selector Format";
+  	}
+
+  	identity ipv6-binary-selector-format {
+  		base traffic-selector-format;
+  		description
+  			"IPv6 Binary Traffic Selector Format";
+  	}
+
+  	// Type definitions and groupings
+  	typedef ipsec-spi {
+  		type uint32;
+  		description "This type defines the first 32-bit IPsec Security Parameter
+				Index (SPI) value on data packets sent from a corresponding
+				node to the mobile node as seen by the home agent. This field
+				is defined in [RFC4303].";
+  			reference
+  				"RFC 4303: IP Encapsulating Security Payload (ESP)";
+  	}
+
+  	grouping traffic-selector-base {
+  		description "A grouping of the commen leaves between the v4 and v6 Traffic Selectors";
+  	    container ipsec-spi-range {
+  	      presence "Enables setting ipsec spi range";
+  	      description
+  	        "Inclusive range representing IPSec Security Parameter Indices to be used.
+  	        When only start-spi is present, it represents a single spi.";
+	  		leaf start-spi {
+	  			type ipsec-spi;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first 32-bit IPsec SPI value, from the
+	  		      range of SPI values to be matched, on data packets sent from a
+	  		      corresponding node to the mobile node as seen by the home agent.
+	  		      This field is defined in [RFC4303].";
+	  		}
+	  		leaf end-spi {
+	  			type ipsec-spi;
+	  	        must ". >= ../start-spi" {
+	  	          error-message
+	  	            "The end-spi must be greater than or equal to start-spi";
+	  	        }
+	  			description
+	  				"If more than one contiguous SPI value needs to be matched, then
+	  		      this field can be used to indicate the end value of a range
+	  		      starting from the value of the Start SPI field.  This field
+	  		      MUST NOT be included unless the Start SPI field is included
+	  			  and has a value less than or equal to this field.
+
+	  		      When this field is included, the receiver will match all of the
+	  		      SPI values between fields start-spi and end-spi,
+	  			  inclusive of start-spi and end-spi.";
+	  		}
+  	    }
+  	    container source-port-range {
+  	      presence "Enables setting source port range";
+  	      description
+  	        "Inclusive range representing source ports to be used.
+  	        When only start-port is present, it represents a single port.";
+	  		leaf start-port {
+	  			type inet:port-number;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first 16-bit source port number, from
+	  		      the range of port numbers to be matched, on data packets sent from
+	  		      a corresponding node to the mobile node as seen by the home agent.
+	  		      This is from the range of port numbers defined by IANA
+	  		      (http://www.iana.org).";
+	  		}
+	  		leaf end-port {
+	  			type inet:port-number;
+	  			must ". >= ../start-port" {
+	  	          error-message
+	  	          "The end-port must be greater than or equal to start-port";
+	  	        }
+	  			description
+	  				"If more than one contiguous source port number needs to be
+	  		      matched, then this field can be used to indicate the end value of
+	  		      a range starting from the value of the Start Port field.
+	  		      This field MUST NOT be included unless the Start Port field
+	  		      is included and has a value less than or equal to this field.
+
+	  			  When this field is included, the receiver will match
+	  		      all of the port numbers between fields start-port and
+	  			  end-port, inclusive of start-port and end-port.";
+	  		}
+  	   }
+  	  container destination-port-range {
+  	      presence "Enables setting destination port range";
+  	      description
+  	        "Inclusive range representing destination ports to be used. When
+  	  		 only start-port is present, it represents a single port.";
+	  		leaf start-port {
+	  			type inet:port-number;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first 16-bit destination port number,
+	  		      from the range of port numbers to be matched, on data packets sent
+	  		      from a corresponding node to the mobile node as seen by the home
+	  		      agent.";
+	  		}
+	  		leaf end-port {
+	  			type inet:port-number;
+	  	        must ". >= ../start-port" {
+	  	          error-message
+	  	            "The end-port must be greater than or equal to start-port";
+	  	        }
+	  			description
+	  				"If more than one contiguous destination port number needs to be
+	  		      matched, then this field can be used to indicate the end value of
+	  		      a range starting from the value of the Start Destination Port
+	  		      field.  This field MUST NOT be included unless the Start
+	  		      Port field is included and has a value less than or equal to this
+	  			  field.
+
+	  			  When this field is included, the receiver will match all of the
+	  			  port numbers between fields start-port and end-port, inclusive of
+	  			  start-port and end-port.";
+	  		}
+  	  }
+  	}
+
+  	grouping ipv4-binary-traffic-selector {
+	  container source-address-range-v4 {
+  	      presence "Enables setting source IPv4 address range";
+  	      description
+  	        "Inclusive range representing IPv4 addresses to be used. When
+  	  		 only start-address is present, it represents a single address.";
+	  		leaf start-address {
+	  			type inet:ipv4-address;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first source address, from the range of
+	  		      32-bit IPv4 addresses to be matched, on data packets sent from a
+	  		      corresponding node to the mobile node as seen by the home agent.
+	  		      In other words, this is one of the addresses of the correspondent
+	  		      node.";
+	  		}
+	  		leaf end-address {
+	  			type inet:ipv4-address;
+	  			description
+	  				"If more than one contiguous source address needs to be matched,
+	  		      then this field can be used to indicate the end value of a range
+	  		      starting from the value of the Start Address field.  This
+	  		      field MUST NOT be included unless the Start Address field
+	  		      is included.  When this field is included, the receiver will match
+	  		      all of the addresses between fields start-address and
+	  			  end-address, inclusive of start-address and end-address.";
+	  		}
+	  }
+	  container destination-address-range-v4 {
+  	      presence "Enables setting destination IPv4 address range";
+  	      description
+  	        "Inclusive range representing IPv4 addresses to be used. When
+  	  		 only start-address is present, it represents a single address.";
+	  		leaf start-address {
+	  			type inet:ipv4-address;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first destination address, from the
+	  		      range of 32-bit IPv4 addresses to be matched, on data packets sent
+	  		      from a corresponding node to the mobile node as seen by the home
+	  		      agent.  In other words, this is one of the registered home
+	  		      addresses of the mobile node.";
+	  		}
+	  		leaf end-address {
+	  			type inet:ipv4-address;
+	  			description
+	  				"If more than one contiguous destination address needs to be
+	  		      matched, then this field can be used to indicate the end value of
+	  		      a range starting from the value of the Start Destination Address
+	  		      field.  This field MUST NOT be included unless the Start
+	  		      Address field is included.  When this field is included, the receiver
+	  			  will match all of the addresses between fields start-address and
+	  			  end-address, inclusive of start-address and end-address.";
+	  		}
+	  }
+	  container ds-range {
+  	      presence "Enables setting dscp range";
+  	      description
+  	        "Inclusive range representing DiffServ Codepoints to be used. When
+  	  		 only start-ds is present, it represents a single Codepoint.";
+  	      leaf start-ds {
+  			type inet:dscp;
+  			mandatory true;
+  			description
+  				"This field identifies the first differential services value, from
+  		      the range of differential services values to be matched, on data
+  		      packets sent from a corresponding node to the mobile node as seen
+  		      by the home agent.  Note that this field is called a 'Type of
+  		      Service field' in [RFC0791].  [RFC3260] then clarified that the
+  		      field has been redefined as a 6-bit DS field with 2 bits reserved,
+  		      later claimed by Explicit Congestion Notification (ECN) [RFC3168].
+  		      For the purpose of this specification, the Start DS field is 8
+  		      bits long, where the 6 most significant bits indicate the DS field
+  		      to be matched and the 2 least significant bits' values MUST be
+  		      ignored in any comparison.";
+	  		}
+	  		leaf end-ds {
+	  			type inet:dscp;
+	  	        must ". >= ../start-ds" {
+	  	          error-message
+	  	            "The end-ds must be greater than or equal to start-ds";
+	  	        }
+	  			description
+	  				"If more than one contiguous DS value needs to be matched, then
+	  		      this field can be used to indicate the end value of a range
+	  		      starting from the value of the Start DS field.  This field MUST
+	  		      NOT be included unless the Start DS field is included.  When this
+	  		      field is included, it MUST be coded the same way as defined for
+	  		      start-ds.  When this field is included, the receiver will match all of
+	  		      the values between fields start-ds and end-ds, inclusive of start-ds
+	  			  and end-ds.";
+	  		}
+	  }
+	  container protocol-range {
+		presence "Enables setting protocol range";
+		description
+			"Inclusive range representing IP protocol(s) to be used. When
+		   	 only start-protocol is present, it represents a single protocol.";
+  		leaf start-protocol {
+  			type uint8;
+  			mandatory true;
+  			description
+  				"This field identifies the first 8-bit protocol value, from the
+  		      range of protocol values to be matched, on data packets sent from
+  		      a corresponding node to the mobile node as seen by the home agent.";
+  		}
+  		leaf end-protocol {
+  			type uint8;
+  	        must ". >= ../start-protocol" {
+  	          error-message
+  	            "The end-protocol must be greater than or equal to start-protocol";
+  	        }
+  			description
+  				"If more than one contiguous protocol value needs to be matched,
+  		      then this field can be used to indicate the end value of a range
+  		      starting from the value of the Start Protocol field.  This field
+  		      MUST NOT be included unless the Start Protocol field is included.
+  		      When this field is included, the receiver will match all of the
+  		      values between fields start-protocol and end-protocol, inclusive
+  			  of start-protocol and end-protocol.";
+  		}
+	  }
+  	}
+
+	grouping ipv6-binary-traffic-selector {
+	 container source-address-range-v6 {
+  	      presence "Enables setting source IPv6 address range";
+  	      description
+  	        "Inclusive range representing IPv6 addresses to be used. When
+  	  		 only start-address is present, it represents a single address.";
+	  		leaf start-address {
+	  			type inet:ipv6-address;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first source address, from the range of
+	  		      128-bit IPv6 addresses to be matched, on data packets sent from a
+	  		      corresponding node to the mobile node as seen by the home agent.
+	  		      In other words, this is one of the addresses of the correspondent
+	  		      node.";
+	  		}
+	  		leaf end-address {
+	  			type inet:ipv6-address;
+	  			description
+	  				"If more than one contiguous source address needs to be matched,
+	  		      then this field can be used to indicate the end value of a range
+	  		      starting from the value of the Start Address field.  This
+	  		      field MUST NOT be included unless the Start Address field is included.
+	  			  When this field is included, the receiver will match all of the addresses
+	  			  between fields start-address and end-address, inclusive of start-address
+	  			  and end-address .";
+	  		}
+	  }
+  	  container destination-address-range-v6 {
+  	      presence "Enables setting destination IPv6 address range";
+  	      description
+  	        "Inclusive range representing IPv6 addresses to be used. When
+  	  		 only start-address is present, it represents a single address.";
+	  		leaf start-address {
+	  			type inet:ipv6-address;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first destination address, from the
+	  		      range of 128-bit IPv6 addresses to be matched, on data packets
+	  		      sent from a corresponding node to the mobile node as seen by the
+	  		      home agent.  In other words, this is one of the registered home
+	  		      addresses of the mobile node.";
+	  		}
+	  		leaf end-address {
+	  			type inet:ipv6-address;
+	  			description
+	  				"If more than one contiguous destination address needs to be
+	  		      matched, then this field can be used to indicate the end value of
+	  		      a range starting from the value of the Start Address field. This
+	  			  field MUST NOT be included unless the Start Address field is included.
+	  			  When this field is included, the receiver will match all of the
+	  			  addresses between fields start-address and end-address, inclusive of
+	  			  start-address and end-address.";
+	  		}
+  	  }
+  	 container flow-label-range {
+      presence "Enables setting Flow Label range";
+      description
+        "Inclusive range representing IPv4 addresses to be used. When
+  		 only start-flow-label is present, it represents a single flow label.";
+  		leaf start-flow-label {
+  			type inet:ipv6-flow-label;
+  			description
+  				"This field identifies the first flow label value, from the range
+  		      of flow label values to be matched, on data packets sent from a
+  		      corresponding node to the mobile node as seen by the home agent.
+  		      According to [RFC2460], the flow label is 24 bits long.  For the
+  		      purpose of this specification, the sender of this option MUST
+  		      prefix the flow label value with 8 bits of '0' before inserting it
+  		      in the start-flow-label field.  The receiver SHOULD ignore the
+  		      first 8 bits of this field before using it in comparisons with
+  		      flow labels in packets.";
+  		}
+  		leaf end-flow-label {
+  			type inet:ipv6-flow-label;
+  	        must ". >= ../start-flow-label" {
+  	          error-message
+  	            "The end-flow-lable must be greater than or equal to start-flow-label";
+  	        }
+  			description
+  				"If more than one contiguous flow label value needs to be matched,
+  		      then this field can be used to indicate the end value of a range
+  		      starting from the value of the Start Flow Label field.  This field
+  		      MUST NOT be included unless the Start Flow Label field is
+  		      included.  When this field is included, the receiver will match
+  		      all of the flow label values between fields start-flow-label
+  			  and end-flow-label, inclusive of start-flow-label and end-flow-label.
+  			  When this field is included, it MUST be coded the same way as defined
+  			  for end-flow-label.";
+  		}
+  	 }
+  	 container traffic-class-range {
+      presence "Enables setting the traffic class range";
+      description
+        "Inclusive range representing IPv4 addresses to be used. When
+  		 only start-traffic-class is present, it represents a single traffic class.";
+  		leaf start-traffic-class {
+  			type inet:dscp;
+  			description
+  				"This field identifies the first traffic class value, from the
+  		      range of traffic class values to be matched, on data packets sent
+  		      from a corresponding node to the mobile node as seen by the home
+  		      agent.  This field is equivalent to the Start DS field in the IPv4
+  		      traffic selector in Figure 1.  As per RFC 3260, the field is
+  		      defined as a 6-bit DS field with 2 bits reserved, later claimed by
+  		      Explicit Congestion Notification (ECN) RFC 3168.  For the purpose
+  		      of this specification, the start-traffic-class field is 8 bits long, where
+  		      the 6 most significant bits indicate the DS field to be matched
+  		      and the 2 least significant bits' values MUST be ignored in any
+  		      comparison.";
+  			reference
+  				"RFC 3260: New Terminology and Clarifications for Diffserv
+  				 RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP";
+  		}
+  		leaf end-traffic-class {
+  			type inet:dscp;
+  	        must ". >= ../start-traffic-class" {
+  	          error-message
+  	            "The end-traffic-class must be greater than or equal to start-traffic-class";
+  	        }
+  			description
+  				"If more than one contiguous TC value needs to be matched, then
+  		      this field can be used to indicate the end value of a range
+  		      starting from the value of the Start TC field.  This field MUST
+  		      NOT be included unless the Start TC field is included.  When this
+  		      field is included, it MUST be coded the same way as defined for
+  			  start-traffic-class.  When this field is included, the receiver
+  			  will match all of the values between fields start-traffic-class
+  			  and end-traffic-class, inclusive of start-traffic-class and
+  		      end-traffic-class.";
+  		}
+  	 }
+  	 container next-header-range {
+      presence "Enables setting Next Header range";
+      description
+        "Inclusive range representing Next Headers to be used. When
+  		 only start-next-header is present, it represents a single Next Header.";
+  		leaf start-next-header {
+  			type uint8;
+  			description
+  				"This field identifies the first 8-bit next header value, from the
+  		      range of next header values to be matched, on data packets sent
+  		      from a corresponding node to the mobile node as seen by the home
+  		      agent.";
+  		}
+  		leaf end-next-header {
+  			type uint8;
+  	        must ". >= ../start-next-header" {
+  	          error-message
+  	            "The end-next-header must be greater than or equal to start-next-header";
+  	        }
+  			description
+  				"If more than one contiguous next header value needs to be matched,
+  		      then this field can be used to indicate the end value of a range
+  		      starting from the value of the Start NH field.  This field MUST
+  		      NOT be included unless the Start next header field is included.
+  		      When this field is included, the receiver will match all of the
+  		      values between fields start-next-header and end-next-header,
+  			  inclusive of start-next-header and end-next-header.";
+  		}
+  	 }
+	}
+
+	grouping traffic-selector {
+		leaf ts-format {
+ 			type identityref {
+  				base traffic-selector-format;
+  			}
+  			description "Traffic Selector Format";
+  		}
+		uses traffic-selector-base {
+			when "boolean(../ts-format/text() = 'ipv6-binary-selector-format') | boolean(../ts-format/text() = 'ipv4-binary-selector-format')";
+		}
+		uses ipv4-binary-traffic-selector {
+			when "boolean(../ts-format/text() = 'ipv4-binary-selector-format')";
+		}
+		uses ipv6-binary-traffic-selector {
+			when "boolean(../ts-format/text() = 'ipv6-binary-selector-format')";
+		}
+		description
+			"The traffic selector includes the parameters used to match
+			   packets for a specific flow binding.";
+		reference
+			"RFC 6089: Flow Bindings in Mobile IPv6 and Network Mobility (NEMO) Basic Support";
+	}
+
+	grouping ts-list {
+		list selectors {
+			key index;
+			leaf index {
+				type uint64;
+			}
+			uses traffic-selector;
+		}
+	}
+}
diff --git a/modules.defs b/modules.defs
new file mode 100644
index 0000000..ad0e561
--- /dev/null
+++ b/modules.defs
@@ -0,0 +1,275 @@
+UTILS = [
+    '//utils/osgi:onlab-osgi',
+    '//utils/junit:onlab-junit',
+    '//utils/misc:onlab-misc',
+    '//utils/rest:onlab-rest',
+    '//tools/build/conf:onos-build-conf',
+]
+
+API = [
+    '//core/api:onos-api',
+    '//incubator/api:onos-incubator-api',
+]
+
+CORE = UTILS + API + [
+    '//core/net:onos-core-net',
+    '//core/common:onos-core-common',
+    '//core/store/primitives:onos-core-primitives',
+    '//core/store/serializers:onos-core-serializers',
+    '//core/store/dist:onos-core-dist',
+    '//core/security:onos-security',
+    '//core/store/persistence:onos-core-persistence',
+
+    '//incubator/net:onos-incubator-net',
+    '//incubator/store:onos-incubator-store',
+    '//incubator/rpc:onos-incubator-rpc',
+
+    '//cli:onos-cli',
+
+    '//protocols/rest/api:onos-protocols-rest-api',
+    '//protocols/rest/ctl:onos-protocols-rest-ctl',
+    '//protocols/bgp/bgpio:onos-protocols-bgp-bgpio',
+    '//protocols/bgp/api:onos-protocols-bgp-api',
+    '//protocols/bgp/ctl:onos-protocols-bgp-ctl',
+    '//protocols/netconf/api:onos-protocols-netconf-api',
+    '//protocols/netconf/ctl:onos-protocols-netconf-ctl',
+    '//protocols/openflow/api:onos-protocols-openflow-api',
+    '//protocols/openflow/ctl:onos-protocols-openflow-ctl',
+    '//protocols/ospf/api:onos-protocols-ospf-api',
+    '//protocols/ospf/protocol:onos-protocols-ospf-protocol',
+    '//protocols/ospf/ctl:onos-protocols-ospf-ctl',
+    '//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc',
+    '//protocols/ovsdb/api:onos-protocols-ovsdb-api',
+    '//protocols/ovsdb/ctl:onos-protocols-ovsdb-ctl',
+    '//protocols/pcep/pcepio:onos-protocols-pcep-pcepio',
+    '//protocols/pcep/server/api:onos-protocols-pcep-server-api',
+    '//protocols/pcep/server/ctl:onos-protocols-pcep-server-ctl',
+    '//protocols/snmp/api:onos-protocols-snmp-api',
+    '//protocols/snmp/ctl:onos-protocols-snmp-ctl',
+    '//protocols/isis/api:onos-protocols-isis-api',
+    '//protocols/isis/ctl:onos-protocols-isis-ctl',
+    '//protocols/isis/isisio:onos-protocols-isis-isisio',
+    '//protocols/lisp/api:onos-protocols-lisp-api',
+    '//protocols/lisp/ctl:onos-protocols-lisp-ctl',
+    '//protocols/lisp/msg:onos-protocols-lisp-msg',
+    '//protocols/tl1/api:onos-protocols-tl1-api',
+    '//protocols/tl1/ctl:onos-protocols-tl1-ctl',
+    '//protocols/restconf/client/api:onos-protocols-restconf-client-api',
+    '//protocols/restconf/client/ctl:onos-protocols-restconf-client-ctl',
+
+    '//drivers/utilities:onos-drivers-utilities',
+
+    '//providers/netconf/device:onos-providers-netconf-device',
+    '//providers/openflow/device:onos-providers-openflow-device',
+    '//providers/openflow/packet:onos-providers-openflow-packet',
+    '//providers/openflow/flow:onos-providers-openflow-flow',
+    '//providers/openflow/group:onos-providers-openflow-group',
+    '//providers/openflow/meter:onos-providers-openflow-meter',
+    '//providers/ovsdb/device:onos-providers-ovsdb-device',
+    '//providers/ovsdb/tunnel:onos-providers-ovsdb-tunnel',
+    '//providers/rest/device:onos-providers-rest-device',
+    '//providers/snmp/device:onos-providers-snmp-device',
+    '//providers/isis/cfg:onos-providers-isis-cfg',
+    '//providers/isis/topology:onos-providers-isis-topology',
+    '//providers/lisp/device:onos-providers-lisp-device',
+    '//providers/tl1/device:onos-providers-tl1-device',
+    '//providers/general/device:onos-providers-general-device',
+    '//providers/p4runtime/packet:onos-providers-p4runtime-packet',
+
+    '//web/api:onos-rest',
+    '//web/gui:onos-gui',
+
+    '//incubator/protobuf/models:onos-incubator-protobuf-models',
+    '//incubator/protobuf/services/nb:onos-incubator-protobuf-services-nb',
+]
+
+ONOS_DRIVERS = [
+    # Drivers
+    '//drivers/default:onos-drivers-default-oar',
+    '//drivers/arista:onos-drivers-arista-oar',
+    # TODO ONOS-5554 excluding from the build
+    #'//drivers/bti:onos-drivers-bti-oar',
+    '//drivers/ciena:onos-drivers-ciena-oar',
+    '//drivers/cisco/netconf:onos-drivers-cisco-netconf-oar',
+    '//drivers/cisco/rest:onos-drivers-cisco-rest-oar',
+    '//drivers/corsa:onos-drivers-corsa-oar',
+    '//drivers/fujitsu:onos-drivers-fujitsu-oar',
+    '//drivers/lumentum:onos-drivers-lumentum-oar',
+    '//drivers/netconf:onos-drivers-netconf-oar',
+    '//drivers/optical:onos-drivers-optical-oar',
+    '//drivers/ovsdb:onos-drivers-ovsdb-oar',
+    '//drivers/juniper:onos-drivers-juniper-oar',
+    '//drivers/lisp:onos-drivers-lisp-oar',
+    '//drivers/flowspec:onos-drivers-flowspec-oar',
+    '//drivers/huawei:onos-drivers-huawei-oar',
+    '//drivers/microsemi:onos-drivers-microsemi-oar',
+    '//drivers/oplink:onos-drivers-oplink-oar',
+    '//drivers/bmv2:onos-drivers-bmv2-oar',
+    '//drivers/barefoot:onos-drivers-barefoot-oar',
+    '//drivers/hp:onos-drivers-hp-oar',
+    '//drivers/p4runtime:onos-drivers-p4runtime-oar',
+    '//drivers/polatis/netconf:onos-drivers-polatis-netconf-oar',
+]
+
+ONOS_PROVIDERS = [
+    # Providers
+    '//providers/bgp:onos-providers-bgp-oar',
+    '//providers/bgpcep:onos-providers-bgpcep-oar',
+    '//providers/host:onos-providers-host-oar',
+    '//providers/lldp:onos-providers-lldp-oar',
+    '//providers/netcfghost:onos-providers-netcfghost-oar',
+    '//providers/netcfglinks:onos-providers-netcfglinks-oar',
+    '//providers/netconf:onos-providers-netconf-oar',
+    '//providers/openflow/message:onos-providers-openflow-message-oar',
+    '//providers/ovsdb:onos-providers-ovsdb-oar',
+    '//providers/ovsdb/host:onos-providers-ovsdb-host-oar',
+    '//providers/ovsdb/base:onos-providers-ovsdb-base-oar',
+    '//providers/pcep:onos-providers-pcep-oar',
+    '//providers/null:onos-providers-null-oar',
+    '//providers/openflow/base:onos-providers-openflow-base-oar',
+    '//providers/openflow/app:onos-providers-openflow-app-oar',
+    '//providers/rest:onos-providers-rest-oar',
+    '//providers/isis:onos-providers-isis-oar',
+    '//providers/snmp:onos-providers-snmp-oar',
+    '//providers/link:onos-providers-link-oar',
+    '//providers/lisp:onos-providers-lisp-oar',
+    '//providers/tl1:onos-providers-tl1-oar',
+    '//providers/general:onos-providers-general-oar',
+    '//providers/p4runtime:onos-providers-p4runtime-oar',
+#    '//providers/ietfte:onos-providers-ietfte-oar',
+]
+
+ONOS_APPS = [
+    # Apps
+    '//apps/dhcp:onos-apps-dhcp-oar',
+    '//apps/dhcprelay:onos-apps-dhcprelay-oar',
+    '//apps/fwd:onos-apps-fwd-oar',
+    '//apps/packet-stats:onos-apps-packet-stats-oar',
+    '//apps/acl:onos-apps-acl-oar',
+    '//apps/bgprouter:onos-apps-bgprouter-oar',
+    '//apps/cip:onos-apps-cip-oar',
+    '//apps/drivermatrix:onos-apps-drivermatrix-oar',
+    '//apps/events:onos-apps-events-oar',
+    '//apps/proxyarp:onos-apps-proxyarp-oar',
+    '//apps/segmentrouting:onos-apps-segmentrouting-oar',
+    '//apps/gangliametrics:onos-apps-gangliametrics-oar',
+    '//apps/graphitemetrics:onos-apps-graphitemetrics-oar',
+    '//apps/flowanalyzer:onos-apps-flowanalyzer-oar',
+    '//apps/intentsync:onos-apps-intentsync-oar',
+    '//apps/influxdbmetrics:onos-apps-influxdbmetrics-oar',
+    '//apps/metrics:onos-apps-metrics-oar',
+    '//apps/mfwd:onos-apps-mfwd-oar',
+    '//apps/mlb:onos-apps-mlb-oar',
+    '//apps/openstacknetworking:onos-apps-openstacknetworking-oar',
+    '//apps/mobility:onos-apps-mobility-oar',
+    '//apps/newoptical:onos-apps-newoptical-oar',
+    '//apps/optical-model:onos-apps-optical-model-oar',
+    '//apps/optical-rest:onos-apps-optical-rest-oar',
+    '//apps/pathpainter:onos-apps-pathpainter-oar',
+    '//apps/pcep-api:onos-apps-pcep-api-oar',
+    '//apps/pim:onos-apps-pim-oar',
+    '//apps/linkprops:onos-apps-linkprops-oar',
+    '//apps/reactive-routing:onos-apps-reactive-routing-oar',
+    '//apps/roadm:onos-apps-roadm-oar',
+    '//apps/sdnip:onos-apps-sdnip-oar',
+    '//apps/test/demo:onos-apps-test-demo-oar',
+    '//apps/test/distributed-primitives:onos-apps-test-distributed-primitives-oar',
+    '//apps/test/election:onos-apps-test-election-oar',
+    '//apps/test/flow-perf:onos-apps-test-flow-perf-oar',
+    '//apps/test/intent-perf:onos-apps-test-intent-perf-oar',
+    '//apps/test/loadtest:onos-apps-test-loadtest-oar',
+    '//apps/test/netcfg-monitor:onos-apps-test-netcfg-monitor-oar',
+    '//apps/test/messaging-perf:onos-apps-test-messaging-perf-oar',
+    '//apps/test/primitive-perf:onos-apps-test-primitive-perf-oar',
+    '//apps/test/transaction-perf:onos-apps-test-transaction-perf-oar',
+    '//apps/virtualbng:onos-apps-virtualbng-oar',
+    '//apps/vpls:onos-apps-vpls-oar',
+    '//apps/vrouter:onos-apps-vrouter-oar',
+    '//apps/routing/fibinstaller:onos-apps-routing-fibinstaller-oar',
+    '//apps/routing/cpr:onos-apps-routing-cpr-oar',
+    '//apps/routing/fpm:onos-apps-routing-fpm-oar',
+    '//apps/vtn:onos-apps-vtn-oar',
+    '//apps/faultmanagement:onos-apps-faultmanagement-oar',
+    '//apps/openstacknode:onos-apps-openstacknode-oar',
+    '//apps/cpman/app:onos-apps-cpman-app-oar',
+    '//apps/scalablegateway:onos-apps-scalablegateway-oar',
+    '//apps/castor:onos-apps-castor-oar',
+#    '//apps/yms:onos-apps-yms-oar',
+    '//apps/ofagent:onos-apps-ofagent-oar',
+    '//apps/mappingmanagement:onos-apps-mappingmanagement-oar',
+    '//apps/config:onos-apps-config-oar',
+    '//apps/configsync:onos-apps-configsync-oar',
+    '//apps/configsync-netconf:onos-apps-configsync-netconf-oar',
+    '//apps/netconf/client:onos-apps-netconf-client-oar',
+    '//apps/tetopology:onos-apps-tetopology-oar',
+    '//apps/tetunnel:onos-apps-tetunnel-oar',
+#    '//apps/tenbi/yangmodel:onos-apps-tenbi-yangmodel-feature',
+#    '//apps/tenbi:onos-apps-tenbi-oar',
+    '//protocols/restconf/server:onos-protocols-restconf-server-oar',
+    '//apps/restconf:onos-apps-restconf-oar',
+    '//apps/flowspec-api:onos-apps-flowspec-api-oar',
+    '//apps/yang:onos-apps-yang-oar',
+    '//apps/yang-gui:onos-apps-yang-gui-oar',
+    '//apps/cord-support:onos-apps-cord-support-oar',
+    '//apps/network-troubleshoot:onos-apps-network-troubleshoot-oar',
+    '//apps/l3vpn:onos-apps-l3vpn-oar',
+    '//apps/openroadm:onos-apps-openroadm-oar',
+    '//apps/artemis:onos-apps-artemis-oar',
+    '//apps/pi-demo/ecmp:onos-apps-pi-demo-ecmp-oar',
+    '//apps/gluon:onos-apps-gluon-oar',
+    '//apps/evpnopenflow:onos-apps-evpnopenflow-oar',
+    '//apps/route-service:onos-apps-route-service-oar',
+    '//apps/evpn-route-service:onos-apps-evpn-route-service-oar',
+    '//incubator/protobuf/registry:onos-incubator-protobuf-registry-oar',
+    '//incubator/protobuf/services/nb:onos-incubator-protobuf-services-nb-oar',
+    '//apps/openstacknetworkingui:onos-apps-openstacknetworkingui-oar',
+    '//apps/p4-tutorial/pipeconf:onos-apps-p4-tutorial-pipeconf-oar',
+    '//apps/p4-tutorial/icmpdropper:onos-apps-p4-tutorial-icmpdropper-oar',
+    '//apps/cfm:onos-apps-cfm-oar',
+    '//apps/routeradvertisement:onos-apps-routeradvertisement-oar',
+    '//apps/powermanagement:onos-apps-powermanagement-oar',
+    '//apps/t3:onos-apps-t3-oar',
+    '//apps/fpcagent:onos-apps-fpcagent-oar',
+]
+
+PROTOCOL_APPS = [
+    '//protocols/grpc:onos-protocols-grpc-oar',
+    '//protocols/p4runtime:onos-protocols-p4runtime-oar',
+]
+
+MODELS = [
+    '//models/common:onos-models-common-oar',
+    '//models/huawei:onos-models-huawei-oar',
+    '//models/openconfig:onos-models-openconfig-oar',
+    '//models/openroadm:onos-models-openroadm-oar',
+    '//models/tapi:onos-models-tapi-oar',
+    '//models/l3vpn:onos-models-l3vpn-oar',
+    '//models/microsemi:onos-models-microsemi-oar',
+    '//models/polatis:onos-models-polatis-oar',
+    '//models/fpcagent:onos-models-fpcagent-oar',
+]
+
+PIPELINES = [
+    '//pipelines/basic:onos-pipelines-basic-oar',
+    '//pipelines/fabric:onos-pipelines-fabric-oar',
+]
+
+APP_JARS = [
+    '//apps/cpman/api:onos-apps-cpman-api',
+    '//apps/routing-api:onos-apps-routing-api',
+    '//apps/dhcp/api:onos-apps-dhcp-api',
+    '//apps/dhcp/app:onos-apps-dhcp-app',
+    '//apps/dhcprelay:onos-apps-dhcprelay',
+    '//apps/fwd:onos-apps-fwd',
+    '//apps/iptopology-api:onos-apps-iptopology-api',
+    '//apps/routing/common:onos-apps-routing-common',
+    '//apps/vtn/vtnrsc:onos-apps-vtn-vtnrsc',
+    '//apps/vtn/sfcmgr:onos-apps-vtn-sfcmgr',
+    '//apps/vtn/vtnmgr:onos-apps-vtn-vtnmgr',
+    '//apps/vtn/vtnweb:onos-apps-vtn-vtnweb',
+#   '//apps/p4runtime-test:onos-apps-p4runtime-test',
+]
+
+APPS = ONOS_DRIVERS + ONOS_PROVIDERS + ONOS_APPS + MODELS + PIPELINES \
+        + PROTOCOL_APPS
+
diff --git a/scripts/addDPN.sh b/scripts/addDPN.sh
new file mode 100755
index 0000000..9c77d37
--- /dev/null
+++ b/scripts/addDPN.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+curl -i --header "Content-type: application/json" --request POST -u onos:rocks --data '{
+    "dpns": [
+        {
+            "dpn-id": "1",
+            "dpn-name": "site1-anchor1",
+            "dpn-groups": [
+                "foo"
+            ],
+            "node-id": "node1",
+            "network-id": "network1"
+        }
+    ]
+}' 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology'
+./getTenants.sh
\ No newline at end of file
diff --git a/scripts/createRPC.sh b/scripts/createRPC.sh
new file mode 100755
index 0000000..621f6df
--- /dev/null
+++ b/scripts/createRPC.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+curl -X POST --header 'Content-Type: application/json' -u onos:rocks --header 'Accept: application/json' -d '{
+    "input": {
+        "admin-state": "enabled",
+        "client-id": "1",
+        "contexts": [
+            {
+                "context-id": 202374887,
+                "delegating-ip-prefixes": [
+                    "192.168.1.5/32"
+                ],
+                "dl": {
+                    "dpn-parameters": {},
+                    "mobility-tunnel-parameters": {
+                        "tunnel-identifier": "2222",
+                        "tunnel-type": "gtpv1"
+                    },
+                    "tunnel-local-address": "192.168.1.1",
+                    "tunnel-remote-address": "10.1.1.1"
+                },
+                "dpn-group": "foo",
+                "dpns": [
+                    {
+                        "direction": "uplink",
+                        "dpn-id": "1",
+                        "dpn-parameters": {}
+                    }
+                ],
+                "ebi": "5",
+                "imsi": "9135551234",
+                "instructions": {
+                    "instr-3gpp-mob": "session uplink"
+                },
+                "lbi": "5",
+                "ul": {
+                    "dpn-parameters": {},
+                    "mobility-tunnel-parameters": {
+                        "tunnel-identifier": "1111",
+                        "tunnel-type": "gtpv1"
+                    },
+                    "tunnel-local-address": "192.168.1.1",
+                    "tunnel-remote-address": "10.1.1.1"
+                }
+            }
+        ],
+        "op-id": "1",
+        "op-ref-scope": "op",
+        "op-type": "create",
+        "session-state": "complete"
+    }
+}' 'http://localhost:8181/onos/restconf/operations/ietf-dmm-fpcagent:configure' | python -m json.tool
diff --git a/scripts/deleteContext.sh b/scripts/deleteContext.sh
new file mode 100755
index 0000000..0e9eda8
--- /dev/null
+++ b/scripts/deleteContext.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-mobility/contexts=202374887'
+./getTenants.sh
\ No newline at end of file
diff --git a/scripts/deleteContextDl.sh b/scripts/deleteContextDl.sh
new file mode 100755
index 0000000..64f6c2b
--- /dev/null
+++ b/scripts/deleteContextDl.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-mobility/contexts=202374887/dl'
+./getTenants.sh
\ No newline at end of file
diff --git a/scripts/deleteDPN.sh b/scripts/deleteDPN.sh
new file mode 100755
index 0000000..f210b60
--- /dev/null
+++ b/scripts/deleteDPN.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology/dpns=1'
+./getTenants.sh
diff --git a/scripts/deleteRPC.sh b/scripts/deleteRPC.sh
new file mode 100755
index 0000000..772b61b
--- /dev/null
+++ b/scripts/deleteRPC.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+curl -X POST --header 'Content-Type: application/json' -u onos:rocks --header 'Accept: application/json' -d '{
+    "input": {
+        "op-id": "3",
+        "targets": [
+            {
+                "target": "/ietf-dmm-fpcagent:tenants/tenant=default/fpc-mobility/contexts=202374887"
+            }
+        ],
+        "client-id": "1",
+        "session-state": "complete",
+        "admin-state": "enabled",
+        "op-type": "delete",
+        "op-ref-scope": "none"
+    }
+}' 'http://localhost:8181/onos/restconf/operations/ietf-dmm-fpcagent:configure' | python -m json.tool
diff --git a/scripts/forwarder_device.py b/scripts/forwarder_device.py
new file mode 100755
index 0000000..04f2a18
--- /dev/null
+++ b/scripts/forwarder_device.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+# coding: utf8
+#Copyright © 2016 - 2017 Copyright (c) Sprint, Inc. and others.  All rights reserved.
+#
+#This program and the accompanying materials are made available under the
+#terms of the Eclipse Public License v1.0 which accompanies this distribution,
+#and is available at http://www.eclipse.org/legal/epl-v10.html
+
+import zmq
+
+def main():
+
+    try:
+        context = zmq.Context(1)
+
+        # Socket facing clients
+        frontend = context.socket(zmq.SUB)
+        frontend.bind("tcp://*:5559")
+        
+        frontend.setsockopt(zmq.SUBSCRIBE, "")
+        
+         # Socket facing services
+        backend = context.socket(zmq.PUB)
+        backend.bind("tcp://*:5560")
+
+
+        zmq.device(zmq.FORWARDER, frontend, backend)
+    except Exception, e:
+        print e
+        print "bringing down zmq device"
+    finally:
+        pass
+        frontend.close()
+        backend.close()
+        context.term()
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/scripts/forwarder_subscriber_with_ACK.py b/scripts/forwarder_subscriber_with_ACK.py
new file mode 100755
index 0000000..fbc5088
--- /dev/null
+++ b/scripts/forwarder_subscriber_with_ACK.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+# coding: utf8
+#Copyright © 2016 - 2017 Copyright (c) Sprint, Inc. and others.  All rights reserved.
+#
+#This program and the accompanying materials are made available under the
+#terms of the Eclipse Public License v1.0 which accompanies this distribution,
+#and is available at http://www.eclipse.org/legal/epl-v10.html
+
+import signal
+import sys
+import zmq
+import struct
+import socket as socketlib
+import datetime
+import time
+import random
+import thread
+from multiprocessing.pool import ThreadPool
+
+pool = ThreadPool(processes=1)
+
+conflict = False
+topicId = None
+#nodeId = "node3"
+#networkId = "network4"
+nodeId = "node"+sys.argv[1]
+networkId = "network"+sys.argv[2]
+toSend = sys.argv[3]
+source = random.randrange(0,65535)
+topicId = random.randrange(4,255)
+
+def signal_handler(signal, frame):
+    print "\nExiting... Sending DPN Status Indication message with Status = GOODBYE"
+    pub_socket.send("%s" % (struct.pack("!BBBBIB",2,12,topicId,2,source,len(nodeId)) + nodeId + struct.pack('!B',len(networkId)) + networkId))
+    sys.exit(0)
+
+signal.signal(signal.SIGINT, signal_handler)
+
+def sendAssignId(pub_socket): 
+    global conflict
+    global topicId
+    time.sleep(1)
+    pub_socket.send("%s" % (struct.pack('!BBBIB',1,10,topicId,source,len(nodeId)) + nodeId + struct.pack('!B',len(networkId)) + networkId))
+    count = 0
+    while True:
+        time.sleep(1)
+        sys.stdout.write("\r"+str(9-count)+" ")
+        sys.stdout.flush()
+        count += 1
+        if conflict:
+            conflict = False
+            sendAssignId(pub_socket)
+            return
+        if count > 9:
+            break
+    print "\nDPN Topic = ", topicId
+    print "Node Id = ", nodeId
+    print "Network Id = ", networkId
+    print "Source Id = ", source
+    print "Sending Hello Message . . ."
+    pub_socket.send("%s" % (struct.pack("!BBBBIB",2,12,topicId,1,source,len(nodeId)) + nodeId + struct.pack('!B',len(networkId)) + networkId))
+
+    print "Ready to receive messages. Press Ctrl+C when ready to exit."
+
+subscriber_uri = "tcp://localhost:5560"
+publisher_uri = "tcp://localhost:5559"
+# Socket to talk to server
+context = zmq.Context()
+sub_socket = context.socket(zmq.SUB)
+pub_socket = context.socket(zmq.PUB)
+sub_socket.connect(subscriber_uri)
+pub_socket.connect(publisher_uri)
+topicfilter = ""
+controller_topic= 252
+sub_socket.setsockopt(zmq.SUBSCRIBE, topicfilter)
+print "Subscriber to ", subscriber_uri
+print "Publisher to ", publisher_uri
+print "DPN Lifecycle start up . . . Please wait."
+
+async_result = pool.apply_async(sendAssignId,(pub_socket,))
+
+count = 0
+msgnum1count = 0
+msgnum2count = 0
+msgnum3count = 0
+msgnum4count = 0
+msgnum5count = 0
+msgnum6count = 0
+for update_nbr in range(900000):
+    string = sub_socket.recv()
+    ts = time.time()
+    st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
+ 
+    topic,msgnum = struct.unpack('!BB',string[:2])
+
+    print 'received %s %s' % (topic, msgnum)
+
+    if topic == 1 and msgnum == 10: #Assign_Id
+        top,msg,topId,src,nodeIdLen = struct.unpack('!BBBIB',string[:8])
+        top,msg,topId,src,nodeIdLen,nodeId1,networkIdLen = struct.unpack('!BBBIB'+str(nodeIdLen)+'sB',string[:8+nodeIdLen+1])
+        top,msg,topId,src,nodeIdLen,nodeId1,networkIdLen,networkId1 = struct.unpack('!BBBIB'+str(nodeIdLen)+'sB'+str(networkIdLen)+'s',string[:8+nodeIdLen+1+networkIdLen])
+        #print nodeId1, networkId1
+        if src != source and (topId == topicId or nodeId1 == nodeId):
+            pub_socket.send("%s" % struct.pack('!BBBIBsBs',1,11,topicId,source,len(nodeId),nodeId,len(networkId),networkId))
+        continue
+
+    elif topic == 1 and msgnum == 11: #Assign_Conflict
+        top,msg,topId,src,nodeIdLen = struct.unpack('!BBBIB',string[:8])
+        top,msg,topId,src,nodeIdLen,nodeId1,networkIdLen = struct.unpack('!BBBIB'+str(nodeIdLen)+'sB',string[:8+nodeIdLen+1])
+        top,msg,topId,src,nodeIdLen,nodeId1,networkIdLen,networkId1 = struct.unpack('!BBBIB'+str(nodeIdLen)+'sB'+str(networkIdLen)+'s',string[:8+nodeIdLen+1+networkIdLen])
+        
+        if src != source:
+            if(nodeId == nodeId1):
+                print "Received assign conflict for node id. Change the node id and restart this script."
+                exit(0)
+            if(networkId == networkId1):
+                print "Received assign conflict for network id. Change the network id and restart this script."
+                exit(0)
+            if(top == topicId):
+                print "Received assign conflict for topic id. Generating new topic id and resending Assign Topic Id Message."
+                topicId = random.randrange(0,255)
+            conflict = True
+        continue
+
+    elif topic == topicId and msgnum == 13:
+        top, msg, controller_topic, controller_status = struct.unpack('!BBBB',string[:4])
+        print "DPN Status ACK received. Controller Topic = ",controller_topic
+        continue
+
+    elif topic == 3 and msgnum == 14:
+        top, msg, controller_topic, controller_status = struct.unpack('!BBBB',string[:4])
+        if controller_status == 1:
+            print "Received controller Hello. Controller Topic = ",controller_topic
+            print "Sending Hello To Controller that has a topic id of ", controller_topic
+            pub_socket.send("%s" % (struct.pack("!BBBBIB",controller_topic,12,topicId,1,source,len(nodeId)) + nodeId + struct.pack('!B',len(networkId)) + networkId))
+
+        elif controller_status == 2:
+            print "Received controller Goodbye. Controller Topic =  ",controller_topic
+
+    if topic != topicId:
+        continue
+    print 'Receiving message', count, ' at ', st, ' ..... '
+    count += 1
+    print 'length of message = ', len(string)
+    print 'topic =', topic
+    print 'msgnum =', msgnum
+
+    if msgnum == 1:
+        msgnum1count += 1
+        topic,msgnum, imsi, default_ebi, ue_ip, s1u_sgw_gtpu_teid, s1u_sgw_gtpu_ipv4, sessionid, ctopic, cid, opid = struct.unpack('!cBQBLLLQBLL',string[:40])    
+        print 'imsi = ', imsi
+        ipa = socketlib.inet_ntoa(struct.pack('!L',ue_ip))
+        print 'ue_ip = ', ipa
+        print 'default_ebi = ', default_ebi
+        s1u_sgw_gtpu_ipv4a = socketlib.inet_ntoa(struct.pack('!L',s1u_sgw_gtpu_ipv4))
+        print 's1u_sgw_gtpu_ipv4 = ', s1u_sgw_gtpu_ipv4a
+        print 's1u_sgw_gtpu_teid = ', s1u_sgw_gtpu_teid
+        print 'sessionid = ', sessionid
+        print 'controller topic = ', ctopic
+        print 'cid = ', cid
+        print 'opid = ', opid
+        responsedata = struct.pack('!BBBLL',controller_topic,4, 16, cid, opid)
+	if toSend == "true":
+        	pub_socket.send("%s" % (responsedata))
+        #uncomment the following lines to send a DDN for every create session message 
+        #time.sleep(5)
+        #pub_socket.send("%s" % (struct.pack('!BBQLLB'+str(len(nodeId))+'sB'+str(len(networkId))+'s',controller_topic,5,sessionid,cid,opid,len(nodeId),nodeId,len(networkId),networkId)))
+
+    elif msgnum == 2:
+        msgnum2count += 1
+        topic, msgnum, s1u_enb_gtpu_ipv4, s1u_enb_gtpu_teid, s1u_sgw_gtpu_ipv4, sessionid, ctopic, cid, opid  = struct.unpack("!cBLLLQBLL",string[:31])
+        s1u_enb_gtpu_ipv4a = socketlib.inet_ntoa(struct.pack('!L',s1u_enb_gtpu_ipv4))
+        print 's1u_enb_gtpu_ipv4 = ', s1u_enb_gtpu_ipv4a
+        print 'dl s1u_enb_gtpu_teid = ', s1u_enb_gtpu_teid
+        print 'dl s1u_sgw_gtpu_ipv4 = ', socketlib.inet_ntoa(struct.pack('!L',s1u_sgw_gtpu_ipv4))
+        print 'sessionid = ', sessionid
+        print 'controller topic = ', ctopic
+        print 'cid = ', cid
+        print 'opid = ', opid
+        responsedata = struct.pack('!BBBLL',controller_topic,4, 16, cid, opid)
+	if  toSend == "true":
+        	pub_socket.send("%s" % (responsedata))
+
+    elif msgnum == 3:
+        msgnum3count += 1
+        topic, msgnum, sessionid, ctopic, cid, opid = struct.unpack("!cBQBLL",string[:19])
+        print 'sessionid = ', sessionid
+        print 'controller topic = ', ctopic
+        print 'cid = ', cid
+        print 'opid = ', opid
+        responsedata = struct.pack('!BBBLL',controller_topic,4, 0, cid, opid)
+	if toSend == "true":
+        	pub_socket.send("%s" % (responsedata))
+
+    elif msgnum == 6:
+        if(len(string)==14):
+            #topic,msgnum,bufduration,bufcount,controller_topic,cid,opid = struct.unpack('!BBBHBLL',string[:14])
+            topic,msgnum,controller_topic,cid,opid = struct.unpack('!BBBLL',string[:11])
+            #print "dl-buffering-duration",bufduration
+            #print "dl-buffering-suggested-count",bufcount
+            print "Controller Topic = ",controller_topic
+            print "Client id = ", cid
+            print "Op Id = ", opid
+
+    elif msgnum == 17:
+        print "-------------------------------------------------------------"
+        print "ADC Rule received. Details:"
+        topic,msgnum,selector_type = struct.unpack('!BBB',string[:3])
+
+        #Domain
+        if(selector_type == 0):
+            domain_name_length, = struct.unpack('!B',string[3:4])
+            domain_name, = struct.unpack('!'+str(domain_name_length)+'s',string[4:4+int(domain_name_length)])
+            next_index = 4+int(domain_name_length)
+            print "Domain Name = ",domain_name
+
+        #IP Address
+        if(selector_type == 1 or selector_type == 2):
+            ip_address, = struct.unpack('!L',string[3:7])
+            ip_addressa = socketlib.inet_ntoa(struct.pack('!L',ip_address))
+            next_index = 7
+            print "IP Address = ",ip_addressa
+
+        #IP Prefix
+        if selector_type == 2:
+            ip_prefix, = struct.unpack('!H',string[7:9])
+            next_index += 2
+            print "IP Prefix = ",ip_prefix
+
+        #rule_id, = struct.unpack('!L',string[rule_id_index:rule_id_index+4])
+        #print "Rule Id = ", rule_id
+
+        #rating_group,service_id,sponsor_id_length = struct.unpack('!LLB', string[rule_id_index+4:rule_id_index+4+9])
+        drop,rating_group,service_id,sponsor_id_length = struct.unpack('!BLLB', string[next_index:next_index+10])
+        print "Drop = ", drop
+        print "Rating Group = ", rating_group
+        print "Service Id = ", service_id
+        #print "Sponsor Length = ", sponsor_id_length
+        #sponsor_id, = struct.unpack('!'+str(sponsor_id_length)+'s',string[rule_id_index+4+9:rule_id_index+4+9+int(sponsor_id_length)])
+        sponsor_id, = struct.unpack('!'+str(sponsor_id_length)+'s',string[next_index+10:next_index+10+int(sponsor_id_length)])
+        print "Sponsor = ", sponsor_id 
+        print "-------------------------------------------------------------"
+        #precedence, = struct.unpack('!L',string[rule_id_index+4+9+int(sponsor_id_length):rule_id_index+4+9+int(sponsor_id_length)+4])
+        #print "precedence = ", precedence
+
+    print '================'
+    print 'Total = ', count, 'msgnum1 count', msgnum1count, 'msgnum2 count', msgnum2count, 'msgnum3 count', msgnum3count, 'msgnum4 count', msgnum4count,'msgnum5 count', msgnum5count, 'msgnum6 count', msgnum6count
+sub_socket.close()
diff --git a/scripts/getFpcAgentInfo.sh b/scripts/getFpcAgentInfo.sh
new file mode 100755
index 0000000..4a45b20
--- /dev/null
+++ b/scripts/getFpcAgentInfo.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+curl -u onos:rocks http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:fpc-agent-info
diff --git a/scripts/getTenants.sh b/scripts/getTenants.sh
new file mode 100755
index 0000000..abe3bd1
--- /dev/null
+++ b/scripts/getTenants.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+curl -u onos:rocks http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants | python -m json.tool
diff --git a/scripts/updateRPC.sh b/scripts/updateRPC.sh
new file mode 100755
index 0000000..de934bf
--- /dev/null
+++ b/scripts/updateRPC.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+curl -X POST --header 'Content-Type: application/json' -u onos:rocks --header 'Accept: application/json' -d '{
+    "input": {
+        "admin-state": "enabled",
+        "client-id": "1",
+        "contexts": [
+            {
+                "context-id": 202374887,
+                "delegating-ip-prefixes": [
+                    "192.168.1.5/32"
+                ],
+                "dl": {
+                    "dpn-parameters": {},
+                    "mobility-tunnel-parameters": {
+                        "tunnel-identifier": "2222",
+                        "tunnel-type": "gtpv1"
+                    },
+                    "tunnel-local-address": "192.168.1.1",
+                    "tunnel-remote-address": "10.1.1.1"
+                },
+                "dpn-group": "foo",
+                "dpns": [
+                    {
+                        "direction": "uplink",
+                        "dpn-id": "1",
+                        "dpn-parameters": {}
+                    }
+                ],
+                "ebi": "5",
+                "imsi": "9135551234",
+                "instructions": {
+                    "instr-3gpp-mob": "session uplink"
+                },
+                "lbi": "5",
+                "ul": {
+                    "dpn-parameters": {},
+                    "mobility-tunnel-parameters": {
+                        "tunnel-identifier": "1111",
+                        "tunnel-type": "gtpv1"
+                    },
+                    "tunnel-local-address": "192.168.1.1",
+                    "tunnel-remote-address": "10.1.1.1"
+                }
+            }
+        ],
+        "op-id": "1",
+        "op-ref-scope": "op",
+        "op-type": "update",
+        "session-state": "complete"
+    }
+}' 'http://localhost:8181/onos/restconf/operations/ietf-dmm-fpcagent:configure' | python -m json.tool