changing structure
diff --git a/apps/fpcagent/BUCK b/apps/fpcagent/BUCK
index a3d15fb..4396a00 100644
--- a/apps/fpcagent/BUCK
+++ b/apps/fpcagent/BUCK
@@ -10,6 +10,7 @@
     '//lib:javax.ws.rs-api',
     '//utils/rest:onlab-rest',
     '//core/store/serializers:onos-core-serializers',
+    '//apps/restconf/utils:onos-apps-restconf-utils',
     ':zeromq',
     ':json',
 ]
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
index 6b4e016..1896cc4 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
@@ -20,8 +20,6 @@
 import com.google.common.collect.Maps;
 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.onosproject.config.DynamicConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
@@ -31,34 +29,30 @@
 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.IetfDmmFpcagentOpParam;
 import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.IetfDmmFpcagentService;
-import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.DefaultTenants;
+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.instructions.instructions.instrtype.Instr3GppMob;
 import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opheader.OpTypeEnum;
 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.DefaultErr;
 import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbodydpn.resulttype.DefaultEmptyCase;
 import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.mobilityinfo.mobprofileparameters.ThreegppTunnel;
-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.ArrayList;
 import java.util.HashMap;
 import java.util.Optional;
 
-import static org.onosproject.fpcagent.helpers.Converter.getFpcIdentity;
+import static org.onosproject.fpcagent.FpcUtil.*;
 
 /**
  * Fpc Manager.
@@ -66,22 +60,21 @@
 @Component(immediate = true)
 @Service
 public class FpcManager implements IetfDmmFpcagentService, FpcService {
-    static final Logger log = LoggerFactory.getLogger(FpcManager.class);
+    private static final Logger log = LoggerFactory.getLogger(FpcManager.class);
 
-    private static final String FPC_APP_ID = "org.onosproject.fpcagent";
     private static final Class<FpcConfig> CONFIG_CLASS = FpcConfig.class;
     private final InternalNetworkConfigListener configListener =
             new InternalNetworkConfigListener();
 
     /* Services */
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected TenantService tenantService;
+    private TenantService tenantService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    ModelConverter modelConverter;
+    private ModelConverter modelConverter;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    DynamicConfigService dynamicConfigService;
+    private DynamicConfigService dynamicConfigService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     private RpcRegistry rpcRegistry;
@@ -96,10 +89,7 @@
     private CoreService coreService;
 
     /* Variables */
-    private ApplicationId appId;
     private FpcConfig fpcConfig;
-    private IetfDmmFpcagentOpParam fpcData;
-
     private HashMap<String, ArrayList<Contexts>> sessionContextsMap = Maps.newHashMap();
     private HashMap<String, String> nodeNetworkMap = Maps.newHashMap();
 
@@ -115,32 +105,12 @@
 
     @Activate
     protected void activate() {
-        appId = coreService.registerApplication(FPC_APP_ID);
+        coreService.registerApplication(FPC_APP_ID);
         configService.addListener(configListener);
         registry.registerConfigFactory(fpcConfigConfigFactory);
 
-        fpcData = new IetfDmmFpcagentOpParam();
-
         rpcRegistry.registerRpcService(this);
 
-        tenantService.addTenant(getFpcIdentity.apply("default"));
-
-        DefaultTenants defaultTenants = new DefaultTenants();
-        fpcData.tenants(defaultTenants);
-        defaultTenants.addToTenant(tenantService.getTenant(getFpcIdentity.apply("default")).get());
-
-        ResourceData dataNode = modelConverter.createDataNode(
-                DefaultModelObjectData.builder()
-                        .addModelObject(defaultTenants)
-                        .build()
-        );
-
-
-        log.info("resourceData {} ", dataNode.dataNodes().size());
-        dataNode.dataNodes().forEach(
-                node -> dynamicConfigService.createNode(dataNode.resourceId(), node)
-        );
-
         log.info("FPC Agent Started");
     }
 
@@ -188,34 +158,23 @@
 
     @Override
     public RpcOutput configureDpn(RpcInput rpcInput) {
-        log.info("RPC configure {}", rpcInput);
-
-        DefaultConfigureDpnOutput defaultConfigureDpnOutput = new DefaultConfigureDpnOutput();
-        defaultConfigureDpnOutput.result(Result.of(ResultEnum.OK));
-        defaultConfigureDpnOutput.resultType(new DefaultEmptyCase());
+        DefaultConfigureDpnOutput output = new DefaultConfigureDpnOutput();
+        output.result(Result.of(ResultEnum.OK));
+        output.resultType(new DefaultEmptyCase());
 
         try {
-            ResourceData data = DefaultResourceData.builder()
-                    .addDataNode(rpcInput.data())
-                    .resourceId(
-                            ResourceId.builder()
-                                    .addBranchPointSchema("configureDpn", "urn:ietf:params:xml:ns:yang:fpcagent")
-                                    .build())
-                    .build();
-
-            ModelObjectData model = modelConverter.createModel(data);
-            model.modelObjects().parallelStream().forEach(
+            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);
-                                nodeNetworkMap.put(dpnId, dpnId + "/" + dpnId);
+                                // TODO
                                 break;
                             case REMOVE:
                                 log.info("Removing DPN {}", dpnId);
-                                nodeNetworkMap.remove(dpnId);
+                                // TODO
                                 break;
                         }
                     });
