initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bff2d76
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.iml
diff --git a/apps/fpcagent/BUCK b/apps/fpcagent/BUCK
new file mode 100644
index 0000000..c57ddf9
--- /dev/null
+++ b/apps/fpcagent/BUCK
@@ -0,0 +1,77 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:JACKSON',
+    '//lib:KRYO',
+    '//models/fpcagent:onos-models-fpcagent',
+    '//models/common:onos-models-common',
+    '//apps/config:onos-apps-config',
+    '//lib:onos-yang-model',
+    '//core/api:onos-api',
+    '//lib:javax.ws.rs-api',
+    '//utils/rest:onlab-rest',
+    '//core/store/serializers:onos-core-serializers',
+    ':zeromq',
+    ':json',
+]
+
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+    '//lib:TEST_REST',
+    '//utils/osgi:onlab-osgi-tests',
+]
+
+BUNDLES = [
+    '//apps/fpcagent:onos-apps-fpcagent',
+]
+
+EXCLUDED_BUNDLES = [
+    ':zeromq',
+    ':json',
+]
+
+APPS = [
+    'org.onosproject.models.fpcagent',
+    'org.onosproject.yang',
+    'org.onosproject.yang-gui',
+    'org.onosproject.config',
+    'org.onosproject.restconf',
+    'org.onosproject.protocols.restconfserver',
+]
+
+osgi_jar_with_tests(
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+    web_context = '/onos/fpcagent',
+    api_title = 'FPC Agent REST API',
+    api_package = 'org.onosproject.fpcagent.rest',
+    api_version = '1.0',
+    api_description = 'FPC Agent REST API',
+)
+
+onos_app(
+    app_name = 'org.onosproject.fpcagent',
+    title = 'YANG FPC Agent',
+    category = 'Traffic Steering',
+    url = 'http://onosproject.org',
+    description = 'FPC Agent YANG Application',
+    required_apps = APPS,
+    excluded_bundles = EXCLUDED_BUNDLES,
+)
+
+remote_jar (
+  name = 'json',
+  out = 'json-20090211.jar',
+  url = 'mvn:org.json:json:jar:20090211',
+  sha1 = 'c183aa3a2a6250293808bba12262c8920ce5a51c',
+  maven_coords = 'org.json:json:jar:NON-OSGI:20090211',
+  visibility = [ 'PUBLIC' ],
+)
+
+remote_jar (
+  name = 'zeromq',
+  out = 'jeromq-0.3.5.jar',
+  url = 'mvn:org.zeromq:jeromq:jar:0.3.5',
+  sha1 = '39a79082570d114bb5433762e836e4dd9c38b03d',
+  maven_coords = 'org.zeromq:jeromq:0.3.5',
+  visibility = [ 'PUBLIC' ],
+)
diff --git a/apps/fpcagent/fpcagent.json b/apps/fpcagent/fpcagent.json
new file mode 100644
index 0000000..5b820df
--- /dev/null
+++ b/apps/fpcagent/fpcagent.json
@@ -0,0 +1,30 @@
+{
+  "apps": {
+    "org.onosproject.fpcagent": {
+      "fpcagent": {
+        "monitor-threads": 4,
+        "scheduled-monitors-poolsize": 4,
+        "dpn-listener-uri": "tcp://127.0.0.1:5569",
+        "dpn-listener-id": 1,
+        "dpn-client-uri": "tcp://127.0.0.1:5559",
+        "dpn-client-threads": 5,
+        "metricsupdate-ms": 10000,
+        "mobilityupdate-ms": 30000,
+        "activation-threads": 5,
+        "target-read-limit": 10,
+        "http-notifier-clients": 3,
+        "zmq-nbi-server-poolsize": 1,
+        "zmq-nbi-server-uri": "tcp://127.0.0.1:5570",
+        "zmq-nbi-inproc-uri": "inproc://backend",
+        "zmq-nbi-handler-poolsize": 10,
+        "http-nio2-nb-poolsize": 80,
+        "http-nio2-nb-port": 9292,
+        "node-id": "node0",
+        "network-id": "network1",
+        "zmq-broadcast-all": "1",
+        "zmq-broadcast-controllers": "2",
+        "zmq-broadcast-dpns": "3"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/Configure.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/Configure.java
new file mode 100644
index 0000000..d6b277a
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/Configure.java
@@ -0,0 +1,7 @@
+package org.onosproject.fpcagent;
+
+import org.onosproject.yang.gen.v1.fpc.rev20150105.FpcService;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.IetfDmmFpcagentService;
+
+public interface Configure extends IetfDmmFpcagentService, FpcService {
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java
new file mode 100644
index 0000000..b9cbb9f
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java
@@ -0,0 +1,25 @@
+package org.onosproject.fpcagent;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+import org.onosproject.net.config.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+public class FpcConfig extends Config<ApplicationId> {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    public Optional<ConfigHelper> getConfig() {
+        try {
+            return Optional.of(mapper.treeToValue(object, ConfigHelper.class));
+        } catch (JsonProcessingException e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+        return Optional.empty();
+    }
+}
+
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
new file mode 100644
index 0000000..31ca0f0
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.fpcagent;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.felix.scr.annotations.*;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.fpcagent.dto.configure.Context;
+import org.onosproject.fpcagent.dto.dpn.AddDpn;
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+import org.onosproject.fpcagent.helpers.DpnApi;
+import org.onosproject.fpcagent.workers.ZMQSBPublisherManager;
+import org.onosproject.fpcagent.workers.ZMQSBSubscriberManager;
+import org.onosproject.net.config.*;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.deregisterclient.DeregisterClientInput;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.registerclient.RegisterClientInput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.ConfigureInput;
+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.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.mobilityinfo.mobprofileparameters.ThreegppTunnel;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.ietfdmmthreegpp.threegppinstr.Bits;
+import org.onosproject.yang.model.RpcInput;
+import org.onosproject.yang.model.RpcOutput;
+import org.onosproject.yang.model.RpcRegistry;
+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;
+
+/**
+ * Fpc Manager.
+ */
+@Component(immediate = true)
+@Service
+public class FpcManager implements Configure, FpcService {
+    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();
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TenantService tenantService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private RpcRegistry rpcRegistry;
+
+    /* Services */
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private NetworkConfigRegistry registry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private NetworkConfigService configService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private CoreService coreService;
+
+//    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+//    protected ModelConverter modelConverter;
+//
+//    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+//    protected DynamicConfigService dynamicConfigService;
+
+    /* Variables */
+    private ApplicationId appId;
+    private FpcConfig fpcConfig;
+
+    private HashMap<String, ArrayList<Contexts>> sessionContextsMap = Maps.newHashMap();
+    private HashMap<String, ArrayList<Context>> sessionContextsRestMap = Maps.newHashMap();
+    private HashMap<String, String> nodeNetworkMap = Maps.newHashMap();
+
+    /* Config */
+    private ConfigFactory<ApplicationId, FpcConfig> fpcConfigConfigFactory =
+            new ConfigFactory<ApplicationId, FpcConfig>(
+                    SubjectFactories.APP_SUBJECT_FACTORY, FpcConfig.class, "fpcagent") {
+                @Override
+                public FpcConfig createConfig() {
+                    return new FpcConfig();
+                }
+            };
+
+    @Activate
+    protected void activate() {
+        appId = coreService.registerApplication(FPC_APP_ID);
+        configService.addListener(configListener);
+        registry.registerConfigFactory(fpcConfigConfigFactory);
+
+        rpcRegistry.registerRpcService(this);
+
+        tenantService.addTenant(getFpcIdentity.apply("default"));
+
+        log.info("FPC Agent Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        configService.removeListener(configListener);
+        registry.unregisterConfigFactory(fpcConfigConfigFactory);
+
+        // TODO check if null before closing
+        ZMQSBSubscriberManager.getInstance().close();
+        ZMQSBPublisherManager.getInstance().close();
+
+        rpcRegistry.unregisterRpcService(this);
+
+        log.info("FPC Agent Stopped");
+    }
+
+    public void init() {
+
+        fpcConfig.getConfig().ifPresent(
+                helper -> {
+                    ZMQSBSubscriberManager.createInstance(
+                            helper.dpnListenerUri(),
+                            helper.zmqBroadcastAll(),
+                            helper.zmqBroadcastControllers(),
+                            helper.zmqBroadcastDpns(),
+                            helper.nodeId(),
+                            helper.networkId()
+                    );
+
+                    ZMQSBPublisherManager.createInstance(
+                            helper.dpnClientUri(),
+                            helper.dpnClientThreads()
+                    );
+
+                    ZMQSBPublisherManager.getInstance().open();
+                    ZMQSBSubscriberManager.getInstance().open();
+                }
+        );
+    }
+
+    @Override
+    public Optional<ConfigHelper> getConfig() {
+        return fpcConfig != null ? fpcConfig.getConfig() : Optional.empty();
+    }
+
+    private class InternalNetworkConfigListener implements NetworkConfigListener {
+
+        @Override
+        public void event(NetworkConfigEvent event) {
+            switch (event.type()) {
+                case CONFIG_REGISTERED:
+                case CONFIG_UNREGISTERED: {
+                    break;
+                }
+                case CONFIG_REMOVED: {
+                    if (event.configClass() == CONFIG_CLASS) {
+                        fpcConfig = null;
+                    }
+                    break;
+                }
+                case CONFIG_UPDATED:
+                case CONFIG_ADDED: {
+                    if (event.configClass() == CONFIG_CLASS) {
+                        event.config().ifPresent(config -> {
+                            fpcConfig = (FpcConfig) config;
+                            init();
+                        });
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+        }
+
+    }
+
+    @Override
+    public RpcOutput configureDpn(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput configure(RpcInput rpcInput) {
+        ConfigureInput input = (ConfigureInput) rpcInput;
+        switch (input.opType()) {
+            case CREATE:
+            case UPDATE:
+                if (input.opBody() instanceof CreateOrUpdate) {
+                    CreateOrUpdate createOrUpdate = (CreateOrUpdate) input.opBody();
+                    createOrUpdate.contexts().forEach(
+                            context -> {
+                                String key = context.contextId().fpcIdentity().union().string();
+                                sessionContextsMap.computeIfAbsent(key, k -> new ArrayList<>())
+                                        .add(context);
+                                context.dpns().forEach(
+                                        dpn -> {
+                                            if (input.instructions().instrType() instanceof Instr3GppMob) {
+
+                                                Instr3GppMob instr3GppMob = (Instr3GppMob) input.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();
+
+                                                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();
+                                                } 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")) {
+                                                        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")) {
+                                                            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")) {
+                                                        DpnApi.create_bearer_ul(
+                                                                dpnTopic,
+                                                                imsi,
+                                                                lbi,
+                                                                ebi,
+                                                                ulLocalAddress,
+                                                                s1u_sgw_gtpu_teid
+                                                        );
+                                                    }
+                                                } else {
+                                                    if (commands.contains("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")) {
+                                                        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
+                                                            );
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                );
+                            }
+                    );
+                }
+                break;
+            case QUERY:
+                break;
+            case DELETE:
+                if (input.opBody() instanceof DeleteOrQuery) {
+                    DeleteOrQuery deleteOrQuery = (DeleteOrQuery) input.opBody();
+
+                    deleteOrQuery.targets().forEach(
+                            target -> {
+                                String targetStr = target.target().union().string();
+                                sessionContextsMap.getOrDefault(targetStr, Lists.newArrayList()).parallelStream().forEach(
+                                        context -> context.dpns().forEach(
+                                                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")) {
+                                                        DpnApi.delete_bearer(
+                                                                dpnTopic,
+                                                                teid
+                                                        );
+                                                    } else {
+                                                        DpnApi.delete_session(
+                                                                dpnTopic,
+                                                                context.lbi().uint8(),
+                                                                teid,
+                                                                input.clientId().fpcIdentity().union().int64(),
+                                                                input.opId().uint64(),
+                                                                context.contextId().fpcIdentity().union().int64()
+                                                        );
+                                                    }
+                                                }
+                                        )
+                                );
+                            }
+                    );
+                }
+                break;
+        }
+
+        return null;
+    }
+
+    @Override
+    public RpcOutput configureBundles(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput eventRegister(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput eventDeregister(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput probe(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput registerClient(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public RpcOutput deregisterClient(RpcInput rpcInput) {
+        return null;
+    }
+
+    @Override
+    public void configure(org.onosproject.fpcagent.dto.configure.Configure configure) {
+        org.onosproject.fpcagent.dto.configure.ConfigureInput configureInput = configure.getConfigureInput();
+        if (configureInput.getOp_type().equals("create") || configureInput.getOp_type().equals("update")) {
+
+            configureInput.getContexts().forEach(
+                    context -> {
+                        String key = String.valueOf(context.getContext_id());
+                        sessionContextsRestMap.computeIfAbsent(key, k -> new ArrayList<>()).add(context);
+                        context.getDpns().forEach(dpn -> {
+                                    try {
+                                        String commands = context.getInstructions().getInstr_3gpp_mob();
+
+                                        Ip4Address ulLocalAddress = Ip4Address.valueOf(context.getUl().getTunnel_local_address()),
+                                                dlRemoteAddress = Ip4Address.valueOf(context.getDl().getTunnel_remote_address());
+
+                                        long s1u_sgw_gtpu_teid, s1u_enb_gtpu_teid,
+                                                clientId = Long.parseLong(configureInput.getClient_id()),
+                                                contextId = context.getContext_id();
+
+                                        BigInteger opId = BigInteger.valueOf(Long.parseLong(configureInput.getOp_id())),
+                                                imsi = BigInteger.valueOf(Long.parseLong(context.getImsi()));
+
+                                        short ebi = Short.parseShort(context.getEbi()),
+                                                lbi = Short.parseShort(context.getLbi());
+
+                                        Short dpnTopic = DpnApi.getTopicFromNode(nodeNetworkMap.get(dpn.getDpn_id()));
+
+
+                                        s1u_sgw_gtpu_teid = Long.parseLong(context.getUl().getMobility_tunnel_parameters().getTunnel_identifier());
+                                        s1u_enb_gtpu_teid = Long.parseLong(context.getDl().getMobility_tunnel_parameters().getTunnel_identifier());
+
+                                        if (configureInput.getOp_type().equals("create")) {
+                                            if (commands.contains("session")) {
+                                                DpnApi.create_session(
+                                                        dpnTopic,
+                                                        imsi,
+                                                        Ip4Prefix.valueOf(context.getDelegating_ip_prefixes().get(0)).address(),
+                                                        ebi,
+                                                        ulLocalAddress,
+                                                        s1u_sgw_gtpu_teid,
+                                                        clientId,
+                                                        opId,
+                                                        contextId
+                                                );
+
+
+                                                if (commands.contains("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")) {
+                                                DpnApi.create_bearer_ul(
+                                                        dpnTopic,
+                                                        imsi,
+                                                        lbi,
+                                                        ebi,
+                                                        ulLocalAddress,
+                                                        s1u_sgw_gtpu_teid
+                                                );
+                                            }
+                                        } else {
+                                            if (commands.contains("downlink")) {
+                                                DpnApi.delete_bearer(
+                                                        dpnTopic,
+                                                        s1u_enb_gtpu_teid
+                                                );
+                                            }
+                                            if (commands.contains("uplink")) {
+                                                DpnApi.delete_bearer(
+                                                        dpnTopic,
+                                                        s1u_sgw_gtpu_teid
+                                                );
+                                            }
+                                        }
+                                    } catch (Exception e) {
+                                        log.error(ExceptionUtils.getFullStackTrace(e));
+                                    }
+                                }
+                        );
+                    }
+            );
+
+        } else if (configureInput.getOp_type().equals("delete") || configureInput.getOp_type().equals("query")) {
+            configureInput.getTargets().forEach(
+                    target -> {
+                        String targetStr = target.getTarget();
+                        String s = StringUtils.substringBetween(targetStr, "contexts/", "/");
+                        if (s == null) {
+                            s = StringUtils.substringAfter(targetStr, "contexts/");
+                        }
+                        sessionContextsRestMap.getOrDefault(s, Lists.newArrayList()).forEach(
+                                context -> context.getDpns().forEach(
+                                        dpn -> {
+                                            Long teid = Long.valueOf(context.getUl().getMobility_tunnel_parameters().getTunnel_identifier());
+                                            Short dpnTopic = DpnApi.getTopicFromNode(nodeNetworkMap.get(dpn.getDpn_id()));
+
+                                            if (targetStr.endsWith("ul") || targetStr.endsWith("dl")) {
+                                                DpnApi.delete_bearer(
+                                                        dpnTopic,
+                                                        teid
+                                                );
+                                            } else {
+                                                DpnApi.delete_session(
+                                                        dpnTopic,
+                                                        Short.valueOf(context.getLbi()),
+                                                        teid,
+                                                        Long.valueOf(configureInput.getClient_id()),
+                                                        BigInteger.valueOf(Long.parseLong(configureInput.getOp_id())),
+                                                        Long.valueOf(context.getContext_id())
+                                                );
+                                            }
+                                        }
+                                )
+                        );
+                    }
+            );
+        }
+    }
+
+    @Override
+    public void registerClient(RegisterClientInput input) {
+        tenantService.registerClient(input.clientId(), input.tenantId());
+    }
+
+    @Override
+    public void deregisterClient(DeregisterClientInput input) {
+        tenantService.deregisterClient(input.clientId());
+    }
+
+    @Override
+    public void addDpn(AddDpn addDpn) {
+        addDpn.getDpns().forEach(
+                dpn -> {
+                    try {
+                        log.info("Addind DPN {}", dpn.getDpn_id());
+                        nodeNetworkMap.put(dpn.getDpn_id(), dpn.getNode_id() + "/" + dpn.getNetwork_id());
+                    } catch (Exception e) {
+                        log.error(ExceptionUtils.getFullStackTrace(e));
+                    }
+                }
+        );
+    }
+
+    @Override
+    public void deleteDpn(String dpn) {
+        log.info("Removing DPN {}", dpn);
+        nodeNetworkMap.remove(dpn);
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java
new file mode 100644
index 0000000..9ff298a
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java
@@ -0,0 +1,24 @@
+package org.onosproject.fpcagent;
+
+import org.onosproject.fpcagent.dto.configure.Configure;
+import org.onosproject.fpcagent.dto.dpn.AddDpn;
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.deregisterclient.DeregisterClientInput;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.registerclient.RegisterClientInput;
+
+import java.util.Optional;
+
+public interface FpcService {
+
+    Optional<ConfigHelper> getConfig();
+
+    void configure(Configure configure);
+
+    void registerClient(RegisterClientInput input);
+
+    void deregisterClient(DeregisterClientInput input);
+
+    void addDpn(AddDpn addDpn);
+
+    void deleteDpn(String dpn);
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
new file mode 100644
index 0000000..e51efed
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
@@ -0,0 +1,100 @@
+package org.onosproject.fpcagent;
+
+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.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.payload.Contexts;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.onosproject.fpcagent.helpers.Converter.getFpcIdentity;
+
+@Component(immediate = true)
+@Service
+public class TenantManager implements TenantService {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private Map<FpcIdentity, Tenant> tenantMap = Maps.newHashMap();
+    private Map<ClientIdentifier, Tenant> clientIdMap = Maps.newHashMap();
+
+    private Map<FpcDpnId, List<FpcDpnId>> vdpnDpnsMap = Maps.newConcurrentMap();
+    private Map<FpcDpnId, Contexts> vdpnContextsMap = Maps.newConcurrentMap();
+
+    @Activate
+    protected void activate() {
+        log.info("Tenant Service Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        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());
+
+        tenantMap.put(tenantId, tenant);
+    }
+
+    public Optional<Tenant> getTenant(FpcIdentity tenantId) {
+        return Optional.ofNullable(tenantMap.get(tenantId));
+    }
+
+    public Optional<Tenant> getTenant(ClientIdentifier clientId) {
+        return Optional.ofNullable(clientIdMap.get(clientId));
+    }
+
+    public Optional<Tenant> registerClient(ClientIdentifier clientId, FpcIdentity tenantId) {
+        return getTenant(tenantId).map(tenant -> clientIdMap.put(clientId, tenant));
+    }
+
+    public Tenant deregisterClient(ClientIdentifier clientId) {
+        return 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));
+                }
+        ).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);
+                    }
+                    return Optional.<FpcDpnId>empty();
+                }
+        ).orElse(Optional.empty());
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java
new file mode 100644
index 0000000..f0f11a5
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java
@@ -0,0 +1,19 @@
+package org.onosproject.fpcagent;
+
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.Tenant;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+
+import java.util.Optional;
+
+public interface TenantService {
+    void addTenant(FpcIdentity tenantId);
+
+    Optional<Tenant> getTenant(FpcIdentity tenantId);
+
+    Optional<Tenant> getTenant(ClientIdentifier clientId);
+
+    Optional<Tenant> registerClient(ClientIdentifier clientId, FpcIdentity tenantId);
+
+    Tenant deregisterClient(ClientIdentifier clientId);
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/client/BindClient.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/client/BindClient.java
new file mode 100755
index 0000000..5817772
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/client/BindClient.java
@@ -0,0 +1,128 @@
+
+package org.onosproject.fpcagent.dto.client;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.onosproject.fpcagent.dto.configure.ConfigureInput;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "client-id",
+    "tenant-id",
+    "supported-features",
+    "endpoint-uri"
+})
+public class BindClient {
+
+    @JsonProperty("client-id")
+    private String client_id;
+    @JsonProperty("tenant-id")
+    private String tenant_id;
+    @JsonProperty("supported-features")
+    private List<String> supported_features = null;
+    @JsonProperty("endpoint-uri")
+    private String endpoint_uri;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public BindClient() {
+    }
+
+    /**
+     * 
+     * @param endpoint_uri
+     * @param supported_features
+     * @param tenant_id
+     * @param client_id
+     */
+    public BindClient(String client_id, String tenant_id, List<String> supported_features, String endpoint_uri) {
+        super();
+        this.client_id = client_id;
+        this.tenant_id = tenant_id;
+        this.supported_features = supported_features;
+        this.endpoint_uri = endpoint_uri;
+    }
+
+    @JsonProperty("client-id")
+    public String getClient_id() {
+        return client_id;
+    }
+
+    @JsonProperty("client-id")
+    public void setClient_id(String client_id) {
+        this.client_id = client_id;
+    }
+
+    @JsonProperty("tenant-id")
+    public String getTenant_id() {
+        return tenant_id;
+    }
+
+    @JsonProperty("tenant-id")
+    public void setTenant_id(String tenant_id) {
+        this.tenant_id = tenant_id;
+    }
+
+    @JsonProperty("supported-features")
+    public List<String> getSupported_features() {
+        return supported_features;
+    }
+
+    @JsonProperty("supported-features")
+    public void setSupported_features(List<String> supported_features) {
+        this.supported_features = supported_features;
+    }
+
+    @JsonProperty("endpoint-uri")
+    public String getEndpoint_uri() {
+        return endpoint_uri;
+    }
+
+    @JsonProperty("endpoint-uri")
+    public void setEndpoint_uri(String endpoint_uri) {
+        this.endpoint_uri = endpoint_uri;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("client_id", client_id).append("tenant_id", tenant_id).append("supported_features", supported_features).append("endpoint_uri", endpoint_uri).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(additionalProperties).append(endpoint_uri).append(supported_features).append(tenant_id).append(client_id).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof ConfigureInput) == false) {
+            return false;
+        }
+        BindClient rhs = ((BindClient) other);
+        return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).append(endpoint_uri, rhs.endpoint_uri).append(supported_features, rhs.supported_features).append(tenant_id, rhs.tenant_id).append(client_id, rhs.client_id).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Configure.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Configure.java
new file mode 100755
index 0000000..b79600f
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Configure.java
@@ -0,0 +1,81 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "input"
+})
+public class Configure {
+
+    @JsonProperty("input")
+    private ConfigureInput configureInput;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Configure() {
+    }
+
+    /**
+     * 
+     * @param configureInput
+     */
+    public Configure(ConfigureInput configureInput) {
+        super();
+        this.configureInput = configureInput;
+    }
+
+    @JsonProperty("input")
+    public ConfigureInput getConfigureInput() {
+        return configureInput;
+    }
+
+    @JsonProperty("input")
+    public void setConfigureInput(ConfigureInput configureInput) {
+        this.configureInput = configureInput;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("input", configureInput).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(configureInput).append(additionalProperties).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Configure) == false) {
+            return false;
+        }
+        Configure rhs = ((Configure) other);
+        return new EqualsBuilder().append(configureInput, rhs.configureInput).append(additionalProperties, rhs.additionalProperties).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/ConfigureInput.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/ConfigureInput.java
new file mode 100755
index 0000000..919052d
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/ConfigureInput.java
@@ -0,0 +1,162 @@
+package org.onosproject.fpcagent.dto.configure;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+        "op-id",
+        "targets",
+        "contexts",
+        "client-id",
+        "session-state",
+        "admin-state",
+        "op-type",
+        "op-ref-scope"
+})
+public class ConfigureInput {
+
+    @JsonProperty("op-id")
+    private String op_id;
+    @JsonProperty("targets")
+    private List<Target> targets = null;
+    @JsonProperty("contexts")
+    private List<Context> contexts = null;
+    @JsonProperty("client-id")
+    private String client_id;
+    @JsonProperty("session-state")
+    private String session_state;
+    @JsonProperty("admin-state")
+    private String admin_state;
+    @JsonProperty("op-type")
+    private String op_type;
+    @JsonProperty("op-ref-scope")
+    private String op_ref_scope;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     */
+    public ConfigureInput() {
+    }
+
+    @JsonProperty("op-id")
+    public String getOp_id() {
+        return op_id;
+    }
+
+    @JsonProperty("op-id")
+    public void setOp_id(String op_id) {
+        this.op_id = op_id;
+    }
+
+    @JsonProperty("targets")
+    public List<Target> getTargets() {
+        return targets;
+    }
+
+    @JsonProperty("targets")
+    public void setTargets(List<Target> targets) {
+        this.targets = targets;
+    }
+
+    @JsonProperty("contexts")
+    public List<Context> getContexts() {
+        return contexts;
+    }
+
+    @JsonProperty("contexts")
+    public void setContexts(List<Context> contexts) {
+        this.contexts = contexts;
+    }
+
+    @JsonProperty("client-id")
+    public String getClient_id() {
+        return client_id;
+    }
+
+    @JsonProperty("client-id")
+    public void setClient_id(String client_id) {
+        this.client_id = client_id;
+    }
+
+    @JsonProperty("session-state")
+    public String getSession_state() {
+        return session_state;
+    }
+
+    @JsonProperty("session-state")
+    public void setSession_state(String session_state) {
+        this.session_state = session_state;
+    }
+
+    @JsonProperty("admin-state")
+    public String getAdmin_state() {
+        return admin_state;
+    }
+
+    @JsonProperty("admin-state")
+    public void setAdmin_state(String admin_state) {
+        this.admin_state = admin_state;
+    }
+
+    @JsonProperty("op-type")
+    public String getOp_type() {
+        return op_type;
+    }
+
+    @JsonProperty("op-type")
+    public void setOp_type(String op_type) {
+        this.op_type = op_type;
+    }
+
+    @JsonProperty("op-ref-scope")
+    public String getOp_ref_scope() {
+        return op_ref_scope;
+    }
+
+    @JsonProperty("op-ref-scope")
+    public void setOp_ref_scope(String op_ref_scope) {
+        this.op_ref_scope = op_ref_scope;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("op_id", op_id).append("targets", targets).append("contexts", contexts).append("client_id", client_id).append("session_state", session_state).append("admin_state", admin_state).append("op_type", op_type).append("op_ref_scope", op_ref_scope).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(session_state).append(op_id).append(additionalProperties).append(admin_state).append(op_type).append(op_ref_scope).append(contexts).append(client_id).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof ConfigureInput) == false) {
+            return false;
+        }
+        ConfigureInput rhs = ((ConfigureInput) other);
+        return new EqualsBuilder().append(session_state, rhs.session_state).append(op_id, rhs.op_id).append(additionalProperties, rhs.additionalProperties).append(admin_state, rhs.admin_state).append(op_type, rhs.op_type).append(op_ref_scope, rhs.op_ref_scope).append(contexts, rhs.contexts).append(client_id, rhs.client_id).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Context.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Context.java
new file mode 100755
index 0000000..2dfaafa
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Context.java
@@ -0,0 +1,217 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "instructions",
+    "context-id",
+    "dpn-group",
+    "delegating-ip-prefixes",
+    "ul",
+    "dl",
+    "dpns",
+    "imsi",
+    "ebi",
+    "lbi"
+})
+public class Context {
+
+    @JsonProperty("instructions")
+    private Instructions instructions;
+    @JsonProperty("context-id")
+    private Integer context_id;
+    @JsonProperty("dpn-group")
+    private String dpn_group;
+    @JsonProperty("delegating-ip-prefixes")
+    private List<String> delegating_ip_prefixes = null;
+    @JsonProperty("ul")
+    private Ul ul;
+    @JsonProperty("dl")
+    private Dl dl;
+    @JsonProperty("dpns")
+    private List<Dpn> dpns = null;
+    @JsonProperty("imsi")
+    private String imsi;
+    @JsonProperty("ebi")
+    private String ebi;
+    @JsonProperty("lbi")
+    private String lbi;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Context() {
+    }
+
+    /**
+     * 
+     * @param lbi
+     * @param dpns
+     * @param ul
+     * @param dpn_group
+     * @param context_id
+     * @param instructions
+     * @param dl
+     * @param delegating_ip_prefixes
+     * @param imsi
+     * @param ebi
+     */
+    public Context(Instructions instructions, Integer context_id, String dpn_group, List<String> delegating_ip_prefixes, Ul ul, Dl dl, List<Dpn> dpns, String imsi, String ebi, String lbi) {
+        super();
+        this.instructions = instructions;
+        this.context_id = context_id;
+        this.dpn_group = dpn_group;
+        this.delegating_ip_prefixes = delegating_ip_prefixes;
+        this.ul = ul;
+        this.dl = dl;
+        this.dpns = dpns;
+        this.imsi = imsi;
+        this.ebi = ebi;
+        this.lbi = lbi;
+    }
+
+    @JsonProperty("instructions")
+    public Instructions getInstructions() {
+        return instructions;
+    }
+
+    @JsonProperty("instructions")
+    public void setInstructions(Instructions instructions) {
+        this.instructions = instructions;
+    }
+
+    @JsonProperty("context-id")
+    public Integer getContext_id() {
+        return context_id;
+    }
+
+    @JsonProperty("context-id")
+    public void setContext_id(Integer context_id) {
+        this.context_id = context_id;
+    }
+
+    @JsonProperty("dpn-group")
+    public String getDpn_group() {
+        return dpn_group;
+    }
+
+    @JsonProperty("dpn-group")
+    public void setDpn_group(String dpn_group) {
+        this.dpn_group = dpn_group;
+    }
+
+    @JsonProperty("delegating-ip-prefixes")
+    public List<String> getDelegating_ip_prefixes() {
+        return delegating_ip_prefixes;
+    }
+
+    @JsonProperty("delegating-ip-prefixes")
+    public void setDelegating_ip_prefixes(List<String> delegating_ip_prefixes) {
+        this.delegating_ip_prefixes = delegating_ip_prefixes;
+    }
+
+    @JsonProperty("ul")
+    public Ul getUl() {
+        return ul;
+    }
+
+    @JsonProperty("ul")
+    public void setUl(Ul ul) {
+        this.ul = ul;
+    }
+
+    @JsonProperty("dl")
+    public Dl getDl() {
+        return dl;
+    }
+
+    @JsonProperty("dl")
+    public void setDl(Dl dl) {
+        this.dl = dl;
+    }
+
+    @JsonProperty("dpns")
+    public List<Dpn> getDpns() {
+        return dpns;
+    }
+
+    @JsonProperty("dpns")
+    public void setDpns(List<Dpn> dpns) {
+        this.dpns = dpns;
+    }
+
+    @JsonProperty("imsi")
+    public String getImsi() {
+        return imsi;
+    }
+
+    @JsonProperty("imsi")
+    public void setImsi(String imsi) {
+        this.imsi = imsi;
+    }
+
+    @JsonProperty("ebi")
+    public String getEbi() {
+        return ebi;
+    }
+
+    @JsonProperty("ebi")
+    public void setEbi(String ebi) {
+        this.ebi = ebi;
+    }
+
+    @JsonProperty("lbi")
+    public String getLbi() {
+        return lbi;
+    }
+
+    @JsonProperty("lbi")
+    public void setLbi(String lbi) {
+        this.lbi = lbi;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("instructions", instructions).append("context_id", context_id).append("dpn_group", dpn_group).append("delegating_ip_prefixes", delegating_ip_prefixes).append("ul", ul).append("dl", dl).append("dpns", dpns).append("imsi", imsi).append("ebi", ebi).append("lbi", lbi).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(lbi).append(dpns).append(ul).append(dpn_group).append(context_id).append(instructions).append(additionalProperties).append(dl).append(delegating_ip_prefixes).append(imsi).append(ebi).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Context) == false) {
+            return false;
+        }
+        Context rhs = ((Context) other);
+        return new EqualsBuilder().append(lbi, rhs.lbi).append(dpns, rhs.dpns).append(ul, rhs.ul).append(dpn_group, rhs.dpn_group).append(context_id, rhs.context_id).append(instructions, rhs.instructions).append(additionalProperties, rhs.additionalProperties).append(dl, rhs.dl).append(delegating_ip_prefixes, rhs.delegating_ip_prefixes).append(imsi, rhs.imsi).append(ebi, rhs.ebi).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dl.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dl.java
new file mode 100755
index 0000000..f372a5b
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dl.java
@@ -0,0 +1,130 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "tunnel-local-address",
+    "tunnel-remote-address",
+    "mobility-tunnel-parameters",
+    "dpn-parameters"
+})
+public class Dl {
+
+    @JsonProperty("tunnel-local-address")
+    private String tunnel_local_address;
+    @JsonProperty("tunnel-remote-address")
+    private String tunnel_remote_address;
+    @JsonProperty("mobility-tunnel-parameters")
+    private Mobility_tunnel_parameters_ mobility_tunnel_parameters;
+    @JsonProperty("dpn-parameters")
+    private Dpn_parameters_ dpn_parameters;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Dl() {
+    }
+
+    /**
+     * 
+     * @param tunnel_remote_address
+     * @param dpn_parameters
+     * @param tunnel_local_address
+     * @param mobility_tunnel_parameters
+     */
+    public Dl(String tunnel_local_address, String tunnel_remote_address, Mobility_tunnel_parameters_ mobility_tunnel_parameters, Dpn_parameters_ dpn_parameters) {
+        super();
+        this.tunnel_local_address = tunnel_local_address;
+        this.tunnel_remote_address = tunnel_remote_address;
+        this.mobility_tunnel_parameters = mobility_tunnel_parameters;
+        this.dpn_parameters = dpn_parameters;
+    }
+
+    @JsonProperty("tunnel-local-address")
+    public String getTunnel_local_address() {
+        return tunnel_local_address;
+    }
+
+    @JsonProperty("tunnel-local-address")
+    public void setTunnel_local_address(String tunnel_local_address) {
+        this.tunnel_local_address = tunnel_local_address;
+    }
+
+    @JsonProperty("tunnel-remote-address")
+    public String getTunnel_remote_address() {
+        return tunnel_remote_address;
+    }
+
+    @JsonProperty("tunnel-remote-address")
+    public void setTunnel_remote_address(String tunnel_remote_address) {
+        this.tunnel_remote_address = tunnel_remote_address;
+    }
+
+    @JsonProperty("mobility-tunnel-parameters")
+    public Mobility_tunnel_parameters_ getMobility_tunnel_parameters() {
+        return mobility_tunnel_parameters;
+    }
+
+    @JsonProperty("mobility-tunnel-parameters")
+    public void setMobility_tunnel_parameters(Mobility_tunnel_parameters_ mobility_tunnel_parameters) {
+        this.mobility_tunnel_parameters = mobility_tunnel_parameters;
+    }
+
+    @JsonProperty("dpn-parameters")
+    public Dpn_parameters_ getDpn_parameters() {
+        return dpn_parameters;
+    }
+
+    @JsonProperty("dpn-parameters")
+    public void setDpn_parameters(Dpn_parameters_ dpn_parameters) {
+        this.dpn_parameters = dpn_parameters;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("tunnel_local_address", tunnel_local_address).append("tunnel_remote_address", tunnel_remote_address).append("mobility_tunnel_parameters", mobility_tunnel_parameters).append("dpn_parameters", dpn_parameters).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(tunnel_remote_address).append(dpn_parameters).append(additionalProperties).append(tunnel_local_address).append(mobility_tunnel_parameters).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Dl) == false) {
+            return false;
+        }
+        Dl rhs = ((Dl) other);
+        return new EqualsBuilder().append(tunnel_remote_address, rhs.tunnel_remote_address).append(dpn_parameters, rhs.dpn_parameters).append(additionalProperties, rhs.additionalProperties).append(tunnel_local_address, rhs.tunnel_local_address).append(mobility_tunnel_parameters, rhs.mobility_tunnel_parameters).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn.java
new file mode 100755
index 0000000..795da24
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn.java
@@ -0,0 +1,111 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "dpn-id",
+    "direction",
+    "dpn-parameters"
+})
+public class Dpn {
+
+    @JsonProperty("dpn-id")
+    private String dpn_id;
+    @JsonProperty("direction")
+    private String direction;
+    @JsonProperty("dpn-parameters")
+    private Dpn_parameters__ dpn_parameters;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Dpn() {
+    }
+
+    /**
+     * 
+     * @param dpn_parameters
+     * @param direction
+     * @param dpn_id
+     */
+    public Dpn(String dpn_id, String direction, Dpn_parameters__ dpn_parameters) {
+        super();
+        this.dpn_id = dpn_id;
+        this.direction = direction;
+        this.dpn_parameters = dpn_parameters;
+    }
+
+    @JsonProperty("dpn-id")
+    public String getDpn_id() {
+        return dpn_id;
+    }
+
+    @JsonProperty("dpn-id")
+    public void setDpn_id(String dpn_id) {
+        this.dpn_id = dpn_id;
+    }
+
+    @JsonProperty("direction")
+    public String getDirection() {
+        return direction;
+    }
+
+    @JsonProperty("direction")
+    public void setDirection(String direction) {
+        this.direction = direction;
+    }
+
+    @JsonProperty("dpn-parameters")
+    public Dpn_parameters__ getDpn_parameters() {
+        return dpn_parameters;
+    }
+
+    @JsonProperty("dpn-parameters")
+    public void setDpn_parameters(Dpn_parameters__ dpn_parameters) {
+        this.dpn_parameters = dpn_parameters;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("dpn_id", dpn_id).append("direction", direction).append("dpn_parameters", dpn_parameters).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(dpn_parameters).append(additionalProperties).append(direction).append(dpn_id).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Dpn) == false) {
+            return false;
+        }
+        Dpn rhs = ((Dpn) other);
+        return new EqualsBuilder().append(dpn_parameters, rhs.dpn_parameters).append(additionalProperties, rhs.additionalProperties).append(direction, rhs.direction).append(dpn_id, rhs.dpn_id).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters.java
new file mode 100755
index 0000000..e8fea8d
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters.java
@@ -0,0 +1,56 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+
+})
+public class Dpn_parameters {
+
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(additionalProperties).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Dpn_parameters) == false) {
+            return false;
+        }
+        Dpn_parameters rhs = ((Dpn_parameters) other);
+        return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters_.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters_.java
new file mode 100755
index 0000000..0e00c6f
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters_.java
@@ -0,0 +1,56 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+
+})
+public class Dpn_parameters_ {
+
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(additionalProperties).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Dpn_parameters_) == false) {
+            return false;
+        }
+        Dpn_parameters_ rhs = ((Dpn_parameters_) other);
+        return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters__.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters__.java
new file mode 100755
index 0000000..009e5e8
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Dpn_parameters__.java
@@ -0,0 +1,53 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+
+})
+public class Dpn_parameters__ {
+
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(additionalProperties).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Dpn_parameters__) == false) {
+            return false;
+        }
+        Dpn_parameters__ rhs = ((Dpn_parameters__) other);
+        return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Instructions.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Instructions.java
new file mode 100755
index 0000000..043755d
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Instructions.java
@@ -0,0 +1,85 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "instr-3gpp-mob"
+})
+public class Instructions {
+
+    @JsonProperty("instr-3gpp-mob")
+    private String instr_3gpp_mob;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Instructions() {
+    }
+
+    /**
+     * 
+     * @param instr_3gpp_mob
+     */
+    public Instructions(String instr_3gpp_mob) {
+        super();
+        this.instr_3gpp_mob = instr_3gpp_mob;
+    }
+
+    @JsonProperty("instr-3gpp-mob")
+    public String getInstr_3gpp_mob() {
+        return instr_3gpp_mob;
+    }
+
+    @JsonProperty("instr-3gpp-mob")
+    public void setInstr_3gpp_mob(String instr_3gpp_mob) {
+        this.instr_3gpp_mob = instr_3gpp_mob;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("instr_3gpp_mob", instr_3gpp_mob).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(additionalProperties).append(instr_3gpp_mob).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Instructions) == false) {
+            return false;
+        }
+        Instructions rhs = ((Instructions) other);
+        return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).append(instr_3gpp_mob, rhs.instr_3gpp_mob).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Mobility_tunnel_parameters.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Mobility_tunnel_parameters.java
new file mode 100755
index 0000000..d58f547
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Mobility_tunnel_parameters.java
@@ -0,0 +1,96 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "tunnel-type",
+    "tunnel-identifier"
+})
+public class Mobility_tunnel_parameters {
+
+    @JsonProperty("tunnel-type")
+    private String tunnel_type;
+    @JsonProperty("tunnel-identifier")
+    private String tunnel_identifier;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Mobility_tunnel_parameters() {
+    }
+
+    /**
+     * 
+     * @param tunnel_type
+     * @param tunnel_identifier
+     */
+    public Mobility_tunnel_parameters(String tunnel_type, String tunnel_identifier) {
+        super();
+        this.tunnel_type = tunnel_type;
+        this.tunnel_identifier = tunnel_identifier;
+    }
+
+    @JsonProperty("tunnel-type")
+    public String getTunnel_type() {
+        return tunnel_type;
+    }
+
+    @JsonProperty("tunnel-type")
+    public void setTunnel_type(String tunnel_type) {
+        this.tunnel_type = tunnel_type;
+    }
+
+    @JsonProperty("tunnel-identifier")
+    public String getTunnel_identifier() {
+        return tunnel_identifier;
+    }
+
+    @JsonProperty("tunnel-identifier")
+    public void setTunnel_identifier(String tunnel_identifier) {
+        this.tunnel_identifier = tunnel_identifier;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("tunnel_type", tunnel_type).append("tunnel_identifier", tunnel_identifier).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(additionalProperties).append(tunnel_type).append(tunnel_identifier).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Mobility_tunnel_parameters) == false) {
+            return false;
+        }
+        Mobility_tunnel_parameters rhs = ((Mobility_tunnel_parameters) other);
+        return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).append(tunnel_type, rhs.tunnel_type).append(tunnel_identifier, rhs.tunnel_identifier).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Mobility_tunnel_parameters_.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Mobility_tunnel_parameters_.java
new file mode 100755
index 0000000..deb615c
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Mobility_tunnel_parameters_.java
@@ -0,0 +1,100 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "tunnel-type",
+    "tunnel-identifier"
+})
+public class Mobility_tunnel_parameters_ {
+
+    @JsonProperty("tunnel-type")
+    private String tunnel_type;
+    @JsonProperty("tunnel-identifier")
+    private String tunnel_identifier;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Mobility_tunnel_parameters_() {
+    }
+
+    /**
+     * 
+     * @param tunnel_type
+     * @param tunnel_identifier
+     */
+    public Mobility_tunnel_parameters_(String tunnel_type, String tunnel_identifier) {
+        super();
+        this.tunnel_type = tunnel_type;
+        this.tunnel_identifier = tunnel_identifier;
+    }
+
+    @JsonProperty("tunnel-type")
+    public String getTunnel_type() {
+        return tunnel_type;
+    }
+
+    @JsonProperty("tunnel-type")
+    public void setTunnel_type(String tunnel_type) {
+        this.tunnel_type = tunnel_type;
+    }
+
+    @JsonProperty("tunnel-identifier")
+    public String getTunnel_identifier() {
+        return tunnel_identifier;
+    }
+
+    @JsonProperty("tunnel-identifier")
+    public void setTunnel_identifier(String tunnel_identifier) {
+        this.tunnel_identifier = tunnel_identifier;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("tunnel_type", tunnel_type).append("tunnel_identifier", tunnel_identifier).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(additionalProperties).append(tunnel_type).append(tunnel_identifier).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Mobility_tunnel_parameters_) == false) {
+            return false;
+        }
+        Mobility_tunnel_parameters_ rhs = ((Mobility_tunnel_parameters_) other);
+        return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).append(tunnel_type, rhs.tunnel_type).append(tunnel_identifier, rhs.tunnel_identifier).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Target.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Target.java
new file mode 100755
index 0000000..db67e91
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Target.java
@@ -0,0 +1,81 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "target"
+})
+public class Target {
+
+    @JsonProperty("target")
+    private String target;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Target() {
+    }
+
+    /**
+     * 
+     * @param target
+     */
+    public Target(String target) {
+        super();
+        this.target = target;
+    }
+
+    @JsonProperty("target")
+    public String getTarget() {
+        return target;
+    }
+
+    @JsonProperty("target")
+    public void setTarget(String target) {
+        this.target = target;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("target", target).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(additionalProperties).append(target).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Target) == false) {
+            return false;
+        }
+        Target rhs = ((Target) other);
+        return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).append(target, rhs.target).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Ul.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Ul.java
new file mode 100755
index 0000000..8f2090e
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/configure/Ul.java
@@ -0,0 +1,130 @@
+
+package org.onosproject.fpcagent.dto.configure;
+
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "tunnel-local-address",
+    "tunnel-remote-address",
+    "mobility-tunnel-parameters",
+    "dpn-parameters"
+})
+public class Ul {
+
+    @JsonProperty("tunnel-local-address")
+    private String tunnel_local_address;
+    @JsonProperty("tunnel-remote-address")
+    private String tunnel_remote_address;
+    @JsonProperty("mobility-tunnel-parameters")
+    private Mobility_tunnel_parameters mobility_tunnel_parameters;
+    @JsonProperty("dpn-parameters")
+    private Dpn_parameters dpn_parameters;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Ul() {
+    }
+
+    /**
+     * 
+     * @param tunnel_remote_address
+     * @param dpn_parameters
+     * @param tunnel_local_address
+     * @param mobility_tunnel_parameters
+     */
+    public Ul(String tunnel_local_address, String tunnel_remote_address, Mobility_tunnel_parameters mobility_tunnel_parameters, Dpn_parameters dpn_parameters) {
+        super();
+        this.tunnel_local_address = tunnel_local_address;
+        this.tunnel_remote_address = tunnel_remote_address;
+        this.mobility_tunnel_parameters = mobility_tunnel_parameters;
+        this.dpn_parameters = dpn_parameters;
+    }
+
+    @JsonProperty("tunnel-local-address")
+    public String getTunnel_local_address() {
+        return tunnel_local_address;
+    }
+
+    @JsonProperty("tunnel-local-address")
+    public void setTunnel_local_address(String tunnel_local_address) {
+        this.tunnel_local_address = tunnel_local_address;
+    }
+
+    @JsonProperty("tunnel-remote-address")
+    public String getTunnel_remote_address() {
+        return tunnel_remote_address;
+    }
+
+    @JsonProperty("tunnel-remote-address")
+    public void setTunnel_remote_address(String tunnel_remote_address) {
+        this.tunnel_remote_address = tunnel_remote_address;
+    }
+
+    @JsonProperty("mobility-tunnel-parameters")
+    public Mobility_tunnel_parameters getMobility_tunnel_parameters() {
+        return mobility_tunnel_parameters;
+    }
+
+    @JsonProperty("mobility-tunnel-parameters")
+    public void setMobility_tunnel_parameters(Mobility_tunnel_parameters mobility_tunnel_parameters) {
+        this.mobility_tunnel_parameters = mobility_tunnel_parameters;
+    }
+
+    @JsonProperty("dpn-parameters")
+    public Dpn_parameters getDpn_parameters() {
+        return dpn_parameters;
+    }
+
+    @JsonProperty("dpn-parameters")
+    public void setDpn_parameters(Dpn_parameters dpn_parameters) {
+        this.dpn_parameters = dpn_parameters;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("tunnel_local_address", tunnel_local_address).append("tunnel_remote_address", tunnel_remote_address).append("mobility_tunnel_parameters", mobility_tunnel_parameters).append("dpn_parameters", dpn_parameters).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(tunnel_remote_address).append(dpn_parameters).append(additionalProperties).append(tunnel_local_address).append(mobility_tunnel_parameters).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Ul) == false) {
+            return false;
+        }
+        Ul rhs = ((Ul) other);
+        return new EqualsBuilder().append(tunnel_remote_address, rhs.tunnel_remote_address).append(dpn_parameters, rhs.dpn_parameters).append(additionalProperties, rhs.additionalProperties).append(tunnel_local_address, rhs.tunnel_local_address).append(mobility_tunnel_parameters, rhs.mobility_tunnel_parameters).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/dpn/AddDpn.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/dpn/AddDpn.java
new file mode 100755
index 0000000..3c166ad
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/dpn/AddDpn.java
@@ -0,0 +1,82 @@
+
+package org.onosproject.fpcagent.dto.dpn;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "dpns"
+})
+public class AddDpn {
+
+    @JsonProperty("dpns")
+    private List<Dpn> dpns = null;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public AddDpn() {
+    }
+
+    /**
+     * 
+     * @param dpns
+     */
+    public AddDpn(List<Dpn> dpns) {
+        super();
+        this.dpns = dpns;
+    }
+
+    @JsonProperty("dpns")
+    public List<Dpn> getDpns() {
+        return dpns;
+    }
+
+    @JsonProperty("dpns")
+    public void setDpns(List<Dpn> dpns) {
+        this.dpns = dpns;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("dpns", dpns).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(dpns).append(additionalProperties).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof AddDpn) == false) {
+            return false;
+        }
+        AddDpn rhs = ((AddDpn) other);
+        return new EqualsBuilder().append(dpns, rhs.dpns).append(additionalProperties, rhs.additionalProperties).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/dpn/Dpn.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/dpn/Dpn.java
new file mode 100755
index 0000000..f71df67
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/dto/dpn/Dpn.java
@@ -0,0 +1,142 @@
+
+package org.onosproject.fpcagent.dto.dpn;
+
+import com.fasterxml.jackson.annotation.*;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+    "dpn-id",
+    "dpn-name",
+    "dpn-groups",
+    "node-id",
+    "network-id"
+})
+public class Dpn {
+
+    @JsonProperty("dpn-id")
+    private String dpn_id;
+    @JsonProperty("dpn-name")
+    private String dpn_name;
+    @JsonProperty("dpn-groups")
+    private List<String> dpn_groups = null;
+    @JsonProperty("node-id")
+    private String node_id;
+    @JsonProperty("network-id")
+    private String network_id;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+    /**
+     * No args constructor for use in serialization
+     * 
+     */
+    public Dpn() {
+    }
+
+    /**
+     * 
+     * @param dpn_name
+     * @param network_id
+     * @param dpn_groups
+     * @param dpn_id
+     * @param node_id
+     */
+    public Dpn(String dpn_id, String dpn_name, List<String> dpn_groups, String node_id, String network_id) {
+        super();
+        this.dpn_id = dpn_id;
+        this.dpn_name = dpn_name;
+        this.dpn_groups = dpn_groups;
+        this.node_id = node_id;
+        this.network_id = network_id;
+    }
+
+    @JsonProperty("dpn-id")
+    public String getDpn_id() {
+        return dpn_id;
+    }
+
+    @JsonProperty("dpn-id")
+    public void setDpn_id(String dpn_id) {
+        this.dpn_id = dpn_id;
+    }
+
+    @JsonProperty("dpn-name")
+    public String getDpn_name() {
+        return dpn_name;
+    }
+
+    @JsonProperty("dpn-name")
+    public void setDpn_name(String dpn_name) {
+        this.dpn_name = dpn_name;
+    }
+
+    @JsonProperty("dpn-groups")
+    public List<String> getDpn_groups() {
+        return dpn_groups;
+    }
+
+    @JsonProperty("dpn-groups")
+    public void setDpn_groups(List<String> dpn_groups) {
+        this.dpn_groups = dpn_groups;
+    }
+
+    @JsonProperty("node-id")
+    public String getNode_id() {
+        return node_id;
+    }
+
+    @JsonProperty("node-id")
+    public void setNode_id(String node_id) {
+        this.node_id = node_id;
+    }
+
+    @JsonProperty("network-id")
+    public String getNetwork_id() {
+        return network_id;
+    }
+
+    @JsonProperty("network-id")
+    public void setNetwork_id(String network_id) {
+        this.network_id = network_id;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this).append("dpn_id", dpn_id).append("dpn_name", dpn_name).append("dpn_groups", dpn_groups).append("node_id", node_id).append("network_id", network_id).append("additionalProperties", additionalProperties).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(dpn_name).append(network_id).append(dpn_groups).append(additionalProperties).append(dpn_id).append(node_id).toHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if ((other instanceof Dpn) == false) {
+            return false;
+        }
+        Dpn rhs = ((Dpn) other);
+        return new EqualsBuilder().append(dpn_name, rhs.dpn_name).append(network_id, rhs.network_id).append(dpn_groups, rhs.dpn_groups).append(additionalProperties, rhs.additionalProperties).append(dpn_id, rhs.dpn_id).append(node_id, rhs.node_id).isEquals();
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java
new file mode 100644
index 0000000..bee7cce
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java
@@ -0,0 +1,318 @@
+package org.onosproject.fpcagent.helpers;
+
+import com.fasterxml.jackson.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+        "monitor-threads",
+        "scheduled-monitors-poolsize",
+        "dpn-listener-uri",
+        "dpn-listener-id",
+        "dpn-client-uri",
+        "dpn-client-threads",
+        "metricsupdate-ms",
+        "mobilityupdate-ms",
+        "activation-threads",
+        "target-read-limit",
+        "http-notifier-clients",
+        "zmq-nbi-server-poolsize",
+        "zmq-nbi-server-uri",
+        "zmq-nbi-inproc-uri",
+        "zmq-nbi-handler-poolsize",
+        "http-nio2-nb-poolsize",
+        "http-nio2-nb-port",
+        "node-id",
+        "network-id",
+        "zmq-broadcast-controllers",
+        "zmq-broadcast-dpns",
+        "zmq-broadcast-all"
+})
+public class ConfigHelper {
+
+    @JsonProperty("monitor-threads")
+    private Integer monitorThreads;
+    @JsonProperty("scheduled-monitors-poolsize")
+    private Integer scheduledMonitorsPoolsize;
+    @JsonProperty("dpn-listener-uri")
+    private String dpnListenerUri;
+    @JsonProperty("dpn-listener-id")
+    private Integer dpnListenerId;
+    @JsonProperty("dpn-client-uri")
+    private String dpnClientUri;
+    @JsonProperty("dpn-client-threads")
+    private Integer dpnClientThreads;
+    @JsonProperty("metricsupdate-ms")
+    private Integer metricsupdateMs;
+    @JsonProperty("mobilityupdate-ms")
+    private Integer mobilityupdateMs;
+    @JsonProperty("activation-threads")
+    private Integer activationThreads;
+    @JsonProperty("target-read-limit")
+    private Integer targetReadLimit;
+    @JsonProperty("http-notifier-clients")
+    private Integer httpNotifierClients;
+    @JsonProperty("zmq-nbi-server-poolsize")
+    private Integer zmqNbiServerPoolsize;
+    @JsonProperty("zmq-nbi-server-uri")
+    private String zmqNbiServerUri;
+    @JsonProperty("zmq-nbi-inproc-uri")
+    private String zmqNbiInprocUri;
+    @JsonProperty("zmq-nbi-handler-poolsize")
+    private Integer zmqNbiHandlerPoolsize;
+    @JsonProperty("http-nio2-nb-poolsize")
+    private Integer httpNio2NbPoolsize;
+    @JsonProperty("http-nio2-nb-port")
+    private Integer httpNio2NbPort;
+    @JsonProperty("node-id")
+    private String nodeId;
+    @JsonProperty("network-id")
+    private String networkId;
+    @JsonProperty("zmq-broadcast-controllers")
+    private String zmqBroadcastControllers;
+    @JsonProperty("zmq-broadcast-dpns")
+    private String zmqBroadcastDpns;
+    @JsonProperty("zmq-broadcast-all")
+    private String zmqBroadcastAll;
+    @JsonIgnore
+    private Map<String, Object> additionalProperties = new HashMap<>();
+
+    /**
+     * No args constructor for use in serialization
+     */
+    public ConfigHelper() {
+    }
+
+    @JsonProperty("monitor-threads")
+    public Integer monitorThreads() {
+        return monitorThreads;
+    }
+
+    @JsonProperty("monitor-threads")
+    public void setMonitorThreads(Integer monitorThreads) {
+        this.monitorThreads = monitorThreads;
+    }
+
+    @JsonProperty("scheduled-monitors-poolsize")
+    public Integer scheduledMonitorsPoolsize() {
+        return scheduledMonitorsPoolsize;
+    }
+
+    @JsonProperty("scheduled-monitors-poolsize")
+    public void setScheduledMonitorsPoolsize(Integer scheduledMonitorsPoolsize) {
+        this.scheduledMonitorsPoolsize = scheduledMonitorsPoolsize;
+    }
+
+    @JsonProperty("dpn-listener-uri")
+    public String dpnListenerUri() {
+        return dpnListenerUri;
+    }
+
+    @JsonProperty("dpn-listener-uri")
+    public void setDpnListenerUri(String dpnListenerUri) {
+        this.dpnListenerUri = dpnListenerUri;
+    }
+
+    @JsonProperty("dpn-listener-id")
+    public Integer dpnListenerId() {
+        return dpnListenerId;
+    }
+
+    @JsonProperty("dpn-listener-id")
+    public void setDpnListenerId(Integer dpnListenerId) {
+        this.dpnListenerId = dpnListenerId;
+    }
+
+    @JsonProperty("dpn-client-uri")
+    public String dpnClientUri() {
+        return dpnClientUri;
+    }
+
+    @JsonProperty("dpn-client-uri")
+    public void setDpnClientUri(String dpnClientUri) {
+        this.dpnClientUri = dpnClientUri;
+    }
+
+    @JsonProperty("dpn-client-threads")
+    public Integer dpnClientThreads() {
+        return dpnClientThreads;
+    }
+
+    @JsonProperty("dpn-client-threads")
+    public void setDpnClientThreads(Integer dpnClientThreads) {
+        this.dpnClientThreads = dpnClientThreads;
+    }
+
+    @JsonProperty("metricsupdate-ms")
+    public Integer metricUpdateMs() {
+        return metricsupdateMs;
+    }
+
+    @JsonProperty("metricsupdate-ms")
+    public void setMetricsupdateMs(Integer metricsupdateMs) {
+        this.metricsupdateMs = metricsupdateMs;
+    }
+
+    @JsonProperty("mobilityupdate-ms")
+    public Integer mobilityUpdateMs() {
+        return mobilityupdateMs;
+    }
+
+    @JsonProperty("mobilityupdate-ms")
+    public void setMobilityupdateMs(Integer mobilityupdateMs) {
+        this.mobilityupdateMs = mobilityupdateMs;
+    }
+
+    @JsonProperty("activation-threads")
+    public Integer activationThreads() {
+        return activationThreads;
+    }
+
+    @JsonProperty("activation-threads")
+    public void setActivationThreads(Integer activationThreads) {
+        this.activationThreads = activationThreads;
+    }
+
+    @JsonProperty("target-read-limit")
+    public Integer targetReadLimit() {
+        return targetReadLimit;
+    }
+
+    @JsonProperty("target-read-limit")
+    public void setTargetReadLimit(Integer targetReadLimit) {
+        this.targetReadLimit = targetReadLimit;
+    }
+
+    @JsonProperty("http-notifier-clients")
+    public Integer httpNotifierClients() {
+        return httpNotifierClients;
+    }
+
+    @JsonProperty("http-notifier-clients")
+    public void setHttpNotifierClients(Integer httpNotifierClients) {
+        this.httpNotifierClients = httpNotifierClients;
+    }
+
+    @JsonProperty("zmq-nbi-server-poolsize")
+    public Integer zmqServerPoolsize() {
+        return zmqNbiServerPoolsize;
+    }
+
+    @JsonProperty("zmq-nbi-server-poolsize")
+    public void setZmqNbiServerPoolsize(Integer zmqNbiServerPoolsize) {
+        this.zmqNbiServerPoolsize = zmqNbiServerPoolsize;
+    }
+
+    @JsonProperty("zmq-nbi-server-uri")
+    public String zmqServerUri() {
+        return zmqNbiServerUri;
+    }
+
+    @JsonProperty("zmq-nbi-server-uri")
+    public void setZmqNbiServerUri(String zmqNbiServerUri) {
+        this.zmqNbiServerUri = zmqNbiServerUri;
+    }
+
+    @JsonProperty("zmq-nbi-inproc-uri")
+    public String zmqInprocUri() {
+        return zmqNbiInprocUri;
+    }
+
+    @JsonProperty("zmq-nbi-inproc-uri")
+    public void setZmqNbiInprocUri(String zmqNbiInprocUri) {
+        this.zmqNbiInprocUri = zmqNbiInprocUri;
+    }
+
+    @JsonProperty("zmq-nbi-handler-poolsize")
+    public Integer zmqHandlerPoolsize() {
+        return zmqNbiHandlerPoolsize;
+    }
+
+    @JsonProperty("zmq-nbi-handler-poolsize")
+    public void setZmqNbiHandlerPoolsize(Integer zmqNbiHandlerPoolsize) {
+        this.zmqNbiHandlerPoolsize = zmqNbiHandlerPoolsize;
+    }
+
+    @JsonProperty("http-nio2-nb-poolsize")
+    public Integer httpNio2Poolsize() {
+        return httpNio2NbPoolsize;
+    }
+
+    @JsonProperty("http-nio2-nb-poolsize")
+    public void setHttpNio2NbPoolsize(Integer httpNio2NbPoolsize) {
+        this.httpNio2NbPoolsize = httpNio2NbPoolsize;
+    }
+
+    @JsonProperty("http-nio2-nb-port")
+    public Integer httpNio2Port() {
+        return httpNio2NbPort;
+    }
+
+    @JsonProperty("http-nio2-nb-port")
+    public void setHttpNio2NbPort(Integer httpNio2NbPort) {
+        this.httpNio2NbPort = httpNio2NbPort;
+    }
+
+    @JsonProperty("node-id")
+    public String nodeId() {
+        return nodeId;
+    }
+
+    @JsonProperty("node-id")
+    public void setNodeId(String node_id) {
+        this.nodeId = node_id;
+    }
+
+    @JsonProperty("network-id")
+    public String networkId() {
+        return networkId;
+    }
+
+    @JsonProperty("network-id")
+    public void setNetworkId(String network_id) {
+        this.networkId = network_id;
+    }
+
+    @JsonProperty("zmq-broadcast-controllers")
+    public String zmqBroadcastControllers() {
+        return zmqBroadcastControllers;
+    }
+
+    @JsonProperty("zmq-broadcast-controllers")
+    public void setZmqBroadcastControllers(String zmqBroadcastControllers) {
+        this.zmqBroadcastControllers = zmqBroadcastControllers;
+    }
+
+    @JsonProperty("zmq-broadcast-dpns")
+    public String zmqBroadcastDpns() {
+        return zmqBroadcastDpns;
+    }
+
+    @JsonProperty("zmq-broadcast-dpns")
+    public void setZmqBroadcastDpns(String zmqBroadcastDpns) {
+        this.zmqBroadcastDpns = zmqBroadcastDpns;
+    }
+
+    @JsonProperty("zmq-broadcast-all")
+    public String zmqBroadcastAll() {
+        return zmqBroadcastAll;
+    }
+
+    @JsonProperty("zmq-broadcast-all")
+    public void setZmqBroadcastAll(String zmqBroadcastAll) {
+        this.zmqBroadcastAll = zmqBroadcastAll;
+    }
+
+    @JsonAnyGetter
+    public Map<String, Object> getAdditionalProperties() {
+        return this.additionalProperties;
+    }
+
+    @JsonAnySetter
+    public void setAdditionalProperty(String name, Object value) {
+        this.additionalProperties.put(name, value);
+    }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java
new file mode 100644
index 0000000..6573ae8
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java
@@ -0,0 +1,104 @@
+package org.onosproject.fpcagent.helpers;
+
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpcidentity.FpcIdentityUnion;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.function.Function;
+
+public class Converter {
+    /**
+     * Short to Byte
+     *
+     * @param value - Short
+     * @return byte value
+     */
+    public static byte toUint8(Short value) {
+        return value.byteValue();
+    }
+
+    /**
+     * Short to byte array
+     *
+     * @param value - Short
+     * @return byte array
+     */
+    public static byte[] toUint16(Short value) {
+        return new byte[]{(byte) (value >>> 8), (byte) (value & 0xFF)};
+    }
+
+    /**
+     * Lower two bytes of an integer to byte array
+     *
+     * @param value - integer value
+     * @return byte array
+     */
+    public static byte[] toUint16(Integer value) {
+        return new byte[]{(byte) (value >>> 8), (byte) (value & 0xFF)};
+    }
+
+    /**
+     * Long to byte array.
+     *
+     * @param value - long
+     * @return byte array
+     */
+    public static byte[] toUint32(long value) {
+        return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) (value & 0xFF)};
+    }
+
+    /**
+     * BigInteger to byte array.
+     *
+     * @param value - BigInteger
+     * @return byte array
+     */
+    public static byte[] toUint64(BigInteger value) {
+        return new byte[]{value.shiftRight(56).byteValue(), value.shiftRight(48).byteValue(), value.shiftRight(40).byteValue(),
+                value.shiftRight(32).byteValue(), value.shiftRight(24).byteValue(), value.shiftRight(16).byteValue(),
+                value.shiftRight(8).byteValue(), value.and(BigInteger.valueOf(0xFF)).byteValue()};
+    }
+
+    /**
+     * Decodes a 32 bit value
+     *
+     * @param source - byte array
+     * @param offset - offset in the array where the 8 bytes begins
+     * @return integer
+     */
+    public static int toInt(byte[] source, int offset) {
+        return new BigInteger(Arrays.copyOfRange(source, offset, offset + 4)).intValue();
+    }
+
+    /**
+     * Converts a byte array to BigInteger
+     *
+     * @param source - byte array
+     * @param offset - offset in the array where the 8 bytes begins
+     * @return BigInteger representing a Uint64
+     */
+    public static BigInteger toBigInt(byte[] source, int offset) {
+        return new BigInteger(Arrays.copyOfRange(source, offset, offset + 8));
+    }
+
+    /**
+     * Converts an integer to a long (used for larger unsigned integers)
+     *
+     * @param source - message buffer (byte array)
+     * @param offset - offset in the array where the 4 bytes begins
+     * @return Long value of the unsigned integer
+     */
+    public static long fromIntToLong(byte[] source, int offset) {
+        long value = 0;
+        for (int i = offset; i < offset + 4; i++) {
+            value = (value << 8) + (source[i] & 0xff);
+        }
+        return value;
+    }
+
+    public static Function<String, FpcIdentity> getFpcIdentity = (v) -> new FpcIdentity(new FpcIdentityUnion(v));
+    public static Function<String, ClientIdentifier> getClientIdentity = (v) -> new ClientIdentifier(getFpcIdentity.apply(v));
+
+}
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
new file mode 100644
index 0000000..f50a985
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnApi.java
@@ -0,0 +1,481 @@
+package org.onosproject.fpcagent.helpers;
+
+
+import com.google.common.collect.Maps;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onosproject.fpcagent.workers.ZMQSBPublisherManager;
+import org.onosproject.fpcagent.workers.ZMQSBSubscriberManager;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.OpIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DefaultDownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpcidentity.FpcIdentityUnion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.util.AbstractMap;
+import java.util.Arrays;
+import java.util.Map;
+
+import static org.onosproject.fpcagent.helpers.Converter.*;
+
+/**
+ * DPDK DPN API over ZeroMQ.
+ */
+public class DpnApi {
+    protected static final Logger log = LoggerFactory.getLogger(DpnApi.class);
+    /**
+     * Topic for broadcasting
+     */
+    private static byte BROADCAST_TOPIC = 0b0000_0000;
+    private static byte CREATE_SESSION_TYPE = 0b0000_0001;
+    private static byte MODIFY_DL_BEARER_TYPE = 0b0000_0010;
+    private static byte DELETE_SESSION_TYPE = 0b0000_0011;
+    private static byte MODIFY_UL_BEARER_TYPE = 0b0000_0100;
+    private static byte CREATE_UL_BEARER_TYPE = 0b0000_0101;
+    private static byte CREATE_DL_BEARER_TYPE = 0b0000_0110;
+    private static byte DELETE_BEARER_TYPE = 0b0000_0110;
+    private static byte HELLO = 0b0000_1000;
+    private static byte BYE = 0b0000_1001;
+    private static byte SEND_ADC_TYPE = 0b001_0001;
+    private static byte DDN_ACK = 0b0000_0110;
+
+    private static byte DPN_HELLO = 0b0000_0001;
+    private static byte DPN_BYE = 0b0000_0010;
+    private static byte DOWNLINK_DATA_NOTIFICATION = 0b0000_0101;
+    private static byte DPN_STATUS_INDICATION = 0b0000_1100;
+    private static byte DPN_OVERLOAD_INDICATION = 0b0000_0101;
+    private static byte DPN_REPLY = 0b0000_0100;
+    private static String DOWNLINK_DATA_NOTIFICATION_STRING = "Downlink-Data-Notification";
+    private static final Map<String, FpcDpnId> uplinkDpnMap;
+    private static final Map<String, Short> topicToNodeMap;
+
+    static {
+        uplinkDpnMap = Maps.newConcurrentMap();
+        topicToNodeMap = Maps.newConcurrentMap();
+    }
+
+    /**
+     * Creates Mobility Session
+     *
+     * @param dpn               - DPN
+     * @param imsi              - IMSI
+     * @param ue_ip             - Session IP Address
+     * @param default_ebi       - Default EBI
+     * @param s1u_sgw_gtpu_ipv4 - SGW GTP-U IPv4 Address
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     * @param clientIdentifier  - Client Identifier
+     * @param opIdentifier      - Operation Identifier
+     * @param sessionId         - Session Id
+     */
+    public static void create_session(
+            Short dpn,
+            BigInteger imsi,
+            Ip4Address ue_ip,
+            Short default_ebi,
+            Ip4Address s1u_sgw_gtpu_ipv4,
+            Long s1u_sgw_gtpu_teid,
+            Long clientIdentifier,
+            BigInteger opIdentifier,
+            Long sessionId
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(41)
+                .put(toUint8(dpn))
+                .put(CREATE_SESSION_TYPE)
+                .put(toUint64(imsi))
+                .put(toUint8(default_ebi))
+                .put(toUint32(ue_ip.toInt()))
+                .put(toUint32(s1u_sgw_gtpu_teid))
+                .put(toUint32(s1u_sgw_gtpu_ipv4.toInt()))
+                .put(toUint64(BigInteger.valueOf(sessionId)))
+                .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+                .put(toUint32(clientIdentifier))
+                .put(toUint32(opIdentifier.longValue()));
+
+        log.info("create_session: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Modify Downlink Bearer
+     *
+     * @param dpn               - DPN
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     * @param s1u_enb_gtpu_ipv4 - ENodeB GTP-U IPv4 Address
+     * @param s1u_enb_gtpu_teid - ENodeB GTP-U TEID
+     * @param clientIdentifier  - Client Identifier
+     * @param opIdentifier      - Operation Identifier
+     */
+    public static void modify_bearer_dl(
+            Short dpn,
+            Long s1u_sgw_gtpu_teid,
+            Ip4Address s1u_enb_gtpu_ipv4,
+            Long s1u_enb_gtpu_teid,
+            Long clientIdentifier,
+            BigInteger opIdentifier
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(23)
+                .put(toUint8(dpn))
+                .put(MODIFY_DL_BEARER_TYPE)
+                .put(toUint32(s1u_enb_gtpu_ipv4.toInt()))
+                .put(toUint32(s1u_enb_gtpu_teid))
+                .put(toUint32(s1u_sgw_gtpu_teid))
+                .put(toUint32(clientIdentifier))
+                .put(toUint32(opIdentifier.longValue()));
+
+        log.info("modify_bearer_dl: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * DeleteOrQuery Mobility Session.
+     *
+     * @param dpn               - DPN
+     * @param del_default_ebi   - Default EBI
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     * @param clientIdentifier  - Client Identifier
+     * @param opIdentifier      - Operation Identifier
+     * @param sessionId         - Session Id
+     */
+    public static void delete_session(
+            Short dpn,
+            Short del_default_ebi,
+            Long s1u_sgw_gtpu_teid,
+            Long clientIdentifier,
+            BigInteger opIdentifier,
+            Long sessionId
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(19)
+                .put(toUint8(dpn))
+                .put(DELETE_SESSION_TYPE)
+                .put(toUint64(BigInteger.valueOf(sessionId)))
+                .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+                .put(toUint32(clientIdentifier))
+                .put(toUint32(opIdentifier.longValue()));
+
+        log.info("delete_session: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Create Uplink Bearer.
+     *
+     * @param dpn               - DPN
+     * @param imsi              - IMSI
+     * @param default_ebi       - Default EBI
+     * @param dedicated_ebi     - Dedicated EBI
+     * @param s1u_sgw_gtpu_ipv4 - SGW GTP-U IPv4 Address
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     */
+    public static void create_bearer_ul(
+            Short dpn,
+            BigInteger imsi,
+            Short default_ebi,
+            Short dedicated_ebi,
+            Ip4Address s1u_sgw_gtpu_ipv4,
+            Long s1u_sgw_gtpu_teid
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(21)
+                .put(toUint8(dpn))
+                .put(CREATE_UL_BEARER_TYPE)
+                .put(toUint64(imsi))
+                .put(toUint8(default_ebi))
+                .put(toUint8(dedicated_ebi))
+                .put(toUint32(s1u_sgw_gtpu_ipv4.toInt()))
+                .put(toUint32(s1u_sgw_gtpu_teid));
+
+        log.info("create_bearer_ul: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Create Downlink Bearer.
+     *
+     * @param dpn               - DPN
+     * @param dedicated_ebi     - Default EBI
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     * @param s1u_enb_gtpu_ipv4 - ENodeB GTP-U IPv4 Address
+     * @param s1u_enb_gtpu_teid - ENodeB GTP-U TEID
+     */
+    public static void create_bearer_dl(
+            Short dpn,
+            Short dedicated_ebi,
+            Long s1u_sgw_gtpu_teid,
+            Ip4Address s1u_enb_gtpu_ipv4,
+            Long s1u_enb_gtpu_teid
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(16)
+                .put(toUint8(dpn))
+                .put(CREATE_DL_BEARER_TYPE)
+                .put(toUint8(dedicated_ebi))
+                .put(toUint32(s1u_sgw_gtpu_teid))
+                .put(toUint32(s1u_enb_gtpu_ipv4.toInt()))
+                .put(toUint32(s1u_enb_gtpu_teid));
+
+        log.info("create_bearer_dl: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Modify Downlink Bearer.
+     *
+     * @param dpn               - DPN
+     * @param s1u_sgw_gtpu_ipv4 - SGW GTP-U IPv4 Address
+     * @param s1u_enb_gtpu_teid - ENodeB TEID
+     * @param s1u_enb_gtpu_ipv4 - ENodeB GTP-U IPv4 Address
+     * @param clientIdentifier  - Client Identifier
+     * @param opIdentifier      - Operation Identifier
+     * @param sessionId         - Session Id
+     */
+    public static void modify_bearer_dl(
+            Short dpn,
+            Ip4Address s1u_enb_gtpu_ipv4,
+            Long s1u_enb_gtpu_teid,
+            Ip4Address s1u_sgw_gtpu_ipv4,
+            Long clientIdentifier,
+            BigInteger opIdentifier,
+            Long sessionId
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(32)
+                .put(toUint8(dpn))
+                .put(MODIFY_DL_BEARER_TYPE)
+                .put(toUint32(s1u_sgw_gtpu_ipv4.toInt()))
+                .put(toUint32(s1u_enb_gtpu_teid))
+                .put(toUint32(s1u_enb_gtpu_ipv4.toInt()))
+                .put(toUint64(BigInteger.valueOf(sessionId)))
+                .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+                .put(toUint32(clientIdentifier))
+                .put(toUint32(opIdentifier.longValue()));
+
+        log.info("modify_bearer_dl: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Modify Uplink Bearer.
+     *
+     * @param dpn               - DPN
+     * @param s1u_enb_gtpu_ipv4 - ENodeB GTP-U IPv4 Address
+     * @param s1u_enb_gtpu_teid - ENodeB GTP-U TEID
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     */
+    public static void modify_bearer_ul(
+            Short dpn,
+            Ip4Address s1u_enb_gtpu_ipv4,
+            Long s1u_enb_gtpu_teid,
+            Long s1u_sgw_gtpu_teid
+    ) {
+        ByteBuffer bb = ByteBuffer.allocate(15)
+                .put(toUint8(dpn))
+                .put(MODIFY_UL_BEARER_TYPE)
+                .put(toUint32(s1u_enb_gtpu_ipv4.toInt()))
+                .put(toUint32(s1u_enb_gtpu_teid))
+                .put(toUint32(s1u_sgw_gtpu_teid));
+
+        log.info("modify_bearer_ul: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * DeleteOrQuery Bearer.
+     *
+     * @param dpnTopic          - DPN
+     * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+     */
+    public static void delete_bearer(
+            Short dpnTopic,
+            Long s1u_sgw_gtpu_teid) {
+        ByteBuffer bb = ByteBuffer.allocate(7)
+                .put(toUint8(dpnTopic))
+                .put(DELETE_BEARER_TYPE)
+                .put(toUint32(s1u_sgw_gtpu_teid));
+
+        log.info("delete_bearer: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Creates the byte buffer to send ADC rules over ZMQ
+     *
+     * @param topic        - DPN Topic
+     * @param domain_name  - domain
+     * @param ip           - ipaddress/ipprefix (i.e. 127.0.0.1/32)
+     * @param drop         - Drop if 1
+     * @param rating_group - Rating Group
+     * @param service_ID   - Service ID
+     * @param sponsor_ID   - Sponsor ID
+     */
+    public static void send_ADC_rules(Short topic,
+                               String domain_name, String ip,
+                               Short drop, Long rating_group,
+                               Long service_ID, String sponsor_ID) {
+        Ip4Prefix ip_prefix = null;
+        if (ip != null) {
+            ip_prefix = Ip4Prefix.valueOf(ip);
+        }
+        Short selector_type = (short) (domain_name != null ? 0 : ip_prefix != null ? 2 : ip_prefix.address() != null ? 1 : 255);
+        if (selector_type == 255) {
+            log.warn("Domain/IP not found, failed to send rules");
+            return;
+        }
+        ByteBuffer bb = ByteBuffer.allocate(200);
+        bb.put(toUint8(topic))
+                .put(SEND_ADC_TYPE)
+                .put(toUint8(selector_type));
+        if (selector_type == 0) {
+            bb.put(toUint8((short) domain_name.length()))
+                    .put(domain_name.getBytes());
+        }
+        if ((selector_type == 1) || (selector_type == 2)) {
+            int ip_address_long = ip_prefix.address().toInt();
+            bb.put(toUint32(ip_address_long));
+        }
+        if (selector_type == 2) {
+            bb.put(toUint16(ip_prefix.prefixLength()));
+        }
+        if (drop != null)
+            bb.put(toUint8(drop));
+        if (rating_group != null)
+            bb.put(toUint32(rating_group));
+        if (service_ID != null)
+            bb.put(toUint32(service_ID));
+        if (sponsor_ID != null && (short) sponsor_ID.length() > 0) {
+            bb.put(toUint8((short) sponsor_ID.length()))
+                    .put(sponsor_ID.getBytes());
+        }
+        bb.put(toUint8(ZMQSBSubscriberManager.getControllerTopic()));
+
+        log.info("send_ADC_rules: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Ensures the session id is an unsigned 64 bit integer
+     *
+     * @param sessionId - session id received from the DPN
+     * @return unsigned session id
+     */
+    private static BigInteger checkSessionId(BigInteger sessionId) {
+        if (sessionId.compareTo(BigInteger.ZERO) < 0) {
+            sessionId = sessionId.add(BigInteger.ONE.shiftLeft(64));
+        }
+        return sessionId;
+    }
+
+    /**
+     * Decodes a DownlinkDataNotification
+     *
+     * @param buf - message buffer
+     * @param key - Concatenation of node id + / + network id
+     * @return DownlinkDataNotification or null if it could not be successfully decoded
+     */
+    private static DownlinkDataNotification processDDN(byte[] buf, String key) {
+        DownlinkDataNotification ddnB = new DefaultDownlinkDataNotification();
+        ddnB.sessionId(checkSessionId(toBigInt(buf, 2)));
+        ddnB.notificationMessageType(DOWNLINK_DATA_NOTIFICATION_STRING);
+        ddnB.clientId(ClientIdentifier.of(FpcIdentity.of(FpcIdentityUnion.of(fromIntToLong(buf, 10)))));
+        ddnB.opId(OpIdentifier.of(BigInteger.valueOf(fromIntToLong(buf, 14))));
+        ddnB.notificationDpnId(uplinkDpnMap.get(key));
+        return ddnB;
+    }
+
+    /**
+     * Decodes a DPN message.
+     *
+     * @param buf - message buffer
+     * @return - A pair with the DPN Id and decoded Object
+     */
+    public static Map.Entry<FpcDpnId, Object> decode(byte[] buf) {
+        if (buf[1] == DPN_REPLY) {
+            return null;
+        } else if (buf[1] == DOWNLINK_DATA_NOTIFICATION) {
+            short nodeIdLen = buf[18];
+            short networkIdLen = buf[19 + nodeIdLen];
+            String key = new String(Arrays.copyOfRange(buf, 19, 19 + nodeIdLen)) + "/" + new String(Arrays.copyOfRange(buf, 20 + nodeIdLen, 20 + nodeIdLen + networkIdLen));
+            return uplinkDpnMap.get(key) == null ? null : new AbstractMap.SimpleEntry<>(uplinkDpnMap.get(key), processDDN(buf, key));
+        } else if (buf[1] == DPN_STATUS_INDICATION) {
+            DPNStatusIndication.Status status = null;
+
+            short nodeIdLen = buf[8];
+            short networkIdLen = buf[9 + nodeIdLen];
+            String key = new String(Arrays.copyOfRange(buf, 9, 9 + nodeIdLen)) + "/" + new String(Arrays.copyOfRange(buf, 10 + nodeIdLen, 10 + nodeIdLen + networkIdLen));
+            if (buf[3] == DPN_OVERLOAD_INDICATION) {
+                status = DPNStatusIndication.Status.OVERLOAD_INDICATION;
+            } else if (buf[3] == DPN_HELLO) {
+                status = DPNStatusIndication.Status.HELLO;
+                topicToNodeMap.put(key, (short) buf[2]);
+            } else if (buf[3] == DPN_BYE) {
+                status = DPNStatusIndication.Status.BYE;
+                topicToNodeMap.remove(key);
+            }
+            return new AbstractMap.SimpleEntry<>(uplinkDpnMap.get(key), new DPNStatusIndication(status, key));
+        }
+        return null;
+    }
+
+    /**
+     * Gets the mapping for node id / network id to ZMQ Topic
+     *
+     * @param Key - Concatenation of node id + / + network id
+     * @return - ZMQ Topic
+     */
+    public static Short getTopicFromNode(String Key) {
+        Short aShort = topicToNodeMap.get(Key);
+        return aShort != null ? aShort : (short) 1;
+    }
+
+    /**
+     * Provides basic status changes,
+     */
+    public static class DPNStatusIndication {
+        private final Status status;
+        private final String key; //nodeId +"/"+ networkId
+        /**
+         * Node Reference of the DPN
+         */
+        public Short nodeRef;
+        /**
+         * Constructor providing the DPN and its associated Status.
+         *
+         * @param status - DPN Status
+         * @param key    - Combination of node id and network id
+         */
+        public DPNStatusIndication(Status status,
+                                   String key) {
+            this.status = status;
+            this.key = key;
+        }
+
+        /**
+         * Provides DPN Status
+         *
+         * @return Status associated to the DPN.
+         */
+        public Status getStatus() {
+            return status;
+        }
+
+        /**
+         * Provides the DPN key - nodeId +"/"+ networkId
+         *
+         * @return FpcDpnId
+         */
+        public String getKey() {
+            return this.key;
+        }
+
+        /**
+         * Basic DPN Status
+         */
+        public enum Status {
+            HELLO,
+            BYE,
+            OVERLOAD_INDICATION
+        }
+    }
+}
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/package-info.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/package-info.java
new file mode 100644
index 0000000..45fe96c
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * FPC Agent.
+ */
+package org.onosproject.fpcagent;
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/rest/AppWebApplication.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/rest/AppWebApplication.java
new file mode 100644
index 0000000..d4e68fc
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/rest/AppWebApplication.java
@@ -0,0 +1,15 @@
+package org.onosproject.fpcagent.rest;
+
+import org.onlab.rest.AbstractWebApplication;
+
+import java.util.Set;
+
+/**
+ * Sample REST API web application.
+ */
+public class AppWebApplication extends AbstractWebApplication {
+    @Override
+    public Set<Class<?>> getClasses() {
+        return getClasses(AppWebResource.class);
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/rest/AppWebResource.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/rest/AppWebResource.java
new file mode 100644
index 0000000..12de2ed
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/rest/AppWebResource.java
@@ -0,0 +1,81 @@
+package org.onosproject.fpcagent.rest;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.fpcagent.FpcService;
+import org.onosproject.fpcagent.dto.configure.Configure;
+import org.onosproject.fpcagent.dto.dpn.AddDpn;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+
+@Path("/")
+public class AppWebResource extends AbstractWebResource {
+    private static final Logger log = LoggerFactory.getLogger(AppWebResource.class);
+
+    protected CoreService coreService = get(CoreService.class);
+    private FpcService fpcService;
+
+    public AppWebResource() {
+        ApplicationId appId = coreService.getAppId("org.onosproject.fpcagent");
+        fpcService = get(FpcService.class);
+    }
+
+    @POST
+    @Path("configure")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response configure(InputStream stream) {
+        try {
+            ObjectNode node = (ObjectNode) mapper().readTree(stream);
+            Configure configure = mapper().readValue(node.toString(), Configure.class);
+            fpcService.configure(configure);
+        } catch (IOException e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+        return Response.ok().build();
+    }
+
+    @POST
+    @Path("dpns/add_dpn")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response addDpn(InputStream stream) {
+        try {
+            ObjectNode node = (ObjectNode) mapper().readTree(stream);
+            AddDpn dpns = mapper().readValue(node.toString(), AddDpn.class);
+            fpcService.addDpn(dpns);
+        } catch (IOException e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+        return Response.ok().build();
+    }
+
+    @DELETE
+    @Path("dpns/{dpn}")
+    public Response deleteDpn(@PathParam("dpn") String dpn) {
+        if (dpn != null) {
+            fpcService.deleteDpn(dpn);
+            return Response.ok().build();
+        }
+        return Response.ok().build();
+    }
+
+    @POST
+    @Path("register_client")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response registerClient(InputStream stream) {
+
+        return Response.ok().build();
+    }
+}
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
new file mode 100644
index 0000000..d79cf69
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/NBWorkManager.java
@@ -0,0 +1,80 @@
+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
new file mode 100644
index 0000000..35701fe
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java
@@ -0,0 +1,71 @@
+package org.onosproject.fpcagent.workers;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZContext;
+import org.zeromq.ZMQ;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class ZMQSBPublisherManager implements AutoCloseable {
+    private static final Logger log = LoggerFactory.getLogger(ZMQSBPublisherManager.class);
+    private static ZMQSBPublisherManager _instance = null;
+    private final ZContext ctx;
+    private final String address;
+    private final BlockingQueue<ByteBuffer> blockingQueue;
+    private final int poolSize;
+    private boolean run;
+
+    protected ZMQSBPublisherManager(String address, int poolSize) {
+        this.ctx = new ZContext();
+        this.address = address;
+        this.run = true;
+        this.blockingQueue = new LinkedBlockingQueue<>();
+        this.poolSize = poolSize;
+    }
+
+    public static ZMQSBPublisherManager createInstance(String address, int poolSize) {
+        if (_instance == null) {
+            _instance = new ZMQSBPublisherManager(address, poolSize);
+        }
+        return _instance;
+    }
+
+    public static ZMQSBPublisherManager getInstance() {
+        return _instance;
+    }
+
+    public void send(ByteBuffer buf) {
+        try {
+            blockingQueue.put(buf);
+        } catch (InterruptedException e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+    }
+
+    public void open() {
+        ExecutorService executorService = Executors.newFixedThreadPool(this.poolSize);
+        executorService.submit(() -> {
+            ZMQ.Socket socket = ctx.createSocket(ZMQ.PUB);
+            socket.connect(address);
+            while ((!Thread.currentThread().isInterrupted()) && run) {
+                try {
+                    byte[] array = blockingQueue.take().array();
+                    socket.send(array);
+                } catch (InterruptedException e) {
+                    log.error(ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+        });
+    }
+
+    @Override
+    public void close() {
+        run = false;
+    }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java
new file mode 100644
index 0000000..cddd6d4
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java
@@ -0,0 +1,314 @@
+package org.onosproject.fpcagent.workers;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onosproject.fpcagent.helpers.DpnApi;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZContext;
+import org.zeromq.ZMQ;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadLocalRandom;
+
+import static org.onosproject.fpcagent.helpers.Converter.*;
+
+public class ZMQSBSubscriberManager implements AutoCloseable {
+    private static final Logger log = LoggerFactory.getLogger(ZMQSBSubscriberManager.class);
+    private static int MIN_TOPIC_VAL = 4;
+    private static int MAX_TOPIC_VAL = 255;
+    private static byte ASSIGN_ID = 0b0000_1010;
+    private static byte ASSIGN_CONFLICT = 0b0000_1011;
+    private static byte HELLO_REPLY = 0b0000_1101;
+    private static byte CONTROLLER_STATUS_INDICATION = 0b0000_1110;
+    private static byte HELLO = 0b0000_0001;
+    private static byte GOODBYE = 0b0000_0010;
+    private static ZMQSBSubscriberManager _instance = null;
+    private static Long controllerSourceId;
+    private static Short subscriberId;
+    private final String address;
+    private final Short broadcastAllId;
+    private final Short broadcastControllersId;
+    private final Short broadcastDpnsId;
+    private final String nodeId;
+    private final String networkId;
+    private boolean run;
+    private boolean conflictingTopic;
+    private Future<?> broadcastAllWorker;
+    private Future<?> broadcastControllersWorker;
+    private Future<?> broadcastTopicWorker;
+    private Future<?> generalWorker;
+
+    protected ZMQSBSubscriberManager(String address, String broadcastAllId, String broadcastControllersId,
+                                     String broadcastDpnsId, String nodeId, String networkId) {
+        this.address = address;
+        this.run = true;
+
+        this.nodeId = nodeId;
+        this.networkId = networkId;
+        this.broadcastAllId = Short.parseShort(broadcastAllId);
+        this.broadcastControllersId = Short.parseShort(broadcastControllersId);
+        this.broadcastDpnsId = Short.parseShort(broadcastDpnsId);
+
+        this.conflictingTopic = false;
+        controllerSourceId = (long) ThreadLocalRandom.current().nextInt(0, 65535);
+    }
+
+    public static ZMQSBSubscriberManager createInstance(String address, String broadcastAllId,
+                                                        String broadcastControllersId, String broadcastDpnsId,
+                                                        String nodeId, String networkId) {
+        if (_instance == null) {
+            _instance = new ZMQSBSubscriberManager(address, broadcastAllId, broadcastControllersId,
+                    broadcastDpnsId, nodeId, networkId);
+        }
+        return _instance;
+    }
+
+    public static ZMQSBSubscriberManager getInstance() {
+        return _instance;
+    }
+
+    public static Short getControllerTopic() {
+        return subscriberId;
+    }
+
+    public static Long getControllerSourceId() {
+        return controllerSourceId;
+    }
+
+    public void open() {
+        short subscriberId = (short) ThreadLocalRandom.current().nextInt(MIN_TOPIC_VAL, MAX_TOPIC_VAL + 1);
+
+        broadcastAllWorker = Executors.newSingleThreadExecutor().submit(new ZMQSubscriberWorker(broadcastAllId));
+        broadcastControllersWorker = Executors.newSingleThreadExecutor()
+                .submit(new ZMQSubscriberWorker(broadcastControllersId));
+        broadcastTopicWorker = Executors.newSingleThreadExecutor().submit(new BroadcastTopic(subscriberId));
+    }
+
+    @Override
+    public void close() {
+        run = false;
+    }
+
+    /**
+     * Interrupts the BroadcastTopicworker if there is an Assign topic Conflict
+     *
+     * @param conflict - Flag to indicate conflict
+     * @param subId    - Topic Id that caused the conflict
+     */
+    protected void BroadcastAllSubIdCallBack(boolean conflict, Short subId) {
+        if (conflict && subscriberId.equals(subId)) {
+            this.conflictingTopic = true;
+            broadcastTopicWorker.cancel(true);
+        }
+    }
+
+    /**
+     * Broadcasts the GOODBYE message to all the DPNs
+     */
+    public void sendGoodbyeToDpns() {
+        ByteBuffer bb = ByteBuffer.allocate(10 + nodeId.length() + networkId.length());
+        bb.put(toUint8(broadcastDpnsId))
+                .put(CONTROLLER_STATUS_INDICATION)
+                .put(toUint8(subscriberId))
+                .put(GOODBYE)
+                .put(toUint32(controllerSourceId))
+                .put(toUint8((short) nodeId.length()))
+                .put(nodeId.getBytes())
+                .put(toUint8((short) networkId.length()))
+                .put(networkId.getBytes());
+
+        log.info("sendGoodbyeToDpns: {}", bb.array());
+        ZMQSBPublisherManager.getInstance().send(bb);
+    }
+
+    /**
+     * Broadcasts an Assign Conflict message
+     *
+     * @param contents - byte array received over the southbound.
+     */
+    protected void SendAssignConflictMessage(byte[] contents) {
+        byte topic = contents[2];
+        short nodeIdLen = contents[7];
+        short networkIdLen = contents[8 + nodeIdLen];
+        String node_id = new String(Arrays.copyOfRange(contents, 8, 8 + nodeIdLen));
+        String network_id = new String(Arrays.copyOfRange(contents, 9 + nodeIdLen, 9 + nodeIdLen + networkIdLen));
+
+        if (toUint8(subscriberId) == topic || nodeId.equals(node_id) || networkId.equals(network_id)) {
+            ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length());
+            bb.put(toUint8(broadcastAllId))
+                    .put(ASSIGN_CONFLICT)
+                    .put(topic)
+                    .put(toUint32(controllerSourceId))
+                    .put(toUint8((short) nodeId.length()))
+                    .put(nodeId.getBytes())
+                    .put(toUint8((short) networkId.length()))
+                    .put(networkId.getBytes());
+
+            log.info("SendAssignConflictMessage: {}", bb.array());
+            ZMQSBPublisherManager.getInstance().send(bb);
+        }
+    }
+
+    protected class ZMQSubscriberWorker implements Runnable {
+        private final Short subscriberId;
+        private ZContext ctx;
+
+        ZMQSubscriberWorker(Short subscriberId) {
+            this.subscriberId = subscriberId;
+            this.ctx = new ZContext();
+        }
+
+        /**
+         * Sends a reply to a DPN Hello
+         *
+         * @param dpnStatus - DPN Status Indication message received from the DPN
+         */
+        protected void sendHelloReply(DpnApi.DPNStatusIndication dpnStatus) {
+            if (DpnApi.getTopicFromNode(dpnStatus.getKey()) != null) {
+                ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length())
+                        .put(toUint8(DpnApi.getTopicFromNode(dpnStatus.getKey())))
+                        .put(HELLO_REPLY)
+                        .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+                        .put(toUint32(ZMQSBSubscriberManager.getControllerSourceId()))
+                        .put(toUint8((short) nodeId.length()))
+                        .put(nodeId.getBytes())
+                        .put(toUint8((short) networkId.length()))
+                        .put(networkId.getBytes());
+
+                log.info("sendHelloReply: {}", bb.array());
+                ZMQSBPublisherManager.getInstance().send(bb);
+            }
+        }
+
+        @Override
+        public void run() {
+            ZMQ.Socket subscriber = this.ctx.createSocket(ZMQ.SUB);
+            subscriber.connect(address);
+            subscriber.subscribe(new byte[]{toUint8(subscriberId)});
+            while ((!Thread.currentThread().isInterrupted()) && run) {
+                byte[] contents = subscriber.recv();
+                byte topic = contents[0];
+                byte messageType = contents[1];
+                switch (topic) {
+                    case 1:
+                        if (messageType == ASSIGN_CONFLICT && toInt(contents, 3) != controllerSourceId) {
+                            BroadcastAllSubIdCallBack(true, (short) contents[2]);
+                        } else if (messageType == ASSIGN_ID && toInt(contents, 3) != controllerSourceId) {
+                            SendAssignConflictMessage(contents);
+                        }
+                        break;
+                    default:
+                        Map.Entry<FpcDpnId, Object> entry = 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);
+                                }
+                            }
+                        }
+                }
+            }
+            subscriber.disconnect(address);
+            subscriber.close();
+            ctx.destroySocket(subscriber);
+            try {
+                Thread.currentThread().join();
+            } catch (InterruptedException e) {
+                log.error(ExceptionUtils.getFullStackTrace(e));
+            }
+        }
+    }
+
+    /**
+     * Class to broadcast a topic for the controller
+     */
+    protected class BroadcastTopic implements Runnable {
+        private Short topic;
+
+        /**
+         * Constructor
+         *
+         * @param topic - Topic to broadcast
+         */
+        public BroadcastTopic(Short topic) {
+            this.topic = topic;
+        }
+
+        /**
+         * Broadcasts the topic
+         */
+        private void broadcastTopic() {
+            ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length());
+            bb.put(toUint8(broadcastAllId))
+                    .put(ASSIGN_ID)
+                    .put(toUint8(this.topic))
+                    .put(toUint32(controllerSourceId))
+                    .put(toUint8((short) nodeId.length()))
+                    .put(nodeId.getBytes())
+                    .put(toUint8((short) networkId.length()))
+                    .put(networkId.getBytes());
+
+            log.info("broadcastTopic: {}", bb.array());
+            ZMQSBPublisherManager.getInstance().send(bb);
+        }
+
+        /**
+         * Broadcasts the HELLO message to all the DPNs
+         */
+        private void sendHelloToDpns() {
+            ByteBuffer bb = ByteBuffer.allocate(10 + nodeId.length() + networkId.length());
+            bb.put(toUint8(broadcastDpnsId))
+                    .put(CONTROLLER_STATUS_INDICATION)
+                    .put(toUint8(subscriberId))
+                    .put(HELLO)
+                    .put(toUint32(controllerSourceId))
+                    .put(toUint8((short) nodeId.length()))
+                    .put(nodeId.getBytes())
+                    .put(toUint8((short) networkId.length()))
+                    .put(networkId.getBytes());
+
+            log.info("sendHelloToDpns: {}", bb.array());
+            ZMQSBPublisherManager.getInstance().send(bb);
+        }
+
+        @Override
+        public void run() {
+            try {
+                this.broadcastTopic();
+                log.info("Thread sleeping: " + Thread.currentThread().getName());
+                Thread.sleep(10000);
+            } catch (InterruptedException e) {
+                if (conflictingTopic) {
+                    conflictingTopic = false;
+                    this.topic = (short) ThreadLocalRandom.current().nextInt(MIN_TOPIC_VAL, MAX_TOPIC_VAL + 1);
+                    subscriberId = this.topic;
+                    this.run();
+                    return;
+                } else {
+                    log.error(ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+            subscriberId = this.topic;
+            log.info("Topic Id: " + this.topic);
+            generalWorker = Executors.newSingleThreadExecutor().submit(new ZMQSubscriberWorker(this.topic));
+
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                log.error(ExceptionUtils.getFullStackTrace(e));
+            }
+            sendHelloToDpns();
+        }
+
+    }
+}
diff --git a/apps/fpcagent/src/main/webapp/WEB-INF/web.xml b/apps/fpcagent/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..92d9960
--- /dev/null
+++ b/apps/fpcagent/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016-present Open Networking Laboratory
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+         id="ONOS" version="2.5">
+    <display-name>FPC Agent REST API</display-name>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Secured</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>admin</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <security-role>
+        <role-name>admin</role-name>
+    </security-role>
+
+    <login-config>
+        <auth-method>BASIC</auth-method>
+        <realm-name>karaf</realm-name>
+    </login-config>
+
+    <servlet>
+        <servlet-name>JAX-RS Service</servlet-name>
+        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+        <init-param>
+            <param-name>javax.ws.rs.Application</param-name>
+            <param-value>org.onosproject.fpcagent.rest.AppWebApplication</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>JAX-RS Service</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+</web-app>
\ No newline at end of file
diff --git a/models/fpcagent/BUCK b/models/fpcagent/BUCK
new file mode 100644
index 0000000..2615870
--- /dev/null
+++ b/models/fpcagent/BUCK
@@ -0,0 +1,14 @@
+COMPILE_DEPS = [
+    '//models/common:onos-models-common',
+]
+
+APPS = [
+    'org.onosproject.models.common',
+]
+
+yang_model(
+    app_name = 'org.onosproject.models.fpcagent',
+    title = 'FPC Agent YANG Models',
+    deps = COMPILE_DEPS,
+    required_apps = APPS,
+)
diff --git a/models/fpcagent/src/main/yang/fpc-config.yang b/models/fpcagent/src/main/yang/fpc-config.yang
new file mode 100644
index 0000000..10a656c
--- /dev/null
+++ b/models/fpcagent/src/main/yang/fpc-config.yang
@@ -0,0 +1,106 @@
+module fpc-config {
+    yang-version 1;
+    namespace "urn:opendaylight:fpc:config";
+    prefix fpc-config;
+
+    description
+      "Configuration for ...";
+
+    revision "2016-09-27" {
+        description
+            "Initial revision.";
+    }
+
+    container fpc-config {
+    	leaf use-memcached {
+    	  type boolean;
+    	}
+    	leaf memcached-uri {
+    	  type string;
+    	}
+    	leaf memcached-threads {
+    	  type uint16;
+    	}
+        leaf scheduled-monitors-poolsize {
+          type uint16;
+        }
+        leaf monitor-threads  {
+          type uint16;
+        }
+        leaf dpn-listener-uri {
+          type string;
+        }
+        leaf dpn-listener-id {
+          type string;
+        }
+        leaf dpn-client-uri {
+          type string;
+        }
+        leaf dpn-message-processor-threads{
+          type uint16;
+        }
+        leaf dpn-client-threads {
+          type uint16;
+        }
+        leaf metricsupdate-ms {
+          type uint32;
+        }
+        leaf mobilityupdate-ms {
+          type uint32;
+        }
+        leaf node-id {
+          type string;
+        }
+        leaf network-id {
+          type string;
+        }
+        leaf activation-threads {
+          type uint16;
+        }
+        leaf target-read-limit {
+          type uint16;
+        }
+        leaf default-tenant-id {
+          type string;
+        }
+        leaf default-group-id {
+          type string;
+        }
+        leaf prefers-fast-clients {
+          type boolean;
+        }
+        leaf http-notifier-clients {
+          type uint16;
+        }
+        leaf zmq-nbi-server-poolsize {
+          type uint16;
+        }
+        leaf zmq-nbi-server-uri {
+          type string;
+        }
+        leaf zmq-nbi-inproc-uri {
+          type string;
+        }
+        leaf zmq-nbi-handler-poolsize {
+          type uint16;
+        }
+        leaf zmq-broadcast-all {
+       	  type string;
+       	}
+       	leaf zmq-broadcast-controllers {
+       	  type string;
+       	}
+       	leaf zmq-broadcast-dpns {
+       	  type string;
+       	}
+        leaf http-nio2-nb-poolsize {
+          type uint16;
+        }
+        leaf http-nio2-nb-port {
+          type uint16;
+        }
+        leaf max-trans-rate {
+          type uint16;
+        }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/fpc.yang b/models/fpcagent/src/main/yang/fpc.yang
new file mode 100644
index 0000000..5cd95f4
--- /dev/null
+++ b/models/fpcagent/src/main/yang/fpc.yang
@@ -0,0 +1,169 @@
+module fpc {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:fpc";
+    prefix "fpc";
+
+    import ietf-dmm-fpcagent { prefix fpcagent; }
+    import ietf-dmm-fpcbase { prefix fpcbase; }
+    import ietf-inet-types { prefix inet; }
+    import ietf-dmm-fpc-pmip { prefix fpc-pmip; }
+    import ietf-dmm-threegpp { prefix threegpp; }
+
+    revision "2015-01-05" {
+        description "Initial revision of fpc model";
+    }
+
+   // grouping zmq-dpn-config {
+   //   leaf topic {
+   //     type string;
+  //    }
+   // }
+
+   // augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-topology/fpcagent:dpns" {
+  //    uses zmq-dpn-config;
+   // }
+
+    // New DPN Type
+    identity zmq-dpn-control-protocol {
+      base "fpcbase:fpc-dpn-control-protocol";
+    }
+
+    typedef membership-match-type {
+      type enumeration {
+        enum eq { value 0; }
+        enum super { value 1; }
+        enum psuper { value 2; }
+        enum sub { value 3; }
+        enum psub { value 4; }
+        enum overlap { value 5; }
+        enum nonoverlap { value 6; }
+      }
+    }
+
+    grouping membership-value {
+      leaf policy-membership {
+        type string;
+      }
+    }
+
+    augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-policy/fpcagent:descriptors/fpcagent:descriptor-value" {
+      case tft-plusplus {
+          uses fpc:membership-value;
+          leaf membership-match-type {
+            type fpc:membership-match-type;
+          }
+      }
+    }
+
+    augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-mobility/fpcagent:contexts" {
+      uses fpc:membership-value;
+    }
+    augment "/fpcagent:configure/fpcagent:input/fpcagent:op_body/fpcagent:create_or_update/fpcagent:contexts" {
+      uses fpc:membership-value;
+    }
+    augment "/fpcagent:configure-bundles/fpcagent:input/fpcagent:bundles/fpcagent:op_body/fpcagent:create_or_update/fpcagent:contexts" {
+       uses fpc:membership-value;
+    }
+    augment "/fpcagent:configure/fpcagent:output/fpcagent:result-type/fpcagent:common-success/fpcagent:contexts" {
+       uses fpc:membership-value;
+    }
+    augment "/fpcagent:configure-bundles/fpcagent:output/fpcagent:bundles/fpcagent:result-type/fpcagent:common-success/fpcagent:contexts" {
+       uses fpc:membership-value;
+    }
+    // TODO - Add Notification Augments for membership-value
+
+      container tx-stats {
+        config false;
+        leaf last-ts {
+          type string;
+        }
+        leaf total-txs {
+          type uint64;
+        }
+        list states {
+          key state;
+          leaf state {
+            type string;
+          }
+          leaf entries {
+            type uint64;
+          }
+          container total-time {
+            leaf mantissa {
+              type uint64;
+            }
+            leaf exponent {
+              type int32;
+            }
+          }
+          container average-time {
+            leaf mantissa {
+              type uint64;
+            }
+            leaf exponent {
+              type int32;
+            }
+          }
+        }
+      }
+
+    grouping connection-config {
+        leaf client-id {
+          type fpcagent:client-identifier;
+        }
+        leaf tenant-id {
+          type fpcbase:fpc-identity;
+        }
+        leaf-list supported-features {
+          type string;
+        }
+        leaf endpoint-uri {
+          type inet:uri;
+        }
+        leaf supports-oknotify-model {
+          type boolean;
+        }
+        leaf supports-ack-model {
+          type boolean;
+        }
+    }
+
+
+    container connection-info {
+      list connections {
+          config false;
+          key client-id;
+          leaf client-id {
+            type string;
+          }
+          container requested-info {
+            uses fpc:connection-config;
+          }
+          container assigned-info {
+            uses fpc:connection-config;
+          }
+      }
+    }
+
+    rpc register_client {
+      input {
+        uses fpc:connection-config;
+      }
+      output {
+        uses fpc:connection-config;
+      }
+    }
+
+    rpc deregister_client {
+      input {
+        leaf client-id {
+          type fpcagent:client-identifier;
+        }
+      }
+      output {
+      	leaf client-id {
+          type fpcagent:client-identifier;
+        }
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang
new file mode 100644
index 0000000..c44aaab
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang
@@ -0,0 +1,71 @@
+module ietf-dmm-fpc-pmip {
+    namespace "urn:ietf:params:xml:ns:yang:ietf-dmm-fpc-pmip";
+    prefix fpc-pmip;
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     Forwarding Policy Configuration Protocol.(FPCP)";
+
+    revision 2016-01-19 {
+        description "Changes based on -01 version of FPCP draft.";
+        reference "draft-ietf-dmm-fpc-cpdp-01";
+    }
+
+    identity pmip-tunnel-type {
+        description "PMIP Tunnel Type";
+    }
+    identity grev1 {
+        base "fpc-pmip:pmip-tunnel-type";
+    }
+    identity grev2 {
+        base "fpc-pmip:pmip-tunnel-type";
+    }
+    identity ipinip {
+        base "fpc-pmip:pmip-tunnel-type";
+    }
+    grouping pmip-mobility {
+        leaf type {
+            type identityref {
+                base "fpc-pmip:pmip-tunnel-type";
+            }
+        }
+        choice value {
+            case gre {
+                leaf key {
+                    type uint32;
+                    description "GRE_KEY";
+                }
+            }
+        }
+    }
+
+    typedef pmip-instr {
+      description "Instruction Set for PMIP";
+      type bits {
+        bit assign-ip {
+          position 0;
+        }
+        bit assign-dpn {
+          position 1;
+        }
+        bit session {
+          position 2;
+        }
+        bit uplink {
+          position 3;
+        }
+        bit downlink {
+          position 4;
+        }
+      }
+    }
+
+    grouping pmip-commandset {
+      leaf instr-pmip-mob {
+        type fpc-pmip:pmip-instr;
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang
new file mode 100644
index 0000000..3845591
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang
@@ -0,0 +1,95 @@
+module ietf-dmm-fpc-policyext {
+    namespace "urn:ietf:params:xml:ns:yang:fpcpolicyext";
+    prefix fpcpolicyext;
+
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     Forwarding Policy Configuration Protocol (FPCP)
+     common Policy Action and Descriptor extensions";
+
+    revision 2016-08-03 {
+        description "Changes based on -04 version of FPC draft.";
+        reference "draft-ietf-dmm-fpc-cpdp-04";
+    }
+
+    grouping simple-nat {
+      leaf outbound-nat-address {
+        type inet:ip-address;
+      }
+    }
+
+    grouping simple-napt {
+      leaf source-port {
+        type inet:port-number;
+      }
+      leaf outbound-napt-address {
+        type inet:ip-address;
+      }
+      leaf destination-port {
+        type inet:port-number;
+      }
+    }
+
+    grouping prefix-traffic-descriptor {
+        description
+        "Traffic descriptor group collects parameters to
+         identify target traffic flow.  It represents
+         source/destination as IP prefixes";
+
+        leaf destination-ip {
+            type inet:ip-prefix;
+            description "Rule of destination IP";
+        }
+        leaf source-ip {
+            type inet:ip-prefix;
+            description "Rule of source IP";
+        }
+    }
+
+    grouping rating-action {
+      description "Rudimentary rating action applied based upon RFC 4006 attributes";
+      leaf service-context-id {
+        type string;
+        description "Per RFC 4006 - Contains a unique identifier of the Diameter credit-control service
+           specific document that applies to the request.  The format of the Service-Context-Id is:
+
+           <service-context>@<domain>
+
+           service-context = Token
+
+         The Token is an arbitrary string of characters and digits.
+
+         'domain' represents the entity that allocated the Service-Context-Id.";
+      }
+      leaf service-identifier {
+        type uint32;
+        description "From RFC 4006 - Contains the identifier of a service.  The specific service the
+           request relates to is uniquely identified by the combination of
+           Service-Context-Id and Service-Identifier AVPs.";
+      }
+      leaf rating-group {
+        type uint32;
+        description "From RFC 4006 - Contains the identifier of a rating group.  All the services subject
+           to the same rating type are part of the same rating group.  The
+           specific rating group the request relates to is uniquely identified
+           by the combination of Service-Context-Id and Rating-Group AVPs.";
+      }
+    }
+
+    grouping domain-descriptor-list {
+      description "Descriptors for list of domains";
+      leaf-list source-domains {
+          type inet:domain-name;
+          description "Source Domain Names";
+      }
+      leaf-list destination-domains {
+          type inet:domain-name;
+          description "Destination Domain Names";
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang
new file mode 100644
index 0000000..1b1ddd6
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang
@@ -0,0 +1,664 @@
+module ietf-dmm-fpcagent {
+    namespace "urn:ietf:params:xml:ns:yang:fpcagent";
+    prefix fpcagent;
+
+    import ietf-dmm-fpcbase { prefix fpcbase; revision-date 2016-08-03; }
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+    import ietf-dmm-fpc-pmip { prefix fpc-pmip; revision-date 2016-01-19; }
+    import ietf-dmm-threegpp { prefix threegpp; }
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     Forwarding Policy Configuration Protocol.(FPCP)";
+
+    revision 2016-08-03 {
+        description "Changes based on -04 version of FPC draft.";
+        reference "draft-ietf-dmm-fpc-cpdp-04";
+    }
+    feature fpc-cloning {
+      description "An ability to support cloning in the RPC.";
+    }
+    feature fpc-basename-registry {
+      description "Ability to track Base Names already provisioned on the Agent";
+    }
+    feature fpc-bundles {
+      description "Ability for Client to send multiple bundles of actions to
+        an Agent";
+    }
+    feature fpc-client-binding {
+      description "Allows a FPC Client to bind a DPN to an Topology Object";
+    }
+    feature fpc-auto-binding {
+      description "Allows a FPC Agent to advertise Topology Objects that could be DPNs";
+    }
+    feature instruction-bitset {
+      description "Allows the expression of instructions (bit sets) over FPC.";
+    }
+    feature operation-ref-scope {
+      description "Provides the scope of refeneces in an operation.  Used to optmize
+        the Agent processing.";
+    }
+
+    typedef agent-identifier {
+        type fpcbase:fpc-identity;
+    }
+
+    typedef client-identifier {
+        type fpcbase:fpc-identity;
+    }
+
+    grouping basename-info {
+          leaf basename {
+            if-feature fpcagent:fpc-basename-registry;
+            description "Rules Basename";
+            type fpcbase:fpc-identity;
+          }
+          leaf base-state {
+            if-feature fpcagent:fpc-basename-registry;
+            type string;
+          }
+          leaf base-checkpoint {
+            if-feature fpcagent:fpc-basename-registry;
+            type string;
+          }
+    }
+
+    // Top Level Structures
+    container tenants {
+        description "";
+
+        list tenant {
+            description "";
+            key "tenant-id";
+            leaf tenant-id {
+                type fpcbase:fpc-identity;
+            }
+
+            container fpc-policy {
+              list policy-groups {
+                  key "policy-group-id";
+                  uses fpcbase:fpc-policy-group;
+              }
+              list policies {
+                  key "policy-id";
+                  uses fpcbase:fpc-policy;
+              }
+              list descriptors {
+                key descriptor-id;
+                uses fpcbase:fpc-descriptor;
+              }
+              list actions {
+                  key action-id;
+                  uses fpcbase:fpc-action;
+              }
+            }
+
+            container fpc-mobility {
+              config false;
+              list contexts {
+                  key context-id;
+                  uses fpcbase:fpc-context;
+              }
+              list ports {
+                  key port-id;
+                  uses fpcbase:fpc-port;
+              }
+              list monitors {
+                  key monitor-id;
+                  uses fpcbase:monitor-config;
+              }
+            }
+            container fpc-topology {
+              // Basic Agent Topology Structures
+              list domains {
+                key domain-id;
+                uses fpcbase:fpc-domain;
+                uses fpcagent:basename-info;
+              }
+
+              list dpn-group-peers {
+                  if-feature fpcbase:fpc-basic-agent;
+                  key "remote-dpn-group-id";
+                  uses fpcbase:fpc-dpn-peer-group;
+              }
+              leaf topology-dpn-id {
+                if-feature fpcbase:fpc-basic-agent;
+                type fpcbase:fpc-dpn-id;
+              }
+              leaf-list control-protocols {
+                if-feature fpcbase:fpc-basic-agent;
+                type identityref {
+                  base "fpcbase:fpc-dpn-control-protocol";
+                }
+              }
+
+              list dpn-groups {
+                  if-feature fpcbase:fpc-multi-dpn;
+                  key dpn-group-id;
+                  uses fpcagent:fpc-dpn-group;
+                  list domains {
+                    key domain-id;
+                    uses fpcbase:fpc-domain;
+                    uses fpcagent:basename-info;
+                  }
+              }
+              list dpns {
+                  if-feature fpcbase:fpc-multi-dpn;
+                  key dpn-id;
+                  uses fpcbase:fpc-dpn;
+              }
+            }
+
+        }
+    }
+
+    container fpc-agent-info {
+      // General Agent Structures
+      leaf-list supported-features {
+        type string;
+      }
+
+      // Common Agent Info
+      list supported-events {
+        key event;
+        leaf event {
+          type identityref {
+            base "fpcbase:event-type";
+          }
+        }
+        leaf event-id {
+          type fpcbase:event-type-id;
+        }
+      }
+
+      list supported-error-types {
+        key error-type;
+        leaf error-type {
+          type identityref {
+            base "fpcagent:error-type";
+          }
+        }
+        leaf error-type-id {
+          type fpcagent:error-type-id;
+        }
+      }
+    }
+
+
+    // Multi-DPN Agent Structures
+    grouping fpc-dpn-group {
+        leaf dpn-group-id {
+            type fpcbase:fpc-dpn-group-id;
+        }
+        leaf data-plane-role {
+            type identityref {
+                base "fpcbase:fpc-forwaridingplane-role";
+            }
+        }
+        leaf access-type {
+            type identityref {
+                base "fpcbase:fpc-access-type";
+            }
+        }
+        leaf mobility-profile {
+            type identityref {
+                base "fpcbase:fpc-mobility-profile-type";
+            }
+        }
+        list dpn-group-peers {
+            key "remote-dpn-group-id";
+            uses fpcbase:fpc-dpn-peer-group;
+        }
+    }
+
+
+    // RPC
+    // RPC Specific Structures
+    //Input Structures
+    typedef admin-status {
+        type enumeration {
+            enum enabled { value 0; }
+            enum disabled { value 1; }
+            enum virtual { value 2; }
+        }
+    }
+
+    typedef session-status {
+        type enumeration {
+            enum complete { value 0; }
+            enum incomplete { value 1; }
+            enum outdated { value 2; }
+        }
+    }
+
+    typedef op-delay {
+        type uint32;
+    }
+
+    typedef op-identifier {
+        type uint64;
+    }
+
+    typedef ref-scope {
+      description "Search scope for references in the operation.
+        op - All references are contained in the operation body (intra-op)
+        bundle - All references in exist in bundle (inter-operation/intra-bundle).
+          NOTE - If this value comes in CONFIG call it is equivalen to 'op'.
+        storage - One or more references exist outside of the operation and bundle.
+          A lookup to a cache / storage is required.
+        unknown - the location of the references are unknown.  This is treated as
+          a 'storage' type.";
+      type enumeration {
+        enum none { value 0; }
+        enum op { value 1; }
+        enum bundle { value 2; }
+        enum storage { value 3; }
+        enum unknown { value 4; }
+      }
+    }
+
+    grouping instructions {
+      container instructions {
+        if-feature instruction-bitset;
+        choice instr-type {
+          case pmip-instr {
+            uses fpc-pmip:pmip-commandset;
+          }
+          case instr-3gpp-mob {
+            uses threegpp:threegpp-commandset;
+          }
+        }
+      }
+    }
+
+    grouping op-header {
+      leaf client-id {
+        type fpcagent:client-identifier;
+      }
+      leaf delay {
+        type op-delay;
+      }
+      leaf session-state {
+        type session-status;
+      }
+      leaf admin-state {
+        type admin-status;
+      }
+      leaf op-type {
+        type enumeration {
+          enum create { value 0; }
+          enum update { value 1; }
+          enum query { value 2; }
+          enum delete { value 3; }
+        }
+      }
+      leaf op-ref-scope {
+          if-feature operation-ref-scope;
+          type fpcagent:ref-scope;
+      }
+      uses fpcagent:instructions;
+    }
+
+    grouping clone-ref {
+      leaf entity {
+        type fpcbase:fpc-identity;
+      }
+      leaf source {
+        type fpcbase:fpc-identity;
+      }
+    }
+
+    identity command-set {
+      description "protocol specific commands";
+    }
+
+    grouping context-operation {
+      uses fpcbase:fpc-context;
+      uses fpcagent:instructions;
+    }
+
+    grouping port-operation {
+      uses fpcbase:fpc-port;
+      uses fpcagent:instructions;
+    }
+
+    // Output Structure
+    grouping payload {
+      list ports {
+        uses fpcagent:port-operation;
+      }
+      list contexts {
+        uses fpcagent:context-operation;
+      }
+    }
+
+    grouping op-input {
+      uses fpcagent:op-header;
+      leaf op-id {
+        type op-identifier;
+      }
+      choice op_body {
+        case create_or_update {
+          list clones {
+            if-feature fpc-cloning;
+            key entity;
+            uses fpcagent:clone-ref;
+          }
+          uses fpcagent:payload;
+        }
+        case delete_or_query {
+          uses fpcbase:targets-value;
+        }
+      }
+    }
+
+    typedef result {
+      type enumeration {
+        enum ok { value 0; }
+        enum err { value 1; }
+        enum ok-notify-follows { value 2; }
+      }
+    }
+
+    identity error-type {
+      description "Base Error Type";
+    }
+    identity name-already-exists {
+      description "Notification that an entity of the same name already exists";
+    }
+
+    typedef error-type-id {
+      description "Integer form of the Error Type";
+      type uint32;
+    }
+
+    grouping op-status-value {
+      leaf op-status {
+        type enumeration {
+          enum ok { value 0; }
+          enum err { value 1; }
+        }
+      }
+    }
+
+    grouping result-body {
+      leaf op-id {
+        type op-identifier;
+      }
+      leaf result {
+        type result;
+      }
+      choice result-type {
+        case err {
+          leaf error-type-id {
+            type fpcagent:error-type-id;
+          }
+          leaf error-info {
+            type string {
+              length "1..1024";
+            }
+          }
+        }
+        case common-success {
+          uses fpcagent:payload;
+        }
+        case delete-success {
+          uses fpcbase:targets-value;
+        }
+        case empty-case {
+        }
+      }
+    }
+
+    grouping result-body-dpn {
+      leaf result {
+        type result;
+      }
+      choice result-type {
+        case err {
+          leaf error-type-id {
+            type fpcagent:error-type-id;
+          }
+          leaf error-info {
+            type string {
+              length "1..1024";
+            }
+          }
+        }
+        case common-delete-success {
+          uses fpcbase:fpc-dpn;
+        }
+        case empty-case {
+        }
+      }
+    }
+
+    typedef dpn-operation {
+        type enumeration {
+            enum add { value 0; }
+            enum remove { value 1; }
+        }
+    }
+
+    grouping dpn-input {
+      leaf abstract-dpn-id {
+        type fpcbase:fpc-dpn-id;
+      }
+      leaf input-dpn-id {
+        type fpcbase:fpc-dpn-id;
+      }
+      leaf operation {
+        type fpcagent:dpn-operation;
+      }
+    }
+
+    // Common RPCs
+    rpc configure-dpn {
+      input {
+        uses fpcagent:dpn-input;
+      }
+      output {
+        uses fpcagent:result-body-dpn;
+      }
+    }
+
+    rpc configure {
+      input {
+        uses fpcagent:op-input;
+      }
+      output {
+        uses fpcagent:result-body;
+      }
+    }
+
+    rpc configure-bundles {
+      if-feature fpcagent:fpc-bundles;
+      input {
+        leaf client-id {
+          type fpcagent:client-identifier;
+        }
+        leaf highest-op-ref-scope {
+            if-feature operation-ref-scope;
+            type fpcagent:ref-scope;
+        }
+        list bundles {
+          key op-id;
+          uses fpcagent:op-input;
+        }
+      }
+      output {
+        list bundles {
+          key op-id;
+          uses fpcagent:result-body;
+        }
+      }
+    }
+
+    // Notification Messages & Structures
+    typedef notification-id {
+      type uint32;
+    }
+
+    grouping notification-header {
+      leaf notification-id {
+          type fpcagent:notification-id;
+      }
+      leaf timestamp {
+          type uint64;
+      }
+    }
+    
+    grouping cause-values {
+      leaf cause-value {
+        type uint32;
+      }
+    }
+
+    notification config-result-notification {
+      uses fpcagent:notification-header;
+      choice value {
+        case config-result {
+          uses fpcagent:op-status-value;
+          uses fpcagent:cause-values;
+          uses fpcagent:result-body;
+        }
+        case config-bundle-result {
+          list bundles {
+            uses fpcagent:op-status-value;
+            uses fpcagent:cause-values;
+            uses fpcagent:result-body;
+          }
+        }
+      }
+    }
+
+    rpc event_register {
+        description "Used to register monitoring of parameters/events";
+        input {
+          uses fpcbase:monitor-config;
+          leaf client-id {
+            type fpcagent:client-identifier;
+          }
+        }
+        output {
+          leaf monitor-result {
+            type fpcagent:result;
+          }
+        }
+    }
+
+    rpc event_deregister {
+        description "Used to de-register monitoring of parameters/events";
+        input {
+          list monitors {
+            uses fpcbase:monitor-id;
+          }
+          leaf client-id {
+            type fpcagent:client-identifier;
+          }
+        }
+        output {
+          leaf monitor-result {
+            type fpcagent:result;
+          }
+        }
+    }
+
+    rpc probe {
+        description "Probe the status of a registered monitor";
+        input {
+          uses fpcbase:targets-value;
+          leaf client-id {
+            type fpcagent:client-identifier;
+          }
+        }
+        output {
+          leaf monitor-result {
+            type fpcagent:result;
+          }
+        }
+    }
+    
+   grouping dpn-status-value {
+      leaf dpn-status {
+        type enumeration {
+          enum available { value 0; }
+          enum unavailable { value 1; }
+        }
+      }
+    }
+
+    notification notify {
+        uses fpcagent:notification-header;
+        choice value {
+            case dpn-candidate-available {
+              if-feature fpcagent:fpc-auto-binding;
+              leaf candidate-node-id {
+                type inet:uri;
+              }
+              leaf-list access-types {
+                type identityref {
+                  base "fpcbase:fpc-access-type";
+                }
+              }
+              leaf-list mobility-profiles {
+                type identityref {
+                  base "fpcbase:fpc-mobility-profile-type";
+                }
+              }
+              leaf-list forwarding-plane-roles {
+                type identityref {
+                  base "fpcbase:fpc-forwaridingplane-role";
+                }
+              }
+            }
+            
+            case dpn-availability {
+              leaf availability-message-type {
+                type string;
+              }
+              uses fpcagent:dpn-status-value;
+              leaf load {
+              	description "A percentage value (between 0 and 100) of the system load.  This is a combined measurement.";
+              	type int8;
+              }
+              uses fpcbase:fpc-dpn;
+            }
+            
+            case monitor-notification {
+              choice monitor-notification-value {
+                case simple-monitor {
+                  uses fpcbase:report;
+                }
+                case bulk-monitors {
+                  list reports {
+                    uses fpcbase:report;
+                  }
+                }
+              }
+            }
+            // Added as part of the augment issue
+            // TODO - Remove once resolved
+            case downlink-data-notification {
+              leaf notification-message-type {
+                type string;
+              }
+              leaf notification-dpn-id {
+                type fpcbase:fpc-dpn-id;
+              }
+              leaf session-id {
+                type uint64;
+              }
+              leaf client-id {
+              	type fpcagent:client-identifier;
+              }
+              leaf op-id {
+              	type fpcagent:op-identifier;
+              }
+            }
+        }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
new file mode 100644
index 0000000..8785850
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
@@ -0,0 +1,706 @@
+module ietf-dmm-fpcbase {
+    namespace "urn:ietf:params:xml:ns:yang:fpcbase";
+    prefix fpcbase;
+
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+    import ietf-dmm-fpc-pmip { prefix fpc-pmip; revision-date 2016-01-19; }
+    import ietf-traffic-selector-types { prefix traffic-selectors; }
+    import ietf-dmm-fpc-policyext { prefix fpcpolicyext; }
+    import ietf-dmm-threegpp { prefix threegpp; }
+    import ietf-pmip-qos { prefix qos-pmip; }
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     Forwarding Policy Configuration Protocol.(FPCP)";
+
+    revision 2016-08-03 {
+        description "Changes based on -04 version of FPC draft.";
+        reference "draft-ietf-dmm-fpc-cpdp-04";
+    }
+
+    feature fpc-basic-agent {
+        description "This is an agent co-located with a DPN.  In this case
+        only DPN Peer Groups, the DPN Id and Control Protocols are exposed
+        along with the core structures.";
+    }
+    feature fpc-multi-dpn {
+        description "The agent supports multiple DPNs.";
+    }
+    
+    typedef fpc-identity {
+        type union {
+            type int64;
+            type string;
+        }
+    }
+
+    grouping target-value {
+      leaf target {
+          type fpc-identity;
+      }
+    }
+
+    grouping targets-value {
+      list targets {
+          key "target";
+          leaf target {
+            type fpc-identity;
+          }
+          leaf-list dpn-id {
+                type fpcbase:fpc-dpn-id;
+          }
+      }
+    }
+
+    // Descriptor Structure
+    typedef fpc-descriptor-id-type {
+        type fpcbase:fpc-identity;
+        description "Descriptor-ID";
+    }
+    identity fpc-descriptor-type {
+        description "A traffic descriptor";
+    }
+    grouping fpc-descriptor-id {
+      leaf descriptor-id {
+        type fpcbase:fpc-identity;
+      }
+    }
+
+    identity pmip-selector-descriptor {
+      base "fpcbase:fpc-descriptor-type";
+    }
+    identity prefix-descriptor {
+      base "fpcbase:fpc-descriptor-type";
+    }
+    identity threegpp-tft-decriptor {
+      base "fpcbase:fpc-descriptor-type";
+    }
+    identity domain-descriptor {
+      base "fpcbase:fpc-descriptor-type";
+    }
+
+    grouping fpc-descriptor {
+        uses fpcbase:fpc-descriptor-id;
+        leaf descriptor-type {
+          mandatory true;
+          type identityref {
+            base "fpc-descriptor-type";
+          }
+          description "Descriptor Type";
+        }
+        choice descriptor-value {
+          case all-traffic {
+            leaf all-traffic {
+              type empty;
+            }
+          }
+          case pmip-selector {
+            uses traffic-selectors:traffic-selector;
+          }
+          case prefix-descriptor {
+              uses fpcpolicyext:prefix-traffic-descriptor;
+          }
+          case threegpp-tft {
+              uses threegpp:tft;
+          }
+          case domain-descriptor {
+              uses fpcpolicyext:domain-descriptor-list;
+          }
+        }
+    }
+
+    // Action Structure
+    typedef fpc-action-id-type {
+        type fpcbase:fpc-identity;
+        description "Action-ID";
+    }
+    identity fpc-action-type {
+        description "Action Type";
+    }
+    grouping fpc-action-id {
+      leaf action-id {
+        type fpcbase:fpc-action-id-type;
+      }
+    }
+
+    identity simple-nat-action {
+      base "fpcbase:fpc-action-type";
+    }
+    identity simple-napt-action {
+      base "fpcbase:fpc-action-type";
+    }
+    identity copy-action {
+      base "fpcbase:fpc-action-type";
+    }
+    identity drop-action {
+      base "fpcbase:fpc-action-type";
+    }
+    identity rate-action {
+      base "fpcbase:fpc-action-type";
+    }
+
+    grouping fpc-action {
+        uses fpcbase:fpc-action-id;
+        leaf action-type {
+          mandatory true;
+          type identityref {
+            base "fpc-action-type";
+          }
+          description "Action Type";
+        }
+        choice action-value {
+          case drop {
+            leaf drop {
+              mandatory true;
+              type empty;
+            }
+            container rate-info{
+              leaf sponsor-identity {
+                type threegpp:sponsor-identity-type;
+              }
+              uses fpcpolicyext:rating-action;
+            }
+          }
+          case simple-nat {
+              uses fpcpolicyext:simple-nat;
+          }
+          case simple-napt {
+              uses fpcpolicyext:simple-napt;
+          }
+          case copy-forward {
+              uses fpcbase:copy-forward;
+          }
+          case rate {
+              leaf sponsor-identity {
+                type threegpp:sponsor-identity-type;
+              }
+              uses fpcpolicyext:rating-action;
+          }
+        }
+    }
+
+    // Rule Structure
+    grouping fpc-rule {
+        description
+          "FPC Rule.  When no actions are present the action is DROP.
+          When no Descriptors are empty the default is 'all traffic'.";
+        list descriptors {
+          key descriptor-id;
+          uses fpcbase:fpc-descriptor-id;
+          leaf direction {
+            type fpc-direction;
+          }
+        }
+        list actions {
+          key action-id;
+          leaf order {
+              type uint32;
+          }
+          uses fpcbase:fpc-action-id;
+        }
+    }
+
+    // Policy Structures
+    typedef fpc-policy-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-policy {
+        leaf policy-id {
+            type fpcbase:fpc-policy-id;
+        }
+        list rules {
+            key order;
+            leaf order {
+              type uint32;
+            }
+            uses fpcbase:fpc-rule;
+        }
+    }
+
+    // Policy Group
+    typedef fpc-policy-group-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-policy-group {
+      leaf policy-group-id {
+        type fpcbase:fpc-policy-group-id;
+      }
+      leaf-list policies {
+        type fpcbase:fpc-policy-id;
+      }
+    }
+
+    // Mobility Structures
+    // Port Group
+    typedef fpc-port-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-port {
+        leaf port-id {
+            type fpcbase:fpc-port-id;
+        }
+        leaf-list policy-groups {
+            type fpcbase:fpc-policy-group-id;
+        }
+    }
+
+    // Context Group
+    typedef fpc-context-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-context-profile {
+        description "A profile that applies to a specific direction";
+        leaf tunnel-local-address {
+            type inet:ip-address;
+            description "Uplink endpoint address of the DPN which agent exists.";
+        }
+        leaf tunnel-remote-address {
+            type inet:ip-address;
+            description "Uplink endpoint address of the DPN which agent exists.";
+        }
+        leaf lifetime {
+            type uint32;
+        }
+        leaf tunnel-mtu-size {
+            type uint32;
+            description "Tunnel MTU size";
+        }
+        container mobility-tunnel-parameters {
+            description "Specifies profile specific uplink tunnel parameters to the DPN which the agent exists. The profiles includes GTP/TEID for 3gpp profile, GRE/Key for ietf-pmip profile, or new profile if anyone will define it.";
+            uses fpcbase:mobility-info;
+        }
+        container nexthop {
+            uses fpcbase:fpc-nexthop;
+        }
+        container qos-profile-parameters {
+            uses fpcbase:fpc-qos-profile;
+        }
+        container dpn-parameters {
+        }
+        list vendor-parameters {
+            key "vendor-id vendor-type";
+            uses fpcbase:vendor-attributes;
+        }
+    }
+
+    typedef fpc-direction {
+       type enumeration {
+         enum uplink;
+         enum downlink;
+       }
+    }
+
+    grouping fpc-context {
+        leaf context-id {
+            type fpcbase:fpc-context-id;
+        }
+        leaf dormant {
+            type boolean;
+        }
+        leaf-list ports {
+            type fpcbase:fpc-port-id;
+        }
+        leaf dpn-group {
+          type fpcbase:fpc-dpn-group-id;
+        }
+        leaf-list delegating-ip-prefixes {
+            type inet:ip-prefix;
+        }
+        container ul {
+            if-feature fpcbase:fpc-basic-agent;
+            uses fpcbase:fpc-context-profile;
+        }
+        container dl {
+            if-feature fpcbase:fpc-basic-agent;
+            uses fpcbase:fpc-context-profile;
+        }
+        list dpns {
+            if-feature fpcbase:fpc-multi-dpn;
+            key "dpn-id direction";
+            leaf dpn-id {
+                type fpcbase:fpc-dpn-id;
+            }
+            leaf direction {
+                mandatory true;
+                type fpcbase:fpc-direction;
+            }
+            uses fpcbase:fpc-context-profile;
+        }
+        leaf parent-context {
+            type fpcbase:fpc-context-id;
+        }
+        uses threegpp:threegpp-properties;
+    }
+
+    // Mobility (Tunnel) Information
+    grouping mobility-info {
+        choice mobprofile-parameters {
+            case nothing {
+              leaf none {
+                type empty;
+              }
+            }
+            case pmip-tunnel {
+              uses fpc-pmip:pmip-mobility;
+              choice pmiptunnel-or-ref {
+                  case defined-selector {
+                    uses traffic-selectors:traffic-selector;
+                  }
+                  case predefined-selector {
+                     leaf selector-reference {
+                        type fpcbase:fpc-identity;
+                     }
+                  }
+              }
+            }
+            case threegpp-tunnel {
+              uses threegpp:threeGPP-tunnel;
+              choice tft-or-ref {
+                  case defined-tft {
+                    uses threegpp:tft;
+                  }
+                  case predefined-tft {
+                     leaf tft-reference {
+                        type fpcbase:fpc-identity;
+                     }
+                  }
+              }
+            }
+        }
+    }
+
+    // Next Hop Structures
+    typedef fpcp-service-path-id {
+        type uint32 {
+            range "0..33554431";
+        }
+        description "SERVICE_PATH_ID";
+    }
+
+    identity fpc-nexthop-type {
+        description "Next Hop Type";
+    }
+    identity fpc-nexthop-ip {
+        base "fpcbase:fpc-nexthop-type";
+    }
+    identity fpc-nexthop-servicepath {
+        base "fpcbase:fpc-nexthop-type";
+    }
+    grouping fpc-nexthop {
+        leaf nexthop-type {
+            type identityref {
+              base "fpcbase:fpc-nexthop-type";
+            }
+        }
+        choice nexthop-value {
+            case ip {
+                leaf ip {
+                  type inet:ip-address;
+                }
+            }
+            case servicepath {
+                leaf servicepath {
+                    type fpcbase:fpcp-service-path-id;
+                }
+            }
+        }
+    }
+
+    // QoS Information
+    identity fpc-qos-type {
+        description "Base identity from which specific uses of QoS types are derived.";
+    }
+    grouping fpc-qos-profile {
+        leaf qos-type {
+            type identityref {
+                base fpcbase:fpc-qos-type;
+            }
+            description "the profile type";
+        }
+        choice value {
+          case qos-pmip {
+              uses qos-pmip:qosattribute;
+          }
+          case threegpp-qos {
+            uses threegpp:threeGPP-QoS;
+          }
+        }
+    }
+
+    // Vendor Specific Attributes
+    identity vendor-specific-type {
+        description "Vendor Specific Attribute Type";
+    }
+    grouping vendor-attributes {
+        leaf vendor-id {
+            type fpcbase:fpc-identity;
+        }
+        leaf vendor-type {
+            type identityref {
+                base "fpcbase:vendor-specific-type";
+            }
+        }
+        choice value {
+            case empty-type {
+                leaf empty-type {
+                    type empty;
+                }
+            }
+        }
+    }
+
+    // Topology
+    typedef fpc-domain-id {
+        type fpcbase:fpc-identity;
+    }
+    grouping fpc-domain {
+      leaf domain-id {
+        type fpcbase:fpc-domain-id;
+      }
+      leaf domain-name {
+        type string;
+      }
+      leaf domain-type {
+        type string;
+      }
+    }
+
+    typedef fpc-dpn-id {
+        type fpcbase:fpc-identity;
+        description "DPN Identifier";
+    }
+    identity fpc-dpn-control-protocol {
+        description "DPN Control Protocol";
+    }
+    grouping fpc-dpn {
+        leaf dpn-id {
+          type fpcbase:fpc-dpn-id;
+        }
+        leaf dpn-name {
+          type string;
+        }
+        leaf-list dpn-groups {
+          type fpcbase:fpc-dpn-group-id;
+        }
+        leaf node-reference {
+          type instance-identifier;
+        }
+        leaf abstract {
+          type boolean;
+        }
+        leaf strategy {
+          type string;
+        }
+        leaf-list dpn-ids {
+          type fpcbase:fpc-dpn-id;
+        }
+        leaf node-id {
+          type string;
+        }
+        leaf network-id {
+          type string;
+        }
+    }
+
+    typedef fpc-dpn-group-id {
+        type fpcbase:fpc-identity;
+        description "DPN Group Identifier";
+    }
+    identity fpc-forwaridingplane-role {
+        description "Role of DPN Group in the Forwarding Plane";
+    }
+    identity fpc-access-type {
+        description "Access Type of the DPN Group";
+    }
+    identity fpc-mobility-profile-type {
+        description "Mobility Profile Type";
+    }
+
+    grouping fpc-dpn-peer-group {
+        leaf remote-dpn-group-id {
+            type fpcbase:fpc-dpn-group-id;
+        }
+        leaf remote-mobility-profile {
+            type identityref {
+                base "fpcbase:fpc-mobility-profile-type";
+            }
+        }
+        leaf remote-data-plane-role {
+            type identityref {
+                base "fpcbase:fpc-forwaridingplane-role";
+            }
+        }
+        leaf remote-endpoint-address {
+            type inet:ip-address;
+        }
+        leaf local-endpoint-address {
+            type inet:ip-address;
+        }
+        leaf tunnel-mtu-size {
+            type uint32;
+        }
+    }
+
+    // Events, Probes & Notifications
+    identity event-type {
+        description "Base Event Type";
+    }
+
+    typedef event-type-id {
+        type uint32;
+    }
+
+    grouping monitor-id {
+      leaf monitor-id {
+        type fpcbase:fpc-identity;
+      }
+    }
+
+    identity report-type {
+      description "Type of Report";
+    }
+    identity periodic-report {
+      base "fpcbase:report-type";
+    }
+    identity threshold-report {
+      base "fpcbase:report-type";
+    }
+    identity scheduled-report {
+      base "fpcbase:report-type";
+    }
+    identity events-report {
+      base "fpcbase:report-type";
+    }
+
+    grouping report-config {
+      choice event-config-value {
+        case periodic-config {
+            leaf period {
+              type uint32;
+            }
+        }
+        case threshold-config {
+            leaf lo-thresh {
+              type uint32;
+            }
+            leaf hi-thresh {
+              type uint32;
+            }
+        }
+        case scheduled-config {
+            leaf report-time {
+              type uint32;
+            }
+        }
+        case events-config-ident {
+            leaf-list event-identities {
+              type identityref {
+                base "fpcbase:event-type";
+              }
+            }
+        }
+        case events-config {
+            leaf-list event-ids {
+              type uint32;
+            }
+        }
+      }
+    }
+
+    grouping monitor-config {
+      uses fpcbase:monitor-id;
+      uses fpcbase:target-value;
+      uses fpcbase:report-config;
+    }
+
+    grouping report {
+      uses fpcbase:monitor-config;
+      choice report-value {
+        leaf trigger {
+          type fpcbase:event-type-id;
+        }
+        case simple-empty {
+          leaf nothing {
+            type empty;
+          }
+        }
+        case simple-val32 {
+          leaf val32 {
+            type uint32;
+          }
+        }
+        case any-data {
+          leaf data {
+            type string;
+          }
+        }
+      }
+    }
+
+    // PMIP Identities
+    identity ietf-pmip-access-type {
+      base "fpcbase:fpc-access-type";
+    }
+
+    identity fpcp-qos-index-pmip {
+        base "fpcbase:fpc-qos-type";
+    }
+    identity traffic-selector-mip6 {
+        base "fpcbase:fpc-descriptor-type";
+    }
+    identity ietf-pmip {
+        base "fpcbase:fpc-mobility-profile-type";
+    }
+
+    // Threegpp
+    identity threeGPP-qos-profile-parameters {
+        base "fpcbase:fpc-qos-type";
+    }
+
+    identity threeGPP-access-type {
+      base "fpcbase:fpc-access-type";
+    }
+
+    // Profile Type
+    identity threeGPP-mobility {
+         base "fpcbase:fpc-mobility-profile-type";
+    }
+
+    // Policy Extensions
+    identity service-function {
+        base "fpcbase:fpc-descriptor-type";
+        description "Base Identifier for Service Functions.";
+    }
+
+    identity napt-service {
+        base "service-function";
+    }
+
+    identity nat-service {
+        base "service-function";
+    }
+
+    identity copy-forward {
+      base "fpcbase:fpc-descriptor-type";
+      description "Copies a packet then forwards to a specific destination";
+    }
+    grouping copy-forward {
+      container destination {
+        choice value {
+          case port-ref {
+            leaf port-ref {
+              type fpcbase:fpc-port-id;
+            }
+          }
+          case context-ref {
+            leaf context-ref {
+              type fpcbase:fpc-context-id;
+            }
+          }
+        }
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang b/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang
new file mode 100644
index 0000000..1439224
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang
@@ -0,0 +1,330 @@
+module ietf-dmm-threegpp {
+    namespace "urn:ietf:params:xml:ns:yang:threegpp";
+    prefix threegpp;
+
+    import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+    import ietf-traffic-selector-types { prefix traffic-selectors; revision-date 2016-01-14; }
+    import ietf-pmip-qos { prefix pmipqos; revision-date 2016-02-10; }
+
+
+    organization "IETF DMM Working Group";
+    contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+    description
+    "This module contains YANG definition for
+     3GPP Related Mobility Structures";
+
+    revision 2016-08-03 {
+        description "Initial";
+        reference "draft-ietf-dmm-fpc-cpdp-04";
+    }
+
+    // Tunnel Types
+    identity threeGPP-tunnel-type {
+        description "Base Tunnel Type";
+    }
+
+    identity gtpv1 {
+        base "threegpp:threeGPP-tunnel-type";
+    }
+
+    identity gtpv2 {
+        base "threegpp:threeGPP-tunnel-type";
+    }
+
+    grouping teid-value {
+         leaf tunnel-identifier {
+            description "TEID";
+            type uint32;
+        }
+    }
+
+    grouping threeGPP-tunnel {
+        leaf tunnel-type {
+            type identityref  {
+              base "threegpp:threeGPP-tunnel-type";
+            }
+        }
+        uses threegpp:teid-value;
+    }
+
+    // QoS Profile
+    typedef fpc-qos-class-identifier {
+        type uint8 {
+            range "1..9";
+        }
+        description "QCI";
+    }
+
+    grouping threeGPP-QoS {
+        leaf qci {
+            type fpc-qos-class-identifier;
+        }
+        leaf gbr {
+            type uint32;
+        }
+        leaf mbr {
+            type uint32;
+        }
+        leaf apn-ambr {
+            type uint32;
+        }
+        leaf ue-ambr {
+            type uint32;
+        }
+        container arp {
+            uses pmipqos:Allocation-Retention-Priority-Value;
+        }
+    }
+
+    typedef ebi-type {
+      type uint8 {
+        range "0..15";
+      }
+    }
+
+   // From 3GPP TS 24.008 version 13.5.0 Release 13
+   typedef component-type-enum {
+        type enumeration {
+            enum ipv4RemoteAddress { value 16; }
+            enum ipv4LocalAddress  { value 17; }
+            enum ipv6RemoteAddress { value 32; }
+            enum ipv6RemoteAddressPrefix { value 33; }
+            enum ipv6LocalAddressPrefix { value 35; }
+            enum protocolNextHeader { value 48; }
+            enum localPort { value 64; }
+            enum localPortRange { value 65; }
+            enum reomotePort { value 80; }
+            enum remotePortRange { value 81; }
+            enum secParamIndex { value 96; }
+            enum tosTraffClass { value 112; }
+            enum flowLabel { value 128; }
+        }
+    }
+
+    typedef packet-filter-direction {
+        type enumeration {
+          enum preRel7Tft { value 0; }
+          enum uplink { value 1; }
+          enum downlink { value 2; }
+          enum bidirectional { value 3; }
+        }
+    }
+
+    typedef component-type-id {
+        type uint8 {
+          range "16 | 17 | 32 | 33 | 35 | 48 | 64 | 65 | 80 | 81 | 96 | 112 | 128";
+        }
+    }
+
+    typedef sponsor-identity-type {
+        type string;
+    }
+
+    grouping packet-filter {
+      leaf direction {
+          type threegpp:packet-filter-direction;
+      }
+      leaf identifier {
+          type uint8 {
+            range "1..15";
+          }
+      }
+      leaf evaluation-precedence {
+          type uint8;
+      }
+      list contents {
+        key component-type-identifier;
+        leaf component-type-identifier {
+            type threegpp:component-type-id;
+        }
+        choice value {
+          case ipv4-local {
+            leaf ipv4-local {
+              type inet:ipv4-address;
+            }
+            leaf ipv4-local-mask {
+              type inet:ipv4-address;
+            }
+          }
+          case ipv6-address-local {
+            leaf ipv6-address-local {
+              type inet:ipv6-prefix;
+            }
+            leaf ipv6-address-local-mask {
+              type inet:ipv6-prefix;
+            }
+          }
+          case ipv6-prefix-local {
+            leaf ipv6-prefix-local {
+              type inet:ipv6-prefix;
+            }
+          }
+
+          case ipv4-ipv6-remote {
+            leaf ipv4-ipv6-remote {
+              type inet:ip-address;
+            }
+            leaf ipv4-ipv6-remote-mask {
+              type inet:ip-address;
+            }
+          }
+
+          case ipv4-remote {
+            leaf ipv4-remote {
+              type inet:ipv4-address;
+            }
+            leaf ipv4-remote-mask {
+              type inet:ipv4-address;
+            }
+          }
+          case ipv6-address-remote {
+            leaf ipv6-address-remote {
+              type inet:ipv6-prefix;
+            }
+            leaf ipv6-address-remote-mask {
+              type inet:ipv6-prefix;
+            }
+          }
+          case ipv6-prefix-remote {
+            leaf ipv6-prefix-remote {
+              type inet:ipv6-prefix;
+            }
+          }
+
+          case protocol-next-header {
+            leaf next-header {
+              type uint8;
+            }
+          }
+
+          case local-port {
+            leaf local-port {
+              type inet:port-number;
+            }
+          }
+          case local-port-range {
+            leaf local-port-lo {
+              type inet:port-number;
+            }
+            leaf local-port-hi {
+              type inet:port-number;
+            }
+          }
+          case remote-port {
+            leaf remote-port {
+              type inet:port-number;
+            }
+          }
+          case remote-port-range {
+            leaf remote-port-lo {
+              type inet:port-number;
+            }
+            leaf remote-port-hi {
+              type inet:port-number;
+            }
+          }
+          case ipsec-index {
+            leaf ipsec-index {
+              type traffic-selectors:ipsec-spi;
+            }
+          }
+          case traffic-class {
+            leaf traffic-class {
+              type inet:dscp;
+            }
+          }
+          case traffic-class-range {
+              leaf traffic-class-lo {
+                type inet:dscp;
+              }
+              leaf traffic-class-hi {
+                type inet:dscp;
+              }
+          }
+          case flow-label-type {
+            leaf-list flow-label-type {
+              type inet:ipv6-flow-label;
+            }
+          }
+        }
+      }
+    }
+
+    grouping tft {
+      list packet-filters {
+          key identifier;
+          uses threegpp:packet-filter;
+      }
+    }
+
+    typedef imsi-type {
+        type uint64;
+    }
+
+    typedef threegpp-instr {
+      description "Instruction Set for 3GPP R11";
+      type bits {
+        bit assign-ip {
+          position 0;
+        }
+        bit assign-fteid-ip {
+          position 1;
+        }
+        bit assign-fteid-teid {
+          position 2;
+        }
+        bit session {
+          position 3;
+        }
+        bit uplink {
+          position 4;
+        }
+        bit downlink {
+          position 5;
+        }
+        bit assign-dpn {
+          position 6;
+        }
+        bit indirect-forward {
+          position 7;
+        }
+        bit create_new_tft {
+          position 8;
+        }
+        bit delete_existing_tft {
+          position 9;
+        }
+        bit add_filters_to_existing_tft {
+          position 10;
+        }
+        bit replace_filters_in_existing_tft {
+          position 11;
+        }
+        bit delete_filters_from_existing_tft {
+          position 12;
+        }
+        bit no_tft_op {
+          position 13;
+        }
+      }
+    }
+
+    grouping threegpp-properties {
+      leaf imsi {
+        type threegpp:imsi-type;
+      }
+      leaf ebi {
+        type threegpp:ebi-type;
+      }
+      leaf lbi {
+        type threegpp:ebi-type;
+      }
+    }
+
+    grouping threegpp-commandset {
+      leaf instr-3gpp-mob {
+        type threegpp:threegpp-instr;
+      }
+    }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-pmip-qos.yang b/models/fpcagent/src/main/yang/ietf-pmip-qos.yang
new file mode 100644
index 0000000..4a22355
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-pmip-qos.yang
@@ -0,0 +1,564 @@
+module ietf-pmip-qos {
+    yang-version 1;
+
+    namespace
+      "urn:ietf:params:xml:ns:yang:ietf-pmip-qos";
+
+    prefix "qos-pmip";
+
+    import ietf-inet-types {
+    	prefix inet;
+    	revision-date 2013-07-15;
+    }
+    import ietf-traffic-selector-types { prefix traffic-selectors; }
+
+    organization
+      "IETF DMM (Dynamic Mobility Management) Working Group";
+
+    contact
+      "WG Web:   <https://datatracker.ietf.org/wg/dmm/>
+     WG List:  <mailto:dmm@ietf.org>
+
+     WG Chair: Dapeng Liu
+               <mailto:maxpassion@gmail.com>
+
+     WG Chair: Jouni Korhonen
+               <mailto:jouni.nospam@gmail.com>
+
+     Editor:
+               <mailto:>";
+
+    description
+      "This module contains a collection of YANG definitions for
+     quality of service paramaters used in Proxy Mobile IPv6.
+
+     Copyright (c) 2015 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module was created as part of the IETF
+    	DMM FPC YANG modules; see the RFC itself for full legal notices.";
+
+    revision 2016-02-10 {
+        description "Initial revision";
+        reference
+         "RFC 7222: Quality-of-Service Option for Proxy Mobile IPv6";
+    }
+
+    // Type Definitions
+
+    // QoS Option Field Type Definitions
+	typedef sr-id {
+		type uint8;
+	    description
+	     "An 8-bit unsigned integer used
+	      for identifying the QoS Service Request.  Its uniqueness is within
+	      the scope of a mobility session.  The local mobility anchor always
+	      allocates the Service Request Identifier.  When a new QoS Service
+	      Request is initiated by a mobile access gateway, the Service
+	      Request Identifier in the initial request message is set to a
+	      value of (0), and the local mobility anchor allocates a Service
+	      Request Identifier and includes it in the response.  For any new
+	      QoS Service Requests initiated by a local mobility anchor, the
+	      Service Request Identifier is set to the allocated value.";
+	  }
+
+    typedef traffic-class {
+    	type inet:dscp;
+    	description
+    		"Traffic Class consists of a 6-bit DSCP field followed by a 2-bit
+    		reserved field.";
+	   reference
+		     "RFC 3289: Management Information Base for the Differentiated
+		                Services Architecture
+		      RFC 2474: Definition of the Differentiated Services Field
+		                (DS Field) in the IPv4 and IPv6 Headers
+		      RFC 2780: IANA Allocation Guidelines For Values In
+		                the Internet Protocol and Related Headers";
+    }
+
+    typedef operational-code {
+    	type enumeration {
+    		enum RESPONSE { value 0; }
+    		enum ALLOCATE { value 1; }
+    		enum DE-ALLOCATE { value 2; }
+    		enum MODIFY { value 3; }
+    		enum QUERY { value 4; }
+    		enum NEGOTIATE { value 5; }
+    	}
+    	description
+    		"1-octet Operational code indicates the type of QoS request.
+
+    	      RESPONSE:   (0)
+    	         Response to a QoS request
+
+    	      ALLOCATE:   (1)
+    	         Request to allocate QoS resources
+
+    	      DE-ALLOCATE:   (2)
+    	         Request to de-Allocate QoS resources
+
+    	      MODIFY:   (3)
+    	         Request to modify QoS parameters for a previously negotiated
+    	         QoS Service Request
+
+    	      QUERY:   (4)
+    	         Query to list the previously negotiated QoS Service Requests
+    	         that are still active
+
+    	      NEGOTIATE:   (5)
+                Response to a QoS Service Request with a counter QoS proposal
+
+              Reserved:   (6) to (255)
+                Currently not used.  Receiver MUST ignore the option received
+                with any value in this range.";
+    }
+
+    // QoS Attribute Types
+
+    //The enumeration value for mapping - don't confuse with the identities
+    typedef qos-attrubite-type-enum {
+    	type enumeration {
+    		enum Reserved { value 0; }
+    		enum Per-MN-Agg-Max-DL-Bit-Rate { value 1; }
+	        enum Per-MN-Agg-Max-UL-Bit-Rate { value 2; }
+	        enum Per-Session-Agg-Max-DL-Bit-Rate { value 3; }
+	        enum Per-Session-Agg-Max-UL-Bit-Rate { value 4; }
+          enum Allocation-Retention-Priority { value 5; }
+	      	enum Aggregate-Max-DL-Bit-Rate { value 6; }
+	        enum Aggregate-Max-UL-Bit-Rate { value 7; }
+	        enum Guaranteed-DL-Bit-Rate { value 8; }
+	        enum Guaranteed-UL-Bit-Rate { value 9; }
+	        enum QoS-Traffic-Selector { value 10; }
+	        enum QoS-Vendor-Specific-Attribute { value 11; }
+    	}
+ 		description
+		"8-bit unsigned integer indicating the type of the QoS
+	      attribute.  This specification reserves the following values.
+	      (0) -  Reserved
+	         This value is reserved and cannot be used
+
+	      (1) -  Per-MN-Agg-Max-DL-Bit-Rate
+	         Per-Mobile-Node Aggregate Maximum Downlink Bit Rate.
+
+	      (2) -  Per-MN-Agg-Max-UL-Bit-Rate
+	         Per-Mobile-Node Aggregate Maximum Uplink Bit Rate.
+
+	      (3) -  Per-Session-Agg-Max-DL-Bit-Rate
+	         Per-Mobility-Session Aggregate Maximum Downlink Bit Rate.
+
+		    (4) -  Per-Session-Agg-Max-UL-Bit-Rate
+              Per-Mobility-Session Aggregate Maximum Uplink Bit Rate.
+
+ 	      (5) -  Allocation-Retention-Priority
+ 	         Allocation and Retention Priority.
+
+ 	      (6) -  Aggregate-Max-DL-Bit-Rate
+ 	         Aggregate Maximum Downlink Bit Rate.
+
+ 	      (7) -  Aggregate-Max-UL-Bit-Rate
+ 	         Aggregate Maximum Uplink Bit Rate.
+
+ 	      (8) -  Guaranteed-DL-Bit-Rate
+ 	         Guaranteed Downlink Bit Rate.
+
+ 	      (9) -  Guaranteed-UL-Bit-Rate
+ 	         Guaranteed Uplink Bit Rate.
+
+ 	      (10) -  QoS-Traffic-Selector
+ 	         QoS Traffic Selector.
+
+ 	      (11) -  QoS-Vendor-Specific-Attribute
+ 	        QoS Vendor-Specific Attribute.
+
+ 	      (12) to (254) -  Reserved
+ 	         These values are reserved for future allocation.
+
+ 	      (255) -  Reserved
+ 	         This value is reserved and cannot be used.";
+    }
+
+    // Attribute Type as Identities
+    // Added for convenience of inclusion and extension in other YANG modules.
+    identity qos-attribute-type {
+    	description
+    		"Base type for Quality of Service Attributes";
+    }
+
+    identity Per-MN-Agg-Max-DL-Bit-Rate-type {
+    	base qos-attribute-type;
+    	description
+    		"Per-Mobile-Node Aggregate Maximum Downlink Bit Rate.";
+	}
+
+ 	identity Per-MN-Agg-Max-UL-Bit-Rate-type {
+    	base qos-attribute-type;
+    	description
+    		"Per-Mobile-Node Aggregate Maximum Uplink Bit Rate";
+ 	}
+
+ 	identity Per-Session-Agg-Max-DL-Bit-Rate-type {
+    	base qos-attribute-type;
+    	description
+    		"Per-Mobility-Session Aggregate Maximum Downlink Bit Rate.";
+ 	}
+
+ 	identity Per-Session-Agg-Max-UL-Bit-Rate-type {
+    	base qos-attribute-type;
+    	description
+    		"Per-Mobility-Session Aggregate Maximum Uplink Bit Rate.";
+ 	}
+
+ 	identity Allocation-Retention-Priority-type {
+    	base qos-attribute-type;
+    	description
+    		"Allocation and Retention Priority.";
+ 	}
+
+ 	identity Aggregate-Max-DL-Bit-Rate-type {
+	  	base qos-attribute-type;
+	  	description "Aggregate Maximum Downlink Bit Rate.";
+ 	}
+
+  identity Aggregate-Max-UL-Bit-Rate-type {
+      base qos-attribute-type;
+      description "Aggregate Maximum Uplink Bit Rate.";
+  }
+
+  identity Guaranteed-DL-Bit-Rate-type {
+      base qos-attribute-type;
+      description "Guaranteed Downlink Bit Rate.";
+  }
+
+  identity Guaranteed-UL-Bit-Rate-type {
+      base qos-attribute-type;
+      description "Guaranteed Uplink Bit Rate.";
+  }
+
+  identity QoS-Traffic-Selector-type {
+      base qos-attribute-type;
+      description "QoS Traffic Selector.";
+  }
+
+  identity QoS-Vendor-Specific-Attribute-type {
+      base qos-attribute-type;
+      description "QoS Vendor-Specific Attribute.";
+  }
+
+  //value definitions
+  typedef Per-MN-Agg-Max-DL-Bit-Rate-Value {
+      type uint32;
+      description
+          "This is a 32-bit unsigned integer that
+          indicates the aggregate maximum downlink bit rate that is
+          requested/allocated for all the mobile node's IP flows.  The
+          measurement units for Per-MN-Agg-Max-DL-Bit-Rate are bits per
+          second.";
+	}
+
+ 	typedef Per-MN-Agg-Max-UL-Bit-Rate-Value {
+    	type uint32;
+    	description
+    		"This is a 32-bit unsigned integer that
+    	      indicates the aggregate maximum uplink bit rate that is requested/
+    	      allocated for the mobile node's IP flows.  The measurement units
+    	      for Per-MN-Agg-Max-UL-Bit-Rate are bits per second.";
+ 	}
+
+ 	// Generic Structure for the uplink and downlink
+ 	grouping Per-Session-Agg-Max-Bit-Rate-Value {
+ 		leaf max-rate {
+ 			type uint32;
+ 			mandatory true;
+ 			description
+ 				"This is a 32-bit unsigned integer
+ 			      that indicates the aggregate maximum bit rate that is requested/allocated
+ 				  for all the IP flows associated with that mobility session.  The measurement
+ 				  units for Per-Session-Agg-Max-UL/DL-Bit-Rate are bits per second.";
+ 		}
+ 		leaf service-flag {
+			type boolean;
+			mandatory true;
+			description
+				"This flag is used for extending the scope of the
+			      target flows for Per-Session-Agg-Max-UL/DL-Bit-Rate from(UL)/to(DL) the mobile
+			      node's other mobility sessions sharing the same Service
+			      Identifier. 3GPP Access Point Name (APN) is an example of a
+			      Service Identifier, and that identifier is carried using the
+			      Service Selection mobility option [RFC5149].
+
+			      *  When the (S) flag is set to a value of (1), then the Per-
+			         Session-Agg-Max-Bit-Rate is measured as an aggregate across
+			         all the mobile node's other mobility sessions sharing the same
+			         Service Identifier associated with this mobility session.
+
+			      *  When the (S) flag is set to a value of (0), then the target
+			         flows are limited to the current mobility session.
+
+			      *  The (S) flag MUST NOT be set to a value of (1) when there is no
+			         Service Identifier associated with the mobility session.";
+			reference
+				"RFC 5149 - Service Selection mobility option";
+ 		}
+ 		leaf exclude-flag {
+ 			type boolean;
+ 			mandatory true;
+ 			description
+ 				"This flag is used to request that the uplink/downlink
+ 			      flows for which the network is providing Guaranteed-Bit-Rate
+ 			      service be excluded from the target IP flows for which Per-
+ 			      Session-Agg-Max-UL/DL-Bit-Rate is measured.
+
+ 			      *  When the (E) flag is set to a value of (1), then the request is
+ 			         to exclude the IP flows for which Guaranteed-UL/DL-Bit-Rate
+ 			         is negotiated from the flows for which Per-Session-Agg-Max-UL/DL-Bit-Rate
+ 				     is measured.
+
+ 			      *  When the (E) flag is set to a value of (0), then the request is
+ 			         not to exclude any IP flows from the target IP flows for which
+ 			         Per-Session-Agg-Max-UL/DL-Bit-Rate is measured.
+
+ 			      *  When the (S) flag and (E) flag are both set to a value of (1),
+ 			         then the request is to exclude all the IP flows sharing the
+ 			         Service Identifier associated with this mobility session from
+ 			         the target flows for which Per-Session-Agg-Max-UL/DL-Bit-Rate is
+ 			         measured.";
+ 		}
+ 	}
+
+ 	grouping Allocation-Retention-Priority-Value {
+ 		leaf prioirty-level {
+ 			type uint8 {
+ 				range "0..15";
+ 			}
+ 			mandatory true;
+ 			description
+ 				"This is a 4-bit unsigned integer value.  It
+ 			      is used to decide whether a mobility session establishment or
+ 			      modification request can be accepted; this is typically used for
+ 			      admission control of Guaranteed Bit Rate traffic in case of
+ 			      resource limitations.  The priority level can also be used to
+
+ 			      decide which existing mobility session to preempt during resource
+ 			      limitations.  The priority level defines the relative timeliness
+ 			      of a resource request.
+
+ 			      Values 1 to 15 are defined, with value 1 as the highest level of
+ 			      priority.
+
+ 			      Values 1 to 8 should only be assigned for services that are
+ 			      authorized to receive prioritized treatment within an operator
+ 			      domain.  Values 9 to 15 may be assigned to resources that are
+ 			      authorized by the home network and thus applicable when a mobile
+ 			      node is roaming.";
+ 		}
+ 		leaf premption-capability {
+ 			type enumeration {
+				enum enabled { value 0; }
+				enum disabled { value 1; }
+				enum reserved1 { value 2; }
+				enum reserved2 { value 3; }
+ 			}
+ 			mandatory true;
+ 			description
+ 				"This is a 2-bit unsigned integer
+ 			      value.  It defines whether a service data flow can get resources
+ 			      that were already assigned to another service data flow with a
+ 			      lower priority level.  The following values are defined:
+
+ 			         Enabled (0): This value indicates that the service data flow is
+ 			         allowed to get resources that were already assigned to another
+ 			         IP data flow with a lower priority level.
+
+ 			         Disabled (1): This value indicates that the service data flow
+ 			         is not allowed to get resources that were already assigned to
+ 			         another IP data flow with a lower priority level.  The values
+ 			         (2) and (3) are reserved.";
+ 		}
+ 		leaf premption-vulnerability {
+ 			type enumeration {
+				enum enabled { value 0; }
+				enum disabled { value 1; }
+				enum reserved1 { value 2; }
+				enum reserved2 { value 3; }
+ 			}
+ 			mandatory true;
+ 			description
+				"This is a 2-bit unsigned integer
+ 			      value.  It defines whether a service data flow can lose the
+ 			      resources assigned to it in order to admit a service data flow
+ 			      with a higher priority level.  The following values are defined:
+
+ 			         Enabled (0): This value indicates that the resources assigned
+ 			         to the IP data flow can be preempted and allocated to a service
+ 			         data flow with a higher priority level.
+
+ 			         Disabled (1): This value indicates that the resources assigned
+ 			         to the IP data flow shall not be preempted and allocated to a
+ 			         service data flow with a higher priority level.  The values (2)
+ 			         and (3) are reserved.";
+ 		}
+ 	}
+
+ 	typedef Aggregate-Max-DL-Bit-Rate-Value {
+	  	type uint32;
+	  	description
+	  		"This is a 32-bit unsigned integer that
+	        indicates the aggregate maximum downlink bit rate that is
+	        requested/allocated for downlink IP flows.  The measurement units
+	        for Aggregate-Max-DL-Bit-Rate are bits per second.";
+ 	}
+
+  	typedef Aggregate-Max-UL-Bit-Rate-Value {
+    	type uint32;
+    	description
+    		"This is a 32-bit unsigned integer that
+    	      indicates the aggregate maximum downlink bit rate that is
+    	      requested/allocated for downlink IP flows.  The measurement units
+    	      for Aggregate-Max-DL-Bit-Rate are bits per second.";
+  	}
+
+  	typedef Guaranteed-DL-Bit-Rate-Value {
+	  	type uint32;
+	  	description
+	  		"This is a 32-bit unsigned integer that
+	        indicates the guaranteed bandwidth in bits per second for downlink
+	        IP flows.  The measurement units for Guaranteed-DL-Bit-Rate are
+	        bits per second.";
+  	}
+
+  	typedef Guaranteed-UL-Bit-Rate-Value {
+    	type uint32;
+    	description
+    		"This is a 32-bit unsigned integer that
+    	      indicates the guaranteed bandwidth in bits per second for uplink
+    	      IP flows.  The measurement units for Guaranteed-UL-Bit-Rate are
+    	      bits per second.";
+  	}
+
+  	grouping QoS-Vendor-Specific-Attribute-Value-Base {
+  		leaf vendorid {
+  			type uint32;
+  			mandatory true;
+  			description
+  				"The Vendor ID is the SMI (Structure of Management
+  		      Information) Network Management Private Enterprise Code of the
+  		      IANA-maintained 'Private Enterprise Numbers' registry [SMI].";
+  			reference
+  				"'PRIVATE ENTERPRISE NUMBERS', SMI Network Management
+                Private Enterprise Codes, April 2014,
+                <http://www.iana.org/assignments/enterprise-numbers>";
+  		}
+  		leaf subtype {
+  			type uint8;
+  			mandatory true;
+  			description
+  				"An 8-bit field indicating the type of vendor-specific
+  		      information carried in the option.  The namespace for this sub-
+  		      type is managed by the vendor identified by the Vendor ID field.";
+  		}
+    	description
+    		"QoS Vendor-Specific Attribute.";
+  	}
+
+    //NOTE - We do NOT add the Status Codes or other changes in PMIP in this module
+
+  	//Primary Structures (groupings)
+    grouping qosattribute {
+        leaf attributetype {
+            type identityref {
+                base qos-attribute-type;
+            }
+            mandatory true;
+            description "the attribute type";
+        }
+
+  		  //All of the sub-types by constraint
+        choice attribute-choice {
+            case per-mn-agg-max-dl-case {
+                when "../attributetype = 'Per-MN-Agg-Max-DL-Bit-Rate-type'";
+                leaf per-mn-agg-max-dl {
+                    type qos-pmip:Per-MN-Agg-Max-DL-Bit-Rate-Value;
+                }
+            }
+            case per-mn-agg-max-ul-case {
+                when "../attributetype = 'Per-MN-Agg-Max-UL-Bit-Rate-type'";
+                leaf per-mn-agg-max-ul {
+                    type qos-pmip:Per-MN-Agg-Max-UL-Bit-Rate-Value;
+                }
+            }
+            case per-session-agg-max-dl-case {
+                when "../attributetype = 'Per-Session-Agg-Max-DL-Bit-Rate-type'";
+                container per-session-agg-max-dl {
+                    uses qos-pmip:Per-Session-Agg-Max-Bit-Rate-Value;
+                }
+            }
+            case per-session-agg-max-ul-case {
+                when "../attributetype = 'Per-Session-Agg-Max-UL-Bit-Rate-type'";
+                container per-session-agg-max-ul {
+                    uses qos-pmip:Per-Session-Agg-Max-Bit-Rate-Value;
+                }
+            }
+            case allocation-retention-priority-case {
+                when "../attributetype = 'Allocation-Retention-Priority-type'";
+                uses qos-pmip:Allocation-Retention-Priority-Value;
+            }
+            case agg-max-dl-case {
+                when "../attributetype = 'Aggregate-Max-DL-Bit-Rate-type'";
+                leaf agg-max-dl {
+                    type qos-pmip:Aggregate-Max-DL-Bit-Rate-Value;
+                }
+            }
+            case agg-max-ul-case {
+                when "../attributetype = 'Aggregate-Max-UL-Bit-Rate-type'";
+                leaf agg-max-ul {
+                    type qos-pmip:Aggregate-Max-UL-Bit-Rate-Value;
+                }
+            }
+            case gbr-dl-case {
+                when "../attributetype = 'Guaranteed-DL-Bit-Rate-type'";
+                leaf gbr-dl {
+                    type qos-pmip:Guaranteed-DL-Bit-Rate-Value;
+                }
+            }
+            case gbr-ul-case {
+                when "../attributetype = 'Guaranteed-UL-Bit-Rate-type'";
+                leaf gbr-ul {
+                    type qos-pmip:Guaranteed-UL-Bit-Rate-Value;
+                }
+            }
+            case traffic-selector-case {
+                when "../attributetype = 'QoS-Traffic-Selector-type'";
+                container traffic-selector {
+                    uses traffic-selectors:traffic-selector;
+                }
+            }
+        }
+    }
+
+  	grouping qosoption {
+        leaf srid {
+            type sr-id;
+            mandatory true;
+        }
+        leaf trafficclass {
+            type traffic-class;
+            mandatory true;
+        }
+        leaf operationcode {
+            type operational-code;
+            mandatory true;
+        }
+        list attributes {
+            unique "attributetype";
+            uses qosattribute;
+            min-elements 1;
+        }
+  	}
+}
diff --git a/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang b/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang
new file mode 100644
index 0000000..029f3ec
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang
@@ -0,0 +1,508 @@
+module ietf-traffic-selector-types {
+    yang-version 1;
+
+    namespace
+      "urn:ietf:params:xml:ns:yang:ietf-traffic-selector-types";
+
+    prefix "ietf-traffic-selectors";
+
+    import ietf-inet-types {
+    	prefix inet;
+    	revision-date 2013-07-15;
+    }
+
+    organization
+      "IETF DMM (Dynamic Mobility Management) Working Group";
+
+    contact
+      "WG Web:   <https://datatracker.ietf.org/wg/dmm/>
+     WG List:  <mailto:dmm@ietf.org>
+
+     WG Chair: Dapeng Liu
+               <mailto:maxpassion@gmail.com>
+
+     WG Chair: Jouni Korhonen
+               <mailto:jouni.nospam@gmail.com>
+
+     Editor:
+               <mailto:>";
+
+    description
+      "This module contains a collection of YANG definitions for
+     traffic selectors for flow bindings.
+
+     Copyright (c) 2015 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module was created as part of the IETF
+    	DMM FPC YANG modules; see the RFC itself for full legal notices.";
+
+    revision 2016-01-14 {
+    	description "Updated for IETF-PACKET-FIELDS module alignment";
+    	reference
+    		"draft-ietf-netmod-acl-model-06";
+    }
+
+    revision 2016-01-12 {
+        description "Initial revision";
+        reference
+        	"RFC 6088: Traffic Selectors for Flow Bindings";
+    }
+
+    // Identities
+  	identity traffic-selector-format {
+  		description "The base type for Traffic-Selector Formats";
+  	}
+
+  	identity ipv4-binary-selector-format {
+  		base traffic-selector-format;
+  		description
+  			"IPv4 Binary Traffic Selector Format";
+  	}
+
+  	identity ipv6-binary-selector-format {
+  		base traffic-selector-format;
+  		description
+  			"IPv6 Binary Traffic Selector Format";
+  	}
+
+  	// Type definitions and groupings
+  	typedef ipsec-spi {
+  		type uint32;
+  		description "This type defines the first 32-bit IPsec Security Parameter
+				Index (SPI) value on data packets sent from a corresponding
+				node to the mobile node as seen by the home agent. This field
+				is defined in [RFC4303].";
+  			reference
+  				"RFC 4303: IP Encapsulating Security Payload (ESP)";
+  	}
+
+  	grouping traffic-selector-base {
+  		description "A grouping of the commen leaves between the v4 and v6 Traffic Selectors";
+  	    container ipsec-spi-range {
+  	      presence "Enables setting ipsec spi range";
+  	      description
+  	        "Inclusive range representing IPSec Security Parameter Indices to be used.
+  	        When only start-spi is present, it represents a single spi.";
+	  		leaf start-spi {
+	  			type ipsec-spi;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first 32-bit IPsec SPI value, from the
+	  		      range of SPI values to be matched, on data packets sent from a
+	  		      corresponding node to the mobile node as seen by the home agent.
+	  		      This field is defined in [RFC4303].";
+	  		}
+	  		leaf end-spi {
+	  			type ipsec-spi;
+	  	        must ". >= ../start-spi" {
+	  	          error-message
+	  	            "The end-spi must be greater than or equal to start-spi";
+	  	        }
+	  			description
+	  				"If more than one contiguous SPI value needs to be matched, then
+	  		      this field can be used to indicate the end value of a range
+	  		      starting from the value of the Start SPI field.  This field
+	  		      MUST NOT be included unless the Start SPI field is included
+	  			  and has a value less than or equal to this field.
+
+	  		      When this field is included, the receiver will match all of the
+	  		      SPI values between fields start-spi and end-spi,
+	  			  inclusive of start-spi and end-spi.";
+	  		}
+  	    }
+  	    container source-port-range {
+  	      presence "Enables setting source port range";
+  	      description
+  	        "Inclusive range representing source ports to be used.
+  	        When only start-port is present, it represents a single port.";
+	  		leaf start-port {
+	  			type inet:port-number;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first 16-bit source port number, from
+	  		      the range of port numbers to be matched, on data packets sent from
+	  		      a corresponding node to the mobile node as seen by the home agent.
+	  		      This is from the range of port numbers defined by IANA
+	  		      (http://www.iana.org).";
+	  		}
+	  		leaf end-port {
+	  			type inet:port-number;
+	  			must ". >= ../start-port" {
+	  	          error-message
+	  	          "The end-port must be greater than or equal to start-port";
+	  	        }
+	  			description
+	  				"If more than one contiguous source port number needs to be
+	  		      matched, then this field can be used to indicate the end value of
+	  		      a range starting from the value of the Start Port field.
+	  		      This field MUST NOT be included unless the Start Port field
+	  		      is included and has a value less than or equal to this field.
+
+	  			  When this field is included, the receiver will match
+	  		      all of the port numbers between fields start-port and
+	  			  end-port, inclusive of start-port and end-port.";
+	  		}
+  	   }
+  	  container destination-port-range {
+  	      presence "Enables setting destination port range";
+  	      description
+  	        "Inclusive range representing destination ports to be used. When
+  	  		 only start-port is present, it represents a single port.";
+	  		leaf start-port {
+	  			type inet:port-number;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first 16-bit destination port number,
+	  		      from the range of port numbers to be matched, on data packets sent
+	  		      from a corresponding node to the mobile node as seen by the home
+	  		      agent.";
+	  		}
+	  		leaf end-port {
+	  			type inet:port-number;
+	  	        must ". >= ../start-port" {
+	  	          error-message
+	  	            "The end-port must be greater than or equal to start-port";
+	  	        }
+	  			description
+	  				"If more than one contiguous destination port number needs to be
+	  		      matched, then this field can be used to indicate the end value of
+	  		      a range starting from the value of the Start Destination Port
+	  		      field.  This field MUST NOT be included unless the Start
+	  		      Port field is included and has a value less than or equal to this
+	  			  field.
+
+	  			  When this field is included, the receiver will match all of the
+	  			  port numbers between fields start-port and end-port, inclusive of
+	  			  start-port and end-port.";
+	  		}
+  	  }
+  	}
+
+  	grouping ipv4-binary-traffic-selector {
+	  container source-address-range-v4 {
+  	      presence "Enables setting source IPv4 address range";
+  	      description
+  	        "Inclusive range representing IPv4 addresses to be used. When
+  	  		 only start-address is present, it represents a single address.";
+	  		leaf start-address {
+	  			type inet:ipv4-address;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first source address, from the range of
+	  		      32-bit IPv4 addresses to be matched, on data packets sent from a
+	  		      corresponding node to the mobile node as seen by the home agent.
+	  		      In other words, this is one of the addresses of the correspondent
+	  		      node.";
+	  		}
+	  		leaf end-address {
+	  			type inet:ipv4-address;
+	  			description
+	  				"If more than one contiguous source address needs to be matched,
+	  		      then this field can be used to indicate the end value of a range
+	  		      starting from the value of the Start Address field.  This
+	  		      field MUST NOT be included unless the Start Address field
+	  		      is included.  When this field is included, the receiver will match
+	  		      all of the addresses between fields start-address and
+	  			  end-address, inclusive of start-address and end-address.";
+	  		}
+	  }
+	  container destination-address-range-v4 {
+  	      presence "Enables setting destination IPv4 address range";
+  	      description
+  	        "Inclusive range representing IPv4 addresses to be used. When
+  	  		 only start-address is present, it represents a single address.";
+	  		leaf start-address {
+	  			type inet:ipv4-address;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first destination address, from the
+	  		      range of 32-bit IPv4 addresses to be matched, on data packets sent
+	  		      from a corresponding node to the mobile node as seen by the home
+	  		      agent.  In other words, this is one of the registered home
+	  		      addresses of the mobile node.";
+	  		}
+	  		leaf end-address {
+	  			type inet:ipv4-address;
+	  			description
+	  				"If more than one contiguous destination address needs to be
+	  		      matched, then this field can be used to indicate the end value of
+	  		      a range starting from the value of the Start Destination Address
+	  		      field.  This field MUST NOT be included unless the Start
+	  		      Address field is included.  When this field is included, the receiver
+	  			  will match all of the addresses between fields start-address and
+	  			  end-address, inclusive of start-address and end-address.";
+	  		}
+	  }
+	  container ds-range {
+  	      presence "Enables setting dscp range";
+  	      description
+  	        "Inclusive range representing DiffServ Codepoints to be used. When
+  	  		 only start-ds is present, it represents a single Codepoint.";
+  	      leaf start-ds {
+  			type inet:dscp;
+  			mandatory true;
+  			description
+  				"This field identifies the first differential services value, from
+  		      the range of differential services values to be matched, on data
+  		      packets sent from a corresponding node to the mobile node as seen
+  		      by the home agent.  Note that this field is called a 'Type of
+  		      Service field' in [RFC0791].  [RFC3260] then clarified that the
+  		      field has been redefined as a 6-bit DS field with 2 bits reserved,
+  		      later claimed by Explicit Congestion Notification (ECN) [RFC3168].
+  		      For the purpose of this specification, the Start DS field is 8
+  		      bits long, where the 6 most significant bits indicate the DS field
+  		      to be matched and the 2 least significant bits' values MUST be
+  		      ignored in any comparison.";
+	  		}
+	  		leaf end-ds {
+	  			type inet:dscp;
+	  	        must ". >= ../start-ds" {
+	  	          error-message
+	  	            "The end-ds must be greater than or equal to start-ds";
+	  	        }
+	  			description
+	  				"If more than one contiguous DS value needs to be matched, then
+	  		      this field can be used to indicate the end value of a range
+	  		      starting from the value of the Start DS field.  This field MUST
+	  		      NOT be included unless the Start DS field is included.  When this
+	  		      field is included, it MUST be coded the same way as defined for
+	  		      start-ds.  When this field is included, the receiver will match all of
+	  		      the values between fields start-ds and end-ds, inclusive of start-ds
+	  			  and end-ds.";
+	  		}
+	  }
+	  container protocol-range {
+		presence "Enables setting protocol range";
+		description
+			"Inclusive range representing IP protocol(s) to be used. When
+		   	 only start-protocol is present, it represents a single protocol.";
+  		leaf start-protocol {
+  			type uint8;
+  			mandatory true;
+  			description
+  				"This field identifies the first 8-bit protocol value, from the
+  		      range of protocol values to be matched, on data packets sent from
+  		      a corresponding node to the mobile node as seen by the home agent.";
+  		}
+  		leaf end-protocol {
+  			type uint8;
+  	        must ". >= ../start-protocol" {
+  	          error-message
+  	            "The end-protocol must be greater than or equal to start-protocol";
+  	        }
+  			description
+  				"If more than one contiguous protocol value needs to be matched,
+  		      then this field can be used to indicate the end value of a range
+  		      starting from the value of the Start Protocol field.  This field
+  		      MUST NOT be included unless the Start Protocol field is included.
+  		      When this field is included, the receiver will match all of the
+  		      values between fields start-protocol and end-protocol, inclusive
+  			  of start-protocol and end-protocol.";
+  		}
+	  }
+  	}
+
+	grouping ipv6-binary-traffic-selector {
+	 container source-address-range-v6 {
+  	      presence "Enables setting source IPv6 address range";
+  	      description
+  	        "Inclusive range representing IPv6 addresses to be used. When
+  	  		 only start-address is present, it represents a single address.";
+	  		leaf start-address {
+	  			type inet:ipv6-address;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first source address, from the range of
+	  		      128-bit IPv6 addresses to be matched, on data packets sent from a
+	  		      corresponding node to the mobile node as seen by the home agent.
+	  		      In other words, this is one of the addresses of the correspondent
+	  		      node.";
+	  		}
+	  		leaf end-address {
+	  			type inet:ipv6-address;
+	  			description
+	  				"If more than one contiguous source address needs to be matched,
+	  		      then this field can be used to indicate the end value of a range
+	  		      starting from the value of the Start Address field.  This
+	  		      field MUST NOT be included unless the Start Address field is included.
+	  			  When this field is included, the receiver will match all of the addresses
+	  			  between fields start-address and end-address, inclusive of start-address
+	  			  and end-address .";
+	  		}
+	  }
+  	  container destination-address-range-v6 {
+  	      presence "Enables setting destination IPv6 address range";
+  	      description
+  	        "Inclusive range representing IPv6 addresses to be used. When
+  	  		 only start-address is present, it represents a single address.";
+	  		leaf start-address {
+	  			type inet:ipv6-address;
+	  			mandatory true;
+	  			description
+	  				"This field identifies the first destination address, from the
+	  		      range of 128-bit IPv6 addresses to be matched, on data packets
+	  		      sent from a corresponding node to the mobile node as seen by the
+	  		      home agent.  In other words, this is one of the registered home
+	  		      addresses of the mobile node.";
+	  		}
+	  		leaf end-address {
+	  			type inet:ipv6-address;
+	  			description
+	  				"If more than one contiguous destination address needs to be
+	  		      matched, then this field can be used to indicate the end value of
+	  		      a range starting from the value of the Start Address field. This
+	  			  field MUST NOT be included unless the Start Address field is included.
+	  			  When this field is included, the receiver will match all of the
+	  			  addresses between fields start-address and end-address, inclusive of
+	  			  start-address and end-address.";
+	  		}
+  	  }
+  	 container flow-label-range {
+      presence "Enables setting Flow Label range";
+      description
+        "Inclusive range representing IPv4 addresses to be used. When
+  		 only start-flow-label is present, it represents a single flow label.";
+  		leaf start-flow-label {
+  			type inet:ipv6-flow-label;
+  			description
+  				"This field identifies the first flow label value, from the range
+  		      of flow label values to be matched, on data packets sent from a
+  		      corresponding node to the mobile node as seen by the home agent.
+  		      According to [RFC2460], the flow label is 24 bits long.  For the
+  		      purpose of this specification, the sender of this option MUST
+  		      prefix the flow label value with 8 bits of '0' before inserting it
+  		      in the start-flow-label field.  The receiver SHOULD ignore the
+  		      first 8 bits of this field before using it in comparisons with
+  		      flow labels in packets.";
+  		}
+  		leaf end-flow-label {
+  			type inet:ipv6-flow-label;
+  	        must ". >= ../start-flow-label" {
+  	          error-message
+  	            "The end-flow-lable must be greater than or equal to start-flow-label";
+  	        }
+  			description
+  				"If more than one contiguous flow label value needs to be matched,
+  		      then this field can be used to indicate the end value of a range
+  		      starting from the value of the Start Flow Label field.  This field
+  		      MUST NOT be included unless the Start Flow Label field is
+  		      included.  When this field is included, the receiver will match
+  		      all of the flow label values between fields start-flow-label
+  			  and end-flow-label, inclusive of start-flow-label and end-flow-label.
+  			  When this field is included, it MUST be coded the same way as defined
+  			  for end-flow-label.";
+  		}
+  	 }
+  	 container traffic-class-range {
+      presence "Enables setting the traffic class range";
+      description
+        "Inclusive range representing IPv4 addresses to be used. When
+  		 only start-traffic-class is present, it represents a single traffic class.";
+  		leaf start-traffic-class {
+  			type inet:dscp;
+  			description
+  				"This field identifies the first traffic class value, from the
+  		      range of traffic class values to be matched, on data packets sent
+  		      from a corresponding node to the mobile node as seen by the home
+  		      agent.  This field is equivalent to the Start DS field in the IPv4
+  		      traffic selector in Figure 1.  As per RFC 3260, the field is
+  		      defined as a 6-bit DS field with 2 bits reserved, later claimed by
+  		      Explicit Congestion Notification (ECN) RFC 3168.  For the purpose
+  		      of this specification, the start-traffic-class field is 8 bits long, where
+  		      the 6 most significant bits indicate the DS field to be matched
+  		      and the 2 least significant bits' values MUST be ignored in any
+  		      comparison.";
+  			reference
+  				"RFC 3260: New Terminology and Clarifications for Diffserv
+  				 RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP";
+  		}
+  		leaf end-traffic-class {
+  			type inet:dscp;
+  	        must ". >= ../start-traffic-class" {
+  	          error-message
+  	            "The end-traffic-class must be greater than or equal to start-traffic-class";
+  	        }
+  			description
+  				"If more than one contiguous TC value needs to be matched, then
+  		      this field can be used to indicate the end value of a range
+  		      starting from the value of the Start TC field.  This field MUST
+  		      NOT be included unless the Start TC field is included.  When this
+  		      field is included, it MUST be coded the same way as defined for
+  			  start-traffic-class.  When this field is included, the receiver
+  			  will match all of the values between fields start-traffic-class
+  			  and end-traffic-class, inclusive of start-traffic-class and
+  		      end-traffic-class.";
+  		}
+  	 }
+  	 container next-header-range {
+      presence "Enables setting Next Header range";
+      description
+        "Inclusive range representing Next Headers to be used. When
+  		 only start-next-header is present, it represents a single Next Header.";
+  		leaf start-next-header {
+  			type uint8;
+  			description
+  				"This field identifies the first 8-bit next header value, from the
+  		      range of next header values to be matched, on data packets sent
+  		      from a corresponding node to the mobile node as seen by the home
+  		      agent.";
+  		}
+  		leaf end-next-header {
+  			type uint8;
+  	        must ". >= ../start-next-header" {
+  	          error-message
+  	            "The end-next-header must be greater than or equal to start-next-header";
+  	        }
+  			description
+  				"If more than one contiguous next header value needs to be matched,
+  		      then this field can be used to indicate the end value of a range
+  		      starting from the value of the Start NH field.  This field MUST
+  		      NOT be included unless the Start next header field is included.
+  		      When this field is included, the receiver will match all of the
+  		      values between fields start-next-header and end-next-header,
+  			  inclusive of start-next-header and end-next-header.";
+  		}
+  	 }
+	}
+
+	grouping traffic-selector {
+		leaf ts-format {
+ 			type identityref {
+  				base traffic-selector-format;
+  			}
+  			description "Traffic Selector Format";
+  		}
+		uses traffic-selector-base {
+			when "boolean(../ts-format/text() = 'ipv6-binary-selector-format') | boolean(../ts-format/text() = 'ipv4-binary-selector-format')";
+		}
+		uses ipv4-binary-traffic-selector {
+			when "boolean(../ts-format/text() = 'ipv4-binary-selector-format')";
+		}
+		uses ipv6-binary-traffic-selector {
+			when "boolean(../ts-format/text() = 'ipv6-binary-selector-format')";
+		}
+		description
+			"The traffic selector includes the parameters used to match
+			   packets for a specific flow binding.";
+		reference
+			"RFC 6089: Flow Bindings in Mobile IPv6 and Network Mobility (NEMO) Basic Support";
+	}
+
+	grouping ts-list {
+		list selectors {
+			key index;
+			leaf index {
+				type uint64;
+			}
+			uses traffic-selector;
+		}
+	}
+}