added p4 communicator
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
index d84b35f..7300e03 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
@@ -26,11 +26,10 @@
 import org.onosproject.config.DynamicConfigService;
 import org.onosproject.config.DynamicConfigStore;
 import org.onosproject.config.Filter;
-import org.onosproject.fpcagent.util.CacheManager;
-import org.onosproject.fpcagent.util.DpnCommunicationService;
-import org.onosproject.fpcagent.util.DpnNgicCommunicator;
-import org.onosproject.fpcagent.util.FpcUtil;
+import org.onosproject.fpcagent.util.*;
 import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.DefaultConnectionInfo;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.P4DpnControlProtocol;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.ZmqDpnControlProtocol;
 import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.connectioninfo.DefaultConnections;
 import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.deregisterclient.DefaultDeregisterClientOutput;
 import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.registerclient.DefaultRegisterClientInput;
@@ -59,10 +58,10 @@
 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.fpcmobility.ContextsKeys;
 import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.fpcmobility.DefaultContexts;
 import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.fpctopology.DefaultDpns;
 import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcContextId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnControlProtocol;
 import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnId;
 import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
 import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Dpns;
@@ -101,8 +100,6 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     private RpcRegistry registry;
 
-    private DpnCommunicationService dpnCommunicationService;
-
     private ConcurrentMap<ClientIdentifier, DefaultRegisterClientInput> clientInfo = Maps.newConcurrentMap();
 
     @Activate
@@ -111,8 +108,6 @@
         FpcUtil.modelConverter = modelConverter;
         getResourceId();
 
-        dpnCommunicationService = new DpnNgicCommunicator();
-
         // Create the Default Tenant and added to the Tenants structure.
         final DefaultTenants tenants = new DefaultTenants();
         final DefaultTenant tenant = new DefaultTenant();
@@ -216,6 +211,8 @@
         Collection<Callable<Object>> tasks = new ArrayList<>();
 
         DefaultCommonSuccess defaultCommonSuccess = new DefaultCommonSuccess();