@@ -224,223 +183,107 @@
         }
 
         ResourceData dataNode = modelConverter.createDataNode(
-                DefaultModelObjectData.builder().addModelObject(defaultConfigureDpnOutput).build()
+                DefaultModelObjectData.builder().addModelObject(output).build()
         );
         return new RpcOutput(RpcOutput.Status.RPC_SUCCESS, dataNode.dataNodes().get(0));
     }
 
     @Override
     public RpcOutput configure(RpcInput rpcInput) {
-        log.info("RPC configure {}", rpcInput);
-
         DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
-        configureOutput.result(Result.of(ResultEnum.OK));
-        configureOutput.resultType(new DefaultCommonSuccess());
 
         try {
-            ResourceData data = DefaultResourceData.builder()
-                    .addDataNode(rpcInput.data())
-                    .resourceId(
-                            ResourceId.builder()
-                                    .addBranchPointSchema("configure", "urn:ietf:params:xml:ns:yang:fpcagent")
-                                    .build())
-                    .build();
-
-            ModelObjectData model = modelConverter.createModel(data);
-            model.modelObjects().parallelStream().forEach(
-                    modelObject -> {
-                        DefaultConfigureInput input = (DefaultConfigureInput) modelObject;
-                        configureOutput.opId(input.opId());
-                        switch (input.opType()) {
-                            case CREATE:
-                            case UPDATE:
-                                if (input.opBody() instanceof CreateOrUpdate) {
-                                    log.info("Create Or Update");
-                                    CreateOrUpdate createOrUpdate = (CreateOrUpdate) input.opBody();
-                                    createOrUpdate.contexts().forEach(
-                                            context -> {
-                                                log.info("Context {}", context);
-                                                String key = context.contextId().fpcIdentity().union().string();
-                                                sessionContextsMap.computeIfAbsent(key, k -> new ArrayList<>()).add(context);
-                                                context.dpns().forEach(
-                                                        dpn -> {
-                                                            if (context.instructions().instrType() instanceof Instr3GppMob) {
-                                                                log.info("3GPP Instructions");
-                                                                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,
-                                                                        clientId = input.clientId().fpcIdentity().union().int64(),
-                                                                        contextId = context.contextId().fpcIdentity().union().int64();
-
-                                                                BigInteger opId = input.opId().uint64(),
-                                                                        imsi = context.imsi().uint64();
-
-                                                                short ebi = context.ebi().uint8(),
-                                                                        lbi = context.lbi().uint8();
+            for (ModelObject modelObject : tenantService.getModelObjects(rpcInput.data(), configureResourceId)) {
+                DefaultConfigureInput input = (DefaultConfigureInput) modelObject;
+                switch (input.opType()) {
+                    case CREATE:
+                    case UPDATE:
+                        if (input.opBody() instanceof CreateOrUpdate) {
+                            CreateOrUpdate createOrUpdate = (CreateOrUpdate) input.opBody();
+                            if (input.opType().equals(OpTypeEnum.CREATE)) {
+                                configureOutput = tenantService.configureCreate(
+                                        createOrUpdate,
+                                        input.clientId(),
+                                        input.opId()
+                                );
+                            } else {
+                                configureOutput = tenantService.configureUpdate(
+                                        createOrUpdate,
+                                        input.clientId(),
+                                        input.opId()
+                                );
+                            }
+                        }
+                        break;
+                    case QUERY:
+                        break;
+                    case DELETE:
+                        if (input.opBody() instanceof DeleteOrQuery) {
+                            DeleteOrQuery deleteOrQuery = (DeleteOrQuery) input.opBody();
+                            // TODO: move to tenant service
+                            deleteOrQuery.targets().forEach(
+                                    target -> {
+                                        log.info("target {}", target);
+                                        String targetStr = target.target().union().string();
+                                        sessionContextsMap.getOrDefault(targetStr, Lists.newArrayList()).parallelStream().forEach(
+                                                context -> {
+                                                    log.info("context {}", context);
+                                                    context.dpns().forEach(
+                                                            dpn -> {
+                                                                log.info("DPN {}", dpn);
+                                                                Long teid;
+                                                                if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+                                                                    teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+                                                                } else {
+                                                                    return;
+                                                                }
 
                                                                 Short dpnTopic = DpnApi.getTopicFromNode(nodeNetworkMap.get(dpn.dpnId().fpcIdentity().union().string()));
 
-                                                                if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
-                                                                    s1u_sgw_gtpu_teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+                                                                if (targetStr.endsWith("ul") || targetStr.endsWith("dl")) {
+                                                                    log.info("DELETE Bearer");
+                                                                    DpnApi.delete_bearer(
+                                                                            dpnTopic,
+                                                                            teid
+                                                                    );
                                                                 } else {
-                                                                    return;
-                                                                }
-                                                                if (context.dl().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
-                                                                    s1u_enb_gtpu_teid = ((ThreegppTunnel) context.dl().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
-                                                                } else {
-                                                                    return;
-                                                                }
-
-                                                                if (input.opType().equals(OpTypeEnum.CREATE)) {
-                                                                    if (commands.contains("session")) {
-                                                                        log.info("CREATE session");
-                                                                        DpnApi.create_session(
-                                                                                dpnTopic,
-                                                                                imsi,
-                                                                                Ip4Prefix.valueOf(context.delegatingIpPrefixes().get(0).toString()).address(),
-                                                                                ebi,
-                                                                                ulLocalAddress,
-                                                                                s1u_sgw_gtpu_teid,
-                                                                                clientId,
-                                                                                opId,
-                                                                                contextId
-                                                                        );
-
-                                                                        if (commands.contains("downlink")) {
-                                                                            log.info("CREATE session downlink");
-                                                                            DpnApi.modify_bearer_dl(
-                                                                                    dpnTopic,
-                                                                                    s1u_sgw_gtpu_teid,
-                                                                                    dlRemoteAddress,
-                                                                                    s1u_enb_gtpu_teid,
-                                                                                    clientId,
-                                                                                    opId
-                                                                            );
-                                                                        }
-                                                                    } else if (commands.contains("indirect-forward")) {
-                                                                        // TODO - Modify API for Indirect Forwarding to/from another SGW
-                                                                    } else if (commands.contains("uplink")) {
-                                                                        log.info("CREATE uplink");
-                                                                        DpnApi.create_bearer_ul(
-                                                                                dpnTopic,
-                                                                                imsi,
-                                                                                lbi,
-                                                                                ebi,
-                                                                                ulLocalAddress,
-                                                                                s1u_sgw_gtpu_teid
-                                                                        );
-                                                                    }
-                                                                } else {
-                                                                    if (commands.contains("downlink")) {
-                                                                        log.info("UPDATE downlink");
-                                                                        if (context.dl().lifetime() >= 0L) {
-                                                                            DpnApi.modify_bearer_dl(
-                                                                                    dpnTopic,
-                                                                                    dlRemoteAddress,
-                                                                                    s1u_enb_gtpu_teid,
-                                                                                    dlLocalAddress,
-                                                                                    clientId,
-                                                                                    opId,
-                                                                                    contextId
-                                                                            );
-                                                                        } else {
-                                                                            DpnApi.delete_bearer(
-                                                                                    dpnTopic,
-                                                                                    s1u_enb_gtpu_teid
-                                                                            );
-                                                                        }
-                                                                    }
-                                                                    if (commands.contains("uplink")) {
-                                                                        log.info("UPDATE uplink");
-                                                                        if (context.ul().lifetime() >= 0L) {
-                                                                            DpnApi.modify_bearer_ul(
-                                                                                    dpnTopic,
-                                                                                    ulLocalAddress,
-                                                                                    s1u_enb_gtpu_teid,
-                                                                                    s1u_sgw_gtpu_teid
-                                                                            );
-                                                                        } else {
-                                                                            DpnApi.delete_bearer(
-                                                                                    dpnTopic,
-                                                                                    s1u_sgw_gtpu_teid
-                                                                            );
-                                                                        }
-                                                                    }
+                                                                    log.info("DELETE session");
+                                                                    DpnApi.delete_session(
+                                                                            dpnTopic,
+                                                                            context.lbi().uint8(),
+                                                                            teid,
+                                                                            input.clientId().fpcIdentity().union().int64(),
+                                                                            input.opId().uint64(),
+                                                                            context.contextId().fpcIdentity().union().int64()
+                                                                    );
                                                                 }
                                                             }
-                                                        }
-                                                );
-                                            }
-                                    );
-                                }
-                                break;
-                            case QUERY:
-                                break;
-                            case DELETE:
-                                if (input.opBody() instanceof DeleteOrQuery) {
-                                    DeleteOrQuery deleteOrQuery = (DeleteOrQuery) input.opBody();
-                                    log.info("Delete Or Query");
-
-                                    deleteOrQuery.targets().forEach(
-                                            target -> {
-                                                log.info("target {}", target);
-                                                String targetStr = target.target().union().string();
-                                                sessionContextsMap.getOrDefault(targetStr, Lists.newArrayList()).parallelStream().forEach(
-                                                        context -> {
-                                                            log.info("context {}", context);
-                                                            context.dpns().forEach(
-                                                                    dpn -> {
-                                                                        log.info("DPN {}", dpn);
-                                                                        Long teid;
-                                                                        if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
-                                                                            teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
-                                                                        } else {
-                                                                            return;
-                                                                        }
-
-                                                                        Short dpnTopic = DpnApi.getTopicFromNode(nodeNetworkMap.get(dpn.dpnId().fpcIdentity().union().string()));
-
-                                                                        if (targetStr.endsWith("ul") || targetStr.endsWith("dl")) {
-                                                                            log.info("DELETE Bearer");
-                                                                            DpnApi.delete_bearer(
-                                                                                    dpnTopic,
-                                                                                    teid
-                                                                            );
-                                                                        } else {
-                                                                            log.info("DELETE session");
-                                                                            DpnApi.delete_session(
-                                                                                    dpnTopic,
-                                                                                    context.lbi().uint8(),
-                                                                                    teid,
-                                                                                    input.clientId().fpcIdentity().union().int64(),
-                                                                                    input.opId().uint64(),
-                                                                                    context.contextId().fpcIdentity().union().int64()
-                                                                            );
-                                                                        }
-                                                                    }
-                                                            );
-                                                        }
-                                                );
-                                            }
-                                    );
-                                }
-                                break;
+                                                    );
+                                                }
+                                        );
+                                    }
+                            );
                         }
-                    }
-            );
-
-
+                        break;
+                }
+                configureOutput.opId(input.opId());
+            }
         } 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));