+        CacheManager cacheManager = CacheManager.getInstance(clientInfo.tenantId());
+
         for (Contexts context : create.contexts()) {
             // add context to response.
             defaultCommonSuccess.addToContexts(context);
@@ -227,21 +224,30 @@
             }
 
             for (Dpns dpn : context.dpns()) {
-                CacheManager cacheManager = CacheManager.getInstance(clientInfo.tenantId());
+                Optional<DefaultDpns> optionalDpn = cacheManager.dpnsCache.get(dpn.dpnId());
                 // check if dpns exists and if there is a DPN registered for the wanted identifier.
-                if (!cacheManager.dpnsCache.get(dpn.dpnId()).isPresent()) {
+                if (!optionalDpn.isPresent()) {
                     // throw exception if DPN ID is not registered.
                     throw new RuntimeException("DPN ID is not registered to the topology.");
                 }
 
+                final DpnCommunicationService dpnCommunicationService;
+                Class<? extends FpcDpnControlProtocol> controlProtocol = optionalDpn.get().controlProtocol();
+                if (controlProtocol.isAssignableFrom(ZmqDpnControlProtocol.class)) {
+                    dpnCommunicationService = new DpnNgicCommunicator();
+                } else if (controlProtocol.isAssignableFrom(P4DpnControlProtocol.class)) {
+                    dpnCommunicationService = new DpnP4Communicator();
+                } else {
+                    throw new RuntimeException("Control Protocol is not supported.");
+                }
+
                 // handle only 3GPP instructions.
                 if (!(context.instructions().instrType() instanceof Instr3GppMob)) {
                     throw new RuntimeException("No 3GPP instructions where given.");
                 }
 
                 // from DPN ID find the Network and Node Identifiers
-                Optional<String> key = cacheManager.dpnsCache.get(dpn.dpnId())
-                        .map(node -> node.nodeId() + "/" + node.networkId());
+                Optional<String> key = optionalDpn.map(node -> node.nodeId() + "/" + node.networkId());
                 if (!key.isPresent()) {
                     throw new RuntimeException("DPN does not have node and network ID defined.");
                 }
@@ -357,8 +363,8 @@
     ) throws Exception {
         DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
         Collection<Callable<Object>> tasks = new ArrayList<>();
-
         DefaultCommonSuccess defaultCommonSuccess = new DefaultCommonSuccess();
+        CacheManager cacheManager = CacheManager.getInstance(clientInfo.tenantId());
         for (Contexts context : update.contexts()) {
             // add updated context to response.
             defaultCommonSuccess.addToContexts(context);
@@ -370,7 +376,6 @@
             }
 
             for (Dpns dpn : context.dpns()) {
-                CacheManager cacheManager = CacheManager.getInstance(clientInfo.tenantId());
                 // check if dpns exists and if there is a DPN registered for the wanted identifier.
                 if (!cacheManager.dpnsCache.get(dpn.dpnId()).isPresent()) {
                     // throw exception if DPN ID is not registered.
@@ -414,46 +419,46 @@
                 DefaultContexts convertContext = convertContext(context);
                 if (commands.contains("downlink")) {
                     if (context.dl().lifetime() >= 0L) {
-                        tasks.add(Executors.callable(() -> {
-                            dpnCommunicationService.modify_bearer(
-                                    topic_id,
-                                    s1u_sgw_ipv4,
-                                    s1u_enb_gtpu_teid,
-                                    s1u_enodeb_ipv4,
-                                    contextId,
-                                    cId,
-                                    opId
-                            );
-
-                            ModelObjectId modelObjectId = defaultTenantBuilder()
-                                    .addChild(DefaultFpcMobility.class)
-                                    .build();
-                            updateNode(convertContext, modelObjectId);
-                            cacheManager.contextsCache.put(convertContext.contextId(), Optional.of(convertContext));
-                        }));
+//                        tasks.add(Executors.callable(() -> {
+//                            dpnCommunicationService.modify_bearer(
+//                                    topic_id,
+//                                    s1u_sgw_ipv4,
+//                                    s1u_enb_gtpu_teid,
+//                                    s1u_enodeb_ipv4,
+//                                    contextId,
+//                                    cId,
+//                                    opId
+//                            );
+//
+//                            ModelObjectId modelObjectId = defaultTenantBuilder()
+//                                    .addChild(DefaultFpcMobility.class)
+//                                    .build();
+//                            updateNode(convertContext, modelObjectId);
+//                            cacheManager.contextsCache.put(convertContext.contextId(), Optional.of(convertContext));
+//                        }));
                     } else {
                         // TODO delete bearer
                     }
                 }
                 if (commands.contains("uplink")) {
                     if (context.ul().lifetime() >= 0L) {
-                        tasks.add(Executors.callable(() -> {
-                            dpnCommunicationService.modify_bearer(
-                                    topic_id,
-                                    s1u_sgw_ipv4,
-                                    s1u_enb_gtpu_teid,
-                                    s1u_enodeb_ipv4,
-                                    contextId,
-                                    cId,
-                                    opId
-                            );
-
-                            ModelObjectId modelObjectId = defaultTenantBuilder()
-                                    .addChild(DefaultFpcMobility.class)
-                                    .build();
-                            updateNode(convertContext, modelObjectId);
-                            cacheManager.contextsCache.put(convertContext.contextId(), Optional.of(convertContext));
-                        }));
+//                        tasks.add(Executors.callable(() -> {
+//                            dpnCommunicationService.modify_bearer(
+//                                    topic_id,
+//                                    s1u_sgw_ipv4,
+//                                    s1u_enb_gtpu_teid,
+//                                    s1u_enodeb_ipv4,
+//                                    contextId,
+//                                    cId,
+//                                    opId
+//                            );
+//
+//                            ModelObjectId modelObjectId = defaultTenantBuilder()
+//                                    .addChild(DefaultFpcMobility.class)
+//                                    .build();
+//                            updateNode(convertContext, modelObjectId);
+//                            cacheManager.contextsCache.put(convertContext.contextId(), Optional.of(convertContext));
+//                        }));
                     } else {
                         // TODO delete bearer
                     }
@@ -487,7 +492,7 @@
     ) throws Exception {
         DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
         Collection<Callable<Object>> tasks = new ArrayList<>();
-
+        CacheManager cacheManager = CacheManager.getInstance(clientInfo.tenantId());
         DefaultDeleteSuccess defaultDeleteSuccess = new DefaultDeleteSuccess();
         for (Targets target : delete.targets()) {
             defaultDeleteSuccess.addToTargets(target);
@@ -505,7 +510,6 @@
 
             DefaultContexts context = defaultContexts.get();
             for (Dpns dpn : context.dpns()) {
-                CacheManager cacheManager = CacheManager.getInstance(clientInfo.tenantId());
                 // check if dpns exists and if there is a DPN registered for the wanted identifier.
                 if (!cacheManager.dpnsCache.get(dpn.dpnId()).isPresent()) {
                     // throw exception if DPN ID is not registered.
@@ -537,25 +541,25 @@
                 if (targetStr.endsWith("ul") || targetStr.endsWith("dl")) {
                     // TODO delete bearer
                 } else {
-                    tasks.add(Executors.callable(() -> {
-                        dpnCommunicationService.delete_session(
-                                topic_id,
-                                context.contextId().fpcIdentity().union().int64(),
-                                client_id,
-                                op_id
-                        );
-
-                        ContextsKeys contextsKeys = new ContextsKeys();
-                        contextsKeys.contextId(context.contextId());
-
-                        ResourceId resourceVal = getResourceVal(defaultTenantBuilder()
-                                .addChild(DefaultFpcMobility.class)
-                                .addChild(DefaultContexts.class, contextsKeys)
-                                .build());
-
-                        dynamicConfigService.deleteNode(resourceVal);
-                        cacheManager.contextsCache.put(context.contextId(), Optional.empty());
-                    }));
+//                    tasks.add(Executors.callable(() -> {
+//                        dpnCommunicationService.delete_session(
+//                                topic_id,
+//                                context.contextId().fpcIdentity().union().int64(),
+//                                client_id,
+//                                op_id
+//                        );
+//
+//                        ContextsKeys contextsKeys = new ContextsKeys();
+//                        contextsKeys.contextId(context.contextId());
+//
+//                        ResourceId resourceVal = getResourceVal(defaultTenantBuilder()
+//                                .addChild(DefaultFpcMobility.class)
+//                                .addChild(DefaultContexts.class, contextsKeys)
+//                                .build());
+//
+//                        dynamicConfigService.deleteNode(resourceVal);
+//                        cacheManager.contextsCache.put(context.contextId(), Optional.empty());
+//                    }));
                 }
             }
         }
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/CacheManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/CacheManager.java
index c7946cc..ebc3644 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/CacheManager.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/CacheManager.java
@@ -105,7 +105,8 @@
     }
 
     public static CacheManager getInstance(FpcIdentity identity) {
-        return cacheInfo.putIfAbsent(identity, new CacheManager(identity));
+        cacheInfo.putIfAbsent(identity, new CacheManager(identity));
+        return cacheInfo.get(identity);
     }
 
     public static void addManager(TenantManager manager) {
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/DpnNgicCommunicator.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/DpnNgicCommunicator.java
index 82618f4..f444e11 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/DpnNgicCommunicator.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/DpnNgicCommunicator.java
@@ -20,6 +20,7 @@
 import org.onlab.packet.Ip4Prefix;
 import org.onosproject.fpcagent.workers.ZMQSBPublisherManager;
 import org.onosproject.fpcagent.workers.ZMQSBSubscriberManager;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.ZmqDpnControlProtocol;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -31,7 +32,7 @@
 /**
  * DPDK DPN API over ZeroMQ for NGIC.
  */
-public class DpnNgicCommunicator implements DpnCommunicationService {
+public class DpnNgicCommunicator extends ZmqDpnControlProtocol implements DpnCommunicationService {
     protected static final Logger log = LoggerFactory.getLogger(DpnNgicCommunicator.class);
 
     @Override
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/DpnP4Communicator.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/DpnP4Communicator.java
new file mode 100644
index 0000000..6fb7eb9
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/util/DpnP4Communicator.java
@@ -0,0 +1,44 @@
+/*
+ * 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.util;
+
+import org.onlab.packet.Ip4Address;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.fpc.P4DpnControlProtocol;
+
+import java.math.BigInteger;
+
+public class DpnP4Communicator extends P4DpnControlProtocol implements DpnCommunicationService {
+    @Override
+    public void create_session(Short topic_id, BigInteger imsi, Short default_ebi, Ip4Address ue_ipv4, Long s1u_sgw_teid, Ip4Address s1u_sgw_ipv4, Long session_id, Long client_id, BigInteger op_id) {
+
+    }
+
+    @Override
+    public void modify_bearer(Short topic_id, Ip4Address s1u_sgw_ipv4, Long s1u_enodeb_teid, Ip4Address s1u_enodeb_ipv4, Long session_id, Long client_id, BigInteger op_id) {
+
+    }
+
+    @Override
+    public void delete_session(Short topic_id, Long session_id, Long client_id, BigInteger op_id) {
+
+    }
+
+    @Override
+    public void send_ADC_rules(Short topic, String domain_name, String ip, Short drop, Long rating_group, Long service_ID, String sponsor_ID) {
+
+    }
+}
diff --git a/models/fpcagent/src/main/yang/fpc.yang b/models/fpcagent/src/main/yang/fpc.yang
index c3c67b3..9337f50 100644
--- a/models/fpcagent/src/main/yang/fpc.yang
+++ b/models/fpcagent/src/main/yang/fpc.yang
@@ -28,6 +28,10 @@
       base "fpcbase:fpc-dpn-control-protocol";
     }
 
+    identity p4-dpn-control-protocol {
+      base "fpcbase:fpc-dpn-control-protocol";
+    }
+
     typedef membership-match-type {
       type enumeration {
         enum eq { value 0; }
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
index 8785850..ecade43 100644
--- a/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
@@ -472,9 +472,11 @@
         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;
@@ -503,6 +505,11 @@
         leaf network-id {
           type string;
         }
+        leaf control-protocol {
+          type identityref {
+            base "fpcbase:fpc-dpn-control-protocol";
+          }
+        }
     }
 
     typedef fpc-dpn-group-id {
diff --git a/scripts/addDPN.sh b/scripts/addDPN.sh
index f108595..18e5e42 100755
--- a/scripts/addDPN.sh
+++ b/scripts/addDPN.sh
@@ -11,7 +11,8 @@
                     "foo"
                 ],
                 "node-id": "node'$1'",
-                "network-id": "network'$1'"
+                "network-id": "network'$1'",
+                "control-protocol": "zmq-dpn-control-protocol"
             }
         ]
     }' 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology'
@@ -28,7 +29,8 @@
                     "foo"
                 ],
                 "node-id": "node'$1'",
-                "network-id": "network'$1'"
+                "network-id": "network'$1'",
+                "control-protocol": "zmq-dpn-control-protocol"
             }
         ]
     }' 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant='$2'/fpc-topology'