+        } finally {
+            tenantService.getTenants().ifPresent(tenants -> tenantService.updateNode(tenants));
         }
 
         ResourceData dataNode = modelConverter.createDataNode(
-                DefaultModelObjectData.builder().addModelObject(configureOutput).build()
+                DefaultModelObjectData.builder()
+                        .addModelObject(configureOutput)
+                        .build()
         );
         return new RpcOutput(RpcOutput.Status.RPC_SUCCESS, dataNode.dataNodes().get(0));
     }
@@ -465,16 +308,6 @@
         return null;
     }
 
-//    @Override
-//    public void registerClient(RegisterClientInput input) {
-//        tenantService.registerClient(input.clientId(), input.tenantId());
-//    }
-//
-//    @Override
-//    public void deregisterClient(DeregisterClientInput input) {
-//        tenantService.deregisterClient(input.clientId());
-//    }
-
     private class InternalNetworkConfigListener implements NetworkConfigListener {
 
         @Override
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..c3a6a77
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcUtil.java
@@ -0,0 +1,89 @@
+/*
+ * 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.onosproject.restconf.utils.RestconfUtils;
+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 java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * Helper class which stores all the static variables.
+ */
+class FpcUtil {
+    static final int MAX_EVENTS = 1000;
+    static final int MAX_BATCH_MS = 5000;
+    static final int MAX_IDLE_MS = 1000;
+    static final String TIMER = "dynamic-config-fpcagent-timer";
+    static final String UNKNOWN_EVENT = "FPC Agent listener: unknown event: {}";
+    static final String EVENT_NULL = "Event cannot be null";
+    static final String FPC_APP_ID = "org.onosproject.fpcagent";
+
+    // Resource ID for Configure DPN RPC command
+    static ResourceId configureDpnResourceId;
+    // Resource ID for Configure RPC command
+    static ResourceId configureResourceId;
+    // Resource ID for tenants data
+    static ResourceId tenantsResourceId;
+    static ResourceId registerClientResourceId;
+    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();
+        }
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
index e51efed..f197bdb 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
@@ -1,28 +1,49 @@
 package org.onosproject.fpcagent;
 
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Service;
-import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+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.DpnApi;
+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.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.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.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.FpcTopology;
-import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.fpctopology.Dpns;
-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.fpccontext.Dpns;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.mobilityinfo.mobprofileparameters.ThreegppTunnel;
+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.util.List;
-import java.util.Map;
-import java.util.Optional;
+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)
@@ -30,34 +51,74 @@
 public class TenantManager implements TenantService {
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    private Map<FpcIdentity, Tenant> tenantMap = Maps.newHashMap();
-    private Map<ClientIdentifier, Tenant> clientIdMap = Maps.newHashMap();
+    private final IetfDmmFpcagentOpParam fpcAgentData = new IetfDmmFpcagentOpParam();
 
-    private Map<FpcDpnId, List<FpcDpnId>> vdpnDpnsMap = Maps.newConcurrentMap();
-    private Map<FpcDpnId, Contexts> vdpnContextsMap = Maps.newConcurrentMap();
+    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;
 
     @Activate
     protected void activate() {
+        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");
     }
 
-    public void addTenant(FpcIdentity tenantId) {
-        Tenant tenant = new DefaultTenant();
-        tenant.tenantId(tenantId);
-        tenant.fpcTopology(new DefaultFpcTopology());
-        tenant.fpcMobility(new DefaultFpcMobility());
-        tenant.fpcPolicy(new DefaultFpcPolicy());
+    @Override
+    public Optional<Tenant> getDefaultTenant() {
+        return fpcAgentData.tenants().tenant().stream()
+                .filter(tenant -> tenant.tenantId().equals(getFpcIdentity.apply("default")))
+                .findFirst();
+    }
 
-        tenantMap.put(tenantId, tenant);
+    @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 Optional.ofNullable(tenantMap.get(tenantId));
+        return fpcAgentData.tenants().tenant().stream()
+                .filter(tenant -> tenant.tenantId().equals(tenantId))
+                .findFirst();
     }
 
     public Optional<Tenant> getTenant(ClientIdentifier clientId) {
@@ -68,33 +129,380 @@
         return getTenant(tenantId).map(tenant -> clientIdMap.put(clientId, tenant));
     }
 
-    public Tenant deregisterClient(ClientIdentifier clientId) {
-        return clientIdMap.remove(clientId);
+    public Optional<Tenant> deregisterClient(ClientIdentifier clientId) {
+        return Optional.ofNullable(clientIdMap.remove(clientId));
     }
 
-    private boolean dpnIdExists(FpcIdentity tenantId, FpcDpnId fpcDpnId) {
-        return getTenant(tenantId).map(
-                tenant -> {
-                    FpcTopology fpcTopology = tenant.fpcTopology();
-                    return fpcTopology.dpns() != null &&
-                            fpcTopology.dpns().stream().anyMatch(dpn -> dpn.dpnId().equals(fpcDpnId));
+    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<>();
+
+        try {
+            DefaultCommonSuccess defaultCommonSuccess = new DefaultCommonSuccess();
+            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.");
                 }
-        ).orElse(false);
-    }
 
-    private Optional<FpcDpnId> getDpnId(String nodeId, String networkId) {
-        return getTenant(getFpcIdentity.apply("default")).map(
-                tenant -> {
-                    FpcTopology fpcTopology = tenant.fpcTopology();
-                    if (fpcTopology.dpns() != null) {
-                        return fpcTopology.dpns().stream()
-                                .filter(dpn -> dpn.nodeId().equals(nodeId))
-                                .filter(dpn -> dpn.networkId().equals(networkId))
-                                .findFirst()
-                                .map(Dpns::dpnId);
+                for (Dpns dpn : context.dpns()) {
+                    if (!getDefaultTenant().map(
+                            tenant -> tenant.fpcTopology().dpns() != null &&
+                                    tenant.fpcTopology().dpns().stream()
+                                            .anyMatch(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+                    ).orElse(false)) {
+                        throw new IllegalStateException("DPN ID is not registered to the topology.");
                     }
-                    return Optional.<FpcDpnId>empty();
+
+                    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();
+
+                        Short dpnTopic = DpnApi.getTopicFromNode(dpn.dpnId().toString());
+
+                        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(() -> DpnApi.create_session(
+                                    dpnTopic,
+                                    imsi,
+                                    Ip4Prefix.valueOf(context.delegatingIpPrefixes().get(0).toString()).address(),
+                                    ebi,
+                                    ulLocalAddress,
+                                    s1u_sgw_gtpu_teid,
+                                    cId,
+                                    opId,
+                                    contextId
+                            )));
+
+                            if (commands.contains("downlink")) {
+                                tasks.add(Executors.callable(() -> DpnApi.modify_bearer_dl(
+                                        dpnTopic,
+                                        s1u_sgw_gtpu_teid,
+                                        dlRemoteAddress,
+                                        s1u_enb_gtpu_teid,
+                                        cId,
+                                        opId
+                                )));
+                            }
+                        } 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(() -> DpnApi.create_bearer_ul(
+                                    dpnTopic,
+                                    imsi,
+                                    lbi,
+                                    ebi,
+                                    ulLocalAddress,
+                                    s1u_sgw_gtpu_teid
+                            )));
+                        }
+                    }
                 }
-        ).orElse(Optional.empty());
+            }
+
+            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));
+
+            create.contexts().forEach(
+                    contexts -> getDefaultTenant().ifPresent(
+                            tenant -> tenant.fpcMobility().addToContexts(convertContext(contexts))
+                    )
+            );
+        } catch (Exception 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()
+                                .parallelStream()
+                                .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()
+                                    .stream()
+                                    .anyMatch(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();
+
+
+                        Short dpnTopic = DpnApi.getTopicFromNode(dpn.dpnId().toString());
+
+                        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(() ->
+                                        DpnApi.modify_bearer_dl(
+                                                dpnTopic,
+                                                dlRemoteAddress,
+                                                s1u_enb_gtpu_teid,
+                                                dlLocalAddress,
+                                                cId,
+                                                opId,
+                                                contextId
+                                        )
+                                ));
+                            } else {
+                                tasks.add(Executors.callable(() ->
+                                        DpnApi.delete_bearer(
+                                                dpnTopic,
+                                                s1u_enb_gtpu_teid
+                                        )
+                                ));
+                            }
+                        }
+                        if (commands.contains("uplink")) {
+                            if (context.ul().lifetime() >= 0L) {
+                                tasks.add(Executors.callable(() ->
+                                        DpnApi.modify_bearer_ul(
+                                                dpnTopic,
+                                                ulLocalAddress,
+                                                s1u_enb_gtpu_teid,
+                                                s1u_sgw_gtpu_teid
+                                        )
+                                ));
+                            } else {
+                                tasks.add(Executors.callable(() ->
+                                        DpnApi.delete_bearer(
+                                                dpnTopic,
+                                                s1u_sgw_gtpu_teid
+                                        )
+                                ));
+                            }
+                        }
+                    }
+                }
+            }
+
+            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) {
+            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;
+    }
+
+    /**
+     * 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) {
+            DynamicConfigEvent event = Iterables.getLast(events);
+            log.debug("processItems {}", 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
index f0f11a5..60118ff 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java
@@ -1,13 +1,32 @@
 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.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 {
-    void addTenant(FpcIdentity tenantId);
+    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);
 
@@ -15,5 +34,17 @@
 
     Optional<Tenant> registerClient(ClientIdentifier clientId, FpcIdentity tenantId);
 
-    Tenant deregisterClient(ClientIdentifier clientId);
+    Optional<Tenant> deregisterClient(ClientIdentifier clientId);
+
+    DefaultConfigureOutput configureCreate(
+            CreateOrUpdate create,
+            ClientIdentifier clientId,
+            OpIdentifier operationId
+    );
+
+    DefaultConfigureOutput configureUpdate(
+            CreateOrUpdate create,
+            ClientIdentifier clientId,
+            OpIdentifier operationId
+    );
 }
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
index 6573ae8..d023cb8 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java
@@ -1,11 +1,23 @@
 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 {
@@ -101,4 +113,55 @@
     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/DpnApi.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnApi.java
index 4ea7b39..43d4759 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnApi.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnApi.java
@@ -29,6 +29,8 @@
  */
 public class DpnApi {
     protected static final Logger log = LoggerFactory.getLogger(DpnApi.class);
+    private static final Map<String, FpcDpnId> uplinkDpnMap;
+    private static final Map<String, Short> topicToNodeMap;
     /**
      * Topic for broadcasting
      */
@@ -44,7 +46,6 @@
     private static byte BYE = 0b0000_1001;
     private static byte SEND_ADC_TYPE = 0b001_0001;
     private static byte DDN_ACK = 0b0000_0110;
-
     private static byte DPN_HELLO = 0b0000_0001;
     private static byte DPN_BYE = 0b0000_0010;
     private static byte DOWNLINK_DATA_NOTIFICATION = 0b0000_0101;
@@ -52,8 +53,6 @@
     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";
-    private static final Map<String, FpcDpnId> uplinkDpnMap;
-    private static final Map<String, Short> topicToNodeMap;
 
     static {
         uplinkDpnMap = Maps.newConcurrentMap();
@@ -312,9 +311,9 @@
      * @param sponsor_ID   - Sponsor ID
      */
     public static void send_ADC_rules(Short topic,
-                               String domain_name, String ip,
-                               Short drop, Long rating_group,
-                               Long service_ID, String sponsor_ID) {
+                                      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);
@@ -409,9 +408,11 @@
                 status = DPNStatusIndication.Status.OVERLOAD_INDICATION;
             } else if (buf[3] == DPN_HELLO) {
                 status = DPNStatusIndication.Status.HELLO;
+                log.info("Hello {} on topic {}", key, buf[2]);
                 topicToNodeMap.put(key, (short) buf[2]);
             } else if (buf[3] == DPN_BYE) {
                 status = DPNStatusIndication.Status.BYE;
+                log.info("Bye {}", key);
                 topicToNodeMap.remove(key);
             }
             return new AbstractMap.SimpleEntry<>(uplinkDpnMap.get(key), new DPNStatusIndication(status, key));
@@ -441,6 +442,7 @@
          * Node Reference of the DPN
          */
         public Short nodeRef;
+
         /**
          * Constructor providing the DPN and its associated Status.
          *
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/NBWorkManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/NBWorkManager.java
deleted file mode 100644
index d79cf69..0000000
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/NBWorkManager.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.onosproject.fpcagent.workers;
-
-import org.apache.commons.lang.exception.ExceptionUtils;
-import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.ConfigureInput;
-import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configurebundles.ConfigureBundlesInput;
-import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.eventderegister.EventDeregisterInput;
-import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.eventregister.EventRegisterInput;
-import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.probe.ProbeInput;
-import org.onosproject.yang.model.RpcInput;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-
-public class NBWorkManager implements AutoCloseable {
-    private static final Logger log = LoggerFactory.getLogger(NBWorkManager.class);
-
-    // TODO: add store
-    private static NBWorkManager _instance = null;
-    private final BlockingQueue<Object> blockingQueue;
-    private final int poolSize;
-    private boolean run;
-
-    protected NBWorkManager(int poolSize) {
-        this.blockingQueue = new LinkedBlockingQueue<>();
-        this.poolSize = poolSize;
-        this.run = true;
-    }
-
-    public static NBWorkManager createInstance(int poolSize) {
-        if (_instance == null) {
-            _instance = new NBWorkManager(poolSize);
-        }
-        return _instance;
-    }
-
-    public static NBWorkManager getInstance() {
-        return _instance;
-    }
-
-    public void submit(RpcInput input) {
-        try {
-            blockingQueue.put(input);
-        } catch (InterruptedException e) {
-            log.error(ExceptionUtils.getFullStackTrace(e));
-        }
-    }
-
-    public void open() {
-        ExecutorService executorService = Executors.newFixedThreadPool(this.poolSize);
-        executorService.submit(() -> {
-            while ((!Thread.currentThread().isInterrupted()) && run) {
-                try {
-                    Object o = blockingQueue.take();
-                    if (o instanceof ConfigureInput) {
-
-                    } else if (o instanceof ConfigureBundlesInput) {
-
-                    } else if (o instanceof EventRegisterInput) {
-
-                    } else if (o instanceof EventDeregisterInput) {
-
-                    } else if (o instanceof ProbeInput) {
-
-                    }
-                } catch (InterruptedException e) {
-                    log.error(ExceptionUtils.getFullStackTrace(e));
-                }
-            }
-        });
-    }
-
-    @Override
-    public void close() throws Exception {
-        run = false;
-    }
-}
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
index 35701fe..ec7321e 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java
@@ -7,10 +7,7 @@
 import org.zeromq.ZMQ;
 
 import java.nio.ByteBuffer;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.*;
 
 public class ZMQSBPublisherManager implements AutoCloseable {
     private static final Logger log = LoggerFactory.getLogger(ZMQSBPublisherManager.class);
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
index cddd6d4..09617c0 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java
@@ -195,6 +195,7 @@
                 byte[] contents = subscriber.recv();
                 byte topic = contents[0];
                 byte messageType = contents[1];
+                log.info("Received {}", contents);
                 switch (topic) {
                     case 1:
                         if (messageType == ASSIGN_CONFLICT && toInt(contents, 3) != controllerSourceId) {
@@ -207,10 +208,8 @@
                         Map.Entry<FpcDpnId, Object> entry = DpnApi.decode(contents);
                         if (entry != null) {
                             if (entry.getValue() instanceof DownlinkDataNotification) {
-//                                log.info("DownlinkDataNotification");
                             } else if (entry.getValue() instanceof DpnApi.DPNStatusIndication) {
                                 DpnApi.DPNStatusIndication dpnStatus = (DpnApi.DPNStatusIndication) entry.getValue();
-//                                log.info("DPNStatusIndication");
                                 if (dpnStatus.getStatus() == DpnApi.DPNStatusIndication.Status.HELLO) {
                                     sendHelloReply(dpnStatus);
                                 }
diff --git a/models/fpcagent/src/main/yang/fpc-config.yang b/models/fpcagent/src/main/yang/fpc-config.yang
index 10a656c..9e28370 100644
--- a/models/fpcagent/src/main/yang/fpc-config.yang
+++ b/models/fpcagent/src/main/yang/fpc-config.yang
@@ -1,6 +1,6 @@
 module fpc-config {
     yang-version 1;
-    namespace "urn:opendaylight:fpc:config";
+    namespace "urn:onos:fpc:config";
     prefix fpc-config;
 
     description
diff --git a/models/fpcagent/src/main/yang/fpc.yang b/models/fpcagent/src/main/yang/fpc.yang
index 5cd95f4..2996283 100644
--- a/models/fpcagent/src/main/yang/fpc.yang
+++ b/models/fpcagent/src/main/yang/fpc.yang
@@ -1,6 +1,6 @@
 module fpc {
     yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:fpc";
+    namespace "urn:onos:params:xml:ns:yang:fpc";
     prefix "fpc";
 
     import ietf-dmm-fpcagent { prefix fpcagent; }
@@ -145,7 +145,7 @@
       }
     }
 
-    rpc register_client {
+    rpc register-client {
       input {
         uses fpc:connection-config;
       }
@@ -154,7 +154,7 @@
       }
     }
 
-    rpc deregister_client {
+    rpc deregister-client {
       input {
         leaf client-id {
           type fpcagent:client-identifier;
diff --git a/scripts/addDPN.sh b/scripts/addDPN.sh
old mode 100644
new mode 100755
index 00f0609..9a07776
--- a/scripts/addDPN.sh
+++ b/scripts/addDPN.sh
@@ -1,13 +1,13 @@
 curl -i --header "Content-type: application/json" --request POST -u onos:rocks --data '{
     "dpns": [
         {
-            "dpn-id": "dpn1",
+            "dpn-id": "1",
             "dpn-name": "site1-anchor1",
             "dpn-groups": [
                 "foo"
             ],
-        "node-id": "node1",
-        "network-id": "network1"
+            "node-id": "node1",
+            "network-id": "network1"
         }
     ]
-}' http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology
\ No newline at end of file
+}' 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology'
diff --git a/scripts/createRPC.sh b/scripts/createRPC.sh
old mode 100644
new mode 100755
index dc2fb9e..e920070
--- a/scripts/createRPC.sh
+++ b/scripts/createRPC.sh
@@ -5,7 +5,45 @@
         "client-id": "1",
         "contexts": [
             {
-                "context-id": 202374885,
+                "context-id": 202374886,
+                "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"
+                }
+            },
+            {
+                "context-id": 202374887,
                 "delegating-ip-prefixes": [
                     "192.168.1.5/32"
                 ],
@@ -48,4 +86,4 @@
         "op-type": "create",
         "session-state": "complete"
     }
-}' 'http://localhost:8181/onos/restconf/operations/ietf-dmm-fpcagent:configure'
+}' 'http://localhost:8181/onos/restconf/operations/ietf-dmm-fpcagent:configure' | python -m json.tool
diff --git a/scripts/deleteDPN.sh b/scripts/deleteDPN.sh
old mode 100644
new mode 100755
index 570da07..08b0dd4
--- a/scripts/deleteDPN.sh
+++ b/scripts/deleteDPN.sh
@@ -1,2 +1,2 @@
 #!/bin/bash
-curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology/dpns=dpn1'
\ No newline at end of file
+curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology/dpns=1'
diff --git a/scripts/deleteRPC.sh b/scripts/deleteRPC.sh
old mode 100644
new mode 100755
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..e3826a5
--- /dev/null
+++ b/scripts/forwarder_subscriber_with_ACK.py
@@ -0,0 +1,253 @@
+#!/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))
+    count = 0
+    while True:
+        time.sleep(1)
+        sys.stdout.write("\r"+str(5-count)+" ")
+        sys.stdout.flush()
+        count += 1
+        if(count > 5):
+            print "\n"
+            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."
+
+rec_port = "5560"
+send_port = "5559"
+# Socket to talk to server
+context = zmq.Context()
+socket = context.socket(zmq.SUB)
+pub_socket = context.socket(zmq.PUB)
+socket.connect ("tcp://localhost:%s" % rec_port)
+pub_socket.connect("tcp://localhost:%s" % send_port)
+topicfilter = ""
+controller_topic= 252
+socket.setsockopt(zmq.SUBSCRIBE, topicfilter)
+print "Listening to port ", rec_port
+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 = socket.recv()
+    ts = time.time()
+    st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
+ 
+    topic,msgnum = struct.unpack('!BB',string[:2])
+
+    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
+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
old mode 100644
new mode 100755
index bf4b6e1..abe3bd1
--- a/scripts/getTenants.sh
+++ b/scripts/getTenants.sh
@@ -1,2 +1,2 @@
 #!/bin/bash
-curl -u onos:rocks http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants
\ No newline at end of file
+curl -u onos:rocks http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants | python -m json.tool