Creating a p4runtime default driver to avoid code duplication between bmv2 and barefoot drivers

Change-Id: Id7f16a284c65278ec1a9ec682da01ddf020343c8
diff --git a/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java b/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
index c05e169..9e7e9f8 100644
--- a/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
+++ b/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
@@ -77,11 +77,12 @@
     private static final String INGRESS_PORT = "ingress_port";
     private static final String ETHER_TYPE = "etherType";
 
+
     private final URL p4InfoUrl = this.getClass().getResource("/bmv2/default.p4info");
     private final URL jsonUrl = this.getClass().getResource("/bmv2/default.json");
 
     private final PiPipeconf bmv2DefaultPipeconf = DefaultPiPipeconf.builder()
-            .withId(new PiPipeconfId("mock-bmv2"))
+            .withId(new PiPipeconfId("mock-p4runtime"))
             .withPipelineModel(Bmv2PipelineModelParser.parse(jsonUrl))
             .addBehaviour(PiPipelineInterpreter.class, Bmv2DefaultInterpreter.class)
             .addExtension(P4_INFO_TEXT, p4InfoUrl)
diff --git a/drivers/bmv2/BUCK b/drivers/bmv2/BUCK
index a8dfd58..30ee2ab 100644
--- a/drivers/bmv2/BUCK
+++ b/drivers/bmv2/BUCK
@@ -31,5 +31,6 @@
         'org.onosproject.generaldeviceprovider',
         'org.onosproject.protocols.p4runtime',
         'org.onosproject.p4runtime',
+        'org.onosproject.drivers.p4runtime'
     ],
 )
diff --git a/drivers/bmv2/src/main/resources/bmv2-drivers.xml b/drivers/bmv2/src/main/resources/bmv2-drivers.xml
index af73d95..97972b3 100644
--- a/drivers/bmv2/src/main/resources/bmv2-drivers.xml
+++ b/drivers/bmv2/src/main/resources/bmv2-drivers.xml
@@ -15,13 +15,7 @@
   ~ limitations under the License.
   -->
 <drivers>
-    <driver name="bmv2" manufacturer="p4.org" hwVersion="master" swVersion="master">
-        <behaviour api="org.onosproject.net.device.DeviceHandshaker"
-                   impl="org.onosproject.drivers.bmv2.Bmv2Handshaker"/>
-        <behaviour api="org.onosproject.net.packet.PacketProgrammable"
-                   impl="org.onosproject.drivers.bmv2.Bmv2PacketProgrammable"/>
-        <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
-                   impl="org.onosproject.drivers.bmv2.Bmv2FlowRuleProgrammable"/>
+    <driver name="bmv2" manufacturer="p4.org" hwVersion="master" swVersion="master" extends="p4runtime">
         <behaviour api="org.onosproject.net.pi.model.PiPipelineProgrammable"
                    impl="org.onosproject.drivers.bmv2.Bmv2PipelineProgrammable"/>
     </driver>
diff --git a/drivers/p4runtime/BUCK b/drivers/p4runtime/BUCK
new file mode 100644
index 0000000..2cbe48d
--- /dev/null
+++ b/drivers/p4runtime/BUCK
@@ -0,0 +1,30 @@
+GRPC_VER = '1.3.0'
+
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//protocols/p4runtime/api:onos-protocols-p4runtime-api',
+    '//incubator/grpc-dependencies:grpc-core-repkg-' + GRPC_VER,
+    '//lib:grpc-netty-' + GRPC_VER,
+]
+
+BUNDLES = [
+    ':onos-drivers-p4runtime',
+]
+
+osgi_jar(
+    deps = COMPILE_DEPS,
+)
+
+onos_app (
+    app_name = 'org.onosproject.drivers.p4runtime',
+    title = 'P4Runtime Default Device Drivers',
+    category = 'Drivers',
+    url = 'http://onosproject.org',
+    description = 'ONOS P4Runtime device drivers application.',
+    included_bundles = BUNDLES,
+    required_apps = [
+        'org.onosproject.generaldeviceprovider',
+        'org.onosproject.protocols.p4runtime',
+        'org.onosproject.p4runtime',
+    ],
+)
diff --git a/drivers/p4runtime/features.xml b/drivers/p4runtime/features.xml
new file mode 100644
index 0000000..448f07a
--- /dev/null
+++ b/drivers/p4runtime/features.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+    <feature name="${project.artifactId}" version="${project.version}"
+             description="${project.description}">
+        <feature>onos-api</feature>
+        <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
+
+    </feature>
+</features>
diff --git a/drivers/p4runtime/pom.xml b/drivers/p4runtime/pom.xml
new file mode 100644
index 0000000..108f9ee
--- /dev/null
+++ b/drivers/p4runtime/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2017-present Open Networking Foundation
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>onos-drivers-general</artifactId>
+        <groupId>org.onosproject</groupId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>onos-drivers-p4runtime</artifactId>
+    <packaging>bundle</packaging>
+    
+    <description>P4Runtime device drivers</description>
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-grpc-protocol-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-netty</artifactId>
+            <version>1.3.0</version>
+        </dependency>
+
+        <!-- protocols/p4runtime/api missing -->
+
+    </dependencies>
+
+    <properties>
+        <onos.app.name>org.onosproject.drivers.p4runtime</onos.app.name>
+        <onos.app.origin>ON.Lab</onos.app.origin>
+        <onos.app.title>P4Runtime Device Drivers</onos.app.title>
+        <onos.app.category>Drivers</onos.app.category>
+        <onos.app.url>http://onosproject.org</onos.app.url>
+        <onos.app.requires>
+            org.onosproject.generaldeviceprovider
+        </onos.app.requires>
+    </properties>
+
+</project>
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriversLoader.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriversLoader.java
new file mode 100644
index 0000000..c8717ac
--- /dev/null
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriversLoader.java
@@ -0,0 +1,36 @@
+/*
+ * 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.drivers.p4runtime;
+
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+
+/**
+ * Loader for P4Runtime device drivers.
+ */
+@Component(immediate = true)
+public class P4RuntimeDriversLoader extends AbstractDriverLoader {
+
+    public P4RuntimeDriversLoader() {
+        super("/p4runtime-drivers.xml");
+    }
+
+    @Override
+    public void activate() {
+        super.activate();
+    }
+}
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
similarity index 86%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleProgrammable.java
rename to drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
index cd2bf7e..bdd53ed 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2;
+package org.onosproject.drivers.p4runtime;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
@@ -38,6 +38,8 @@
 import org.onosproject.p4runtime.api.P4RuntimeClient;
 import org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType;
 import org.onosproject.p4runtime.api.P4RuntimeController;
+import org.onosproject.p4runtime.api.P4RuntimeFlowRuleWrapper;
+import org.onosproject.p4runtime.api.P4RuntimeTableEntryReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,8 +52,8 @@
 import java.util.concurrent.locks.ReentrantLock;
 
 import static com.google.common.collect.Lists.newArrayList;
-import static org.onosproject.drivers.bmv2.Bmv2FlowRuleProgrammable.Operation.APPLY;
-import static org.onosproject.drivers.bmv2.Bmv2FlowRuleProgrammable.Operation.REMOVE;
+import static org.onosproject.drivers.p4runtime.P4RuntimeFlowRuleProgrammable.Operation.APPLY;
+import static org.onosproject.drivers.p4runtime.P4RuntimeFlowRuleProgrammable.Operation.REMOVE;
 import static org.onosproject.net.flow.FlowEntry.FlowEntryState.ADDED;
 import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.DELETE;
 import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.INSERT;
@@ -59,16 +61,16 @@
 /**
  * Implementation of the flow rule programmable behaviour for BMv2.
  */
-public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
+public class P4RuntimeFlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     // Needed to synchronize operations over the same table entry.
-    private static final ConcurrentMap<Bmv2TableEntryReference, Lock> ENTRY_LOCKS = Maps.newConcurrentMap();
+    private static final ConcurrentMap<P4RuntimeTableEntryReference, Lock> ENTRY_LOCKS = Maps.newConcurrentMap();
 
     // TODO: replace with distributed store.
     // Can reuse old BMv2TableEntryService from ONOS 1.6
-    private static final ConcurrentMap<Bmv2TableEntryReference, Bmv2FlowRuleWrapper> ENTRY_STORE =
+    private static final ConcurrentMap<P4RuntimeTableEntryReference, P4RuntimeFlowRuleWrapper> ENTRY_STORE =
             Maps.newConcurrentMap();
 
     private DeviceId deviceId;
@@ -142,10 +144,11 @@
 
             for (PiTableEntry installedEntry : installedEntries) {
 
-                Bmv2TableEntryReference entryRef = new Bmv2TableEntryReference(deviceId, piTableId,
-                                                                               installedEntry.matchKey());
+                P4RuntimeTableEntryReference entryRef = new P4RuntimeTableEntryReference(deviceId, piTableId,
+                        installedEntry.matchKey());
 
-                Bmv2FlowRuleWrapper frWrapper = ENTRY_STORE.get(entryRef);
+                P4RuntimeFlowRuleWrapper frWrapper = ENTRY_STORE.get(entryRef);
+
 
                 if (frWrapper == null) {
                     // Inconsistent entry
@@ -158,14 +161,14 @@
                 long packets = 0L;
 
                 FlowEntry entry = new DefaultFlowEntry(frWrapper.rule(), ADDED, frWrapper.lifeInSeconds(),
-                                                       packets, bytes);
+                        packets, bytes);
                 resultBuilder.add(entry);
             }
         }
 
         if (inconsistentEntries.size() > 0) {
             log.warn("Found {} entries in {} that are not known by table entry service," +
-                             " removing them", inconsistentEntries.size(), deviceId);
+                    " removing them", inconsistentEntries.size(), deviceId);
             inconsistentEntries.forEach(entry -> log.debug(entry.toString()));
             // Async remove them.
             client.writeTableEntries(inconsistentEntries, DELETE, pipeconf);
@@ -207,17 +210,18 @@
             }
 
             PiTableId tableId = piTableEntry.table();
-            Bmv2TableEntryReference entryRef = new Bmv2TableEntryReference(deviceId, tableId, piTableEntry.matchKey());
+            P4RuntimeTableEntryReference entryRef = new P4RuntimeTableEntryReference(deviceId,
+                    tableId, piTableEntry.matchKey());
 
             Lock lock = ENTRY_LOCKS.computeIfAbsent(entryRef, k -> new ReentrantLock());
             lock.lock();
 
             try {
 
-                Bmv2FlowRuleWrapper frWrapper = ENTRY_STORE.get(entryRef);
+                P4RuntimeFlowRuleWrapper frWrapper = ENTRY_STORE.get(entryRef);
 
                 WriteOperationType opType;
-                if (operation == Operation.APPLY) {
+                if (operation == APPLY) {
                     opType = INSERT;
                     if (frWrapper != null) {
                         // We've seen some strange error when trying to modify existing flow rules.
@@ -227,7 +231,7 @@
                                 frWrapper = null;
                             } else {
                                 log.warn("Unable to DELETE table entry (before re-adding) in {}: {}",
-                                         deviceId, piTableEntry);
+                                        deviceId, piTableEntry);
                             }
                         } catch (InterruptedException | ExecutionException e) {
                             log.warn("Exception while deleting table entry:", operation.name(), e);
@@ -240,7 +244,7 @@
                 try {
                     if (client.writeTableEntries(newArrayList(piTableEntry), opType, pipeconf).get()) {
                         processedFlowRuleListBuilder.add(rule);
-                        frWrapper = new Bmv2FlowRuleWrapper(rule, System.currentTimeMillis());
+                        frWrapper = new P4RuntimeFlowRuleWrapper(rule, System.currentTimeMillis());
                     } else {
                         log.warn("Unable to {} table entry in {}: {}", opType.name(), deviceId, piTableEntry);
                     }
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2GroupProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
similarity index 96%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2GroupProgrammable.java
rename to drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
index 954ecf8..15a40ca 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2GroupProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2;
+package org.onosproject.drivers.p4runtime;
 
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
@@ -34,7 +34,7 @@
 
 import java.nio.ByteBuffer;
 
-public class Bmv2GroupProgrammable extends AbstractHandlerBehaviour implements GroupProgrammable {
+public class P4RuntimeGroupProgrammable extends AbstractHandlerBehaviour implements GroupProgrammable {
 
     /*
     Work in progress.
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2Handshaker.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeHandshaker.java
similarity index 96%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2Handshaker.java
rename to drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeHandshaker.java
index 808561d..82a9b85 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2Handshaker.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeHandshaker.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2;
+package org.onosproject.drivers.p4runtime;
 
 import io.grpc.ManagedChannelBuilder;
 import io.grpc.netty.NettyChannelBuilder;
@@ -33,7 +33,7 @@
 /**
  * Implementation of DeviceHandshaker for BMv2.
  */
-public class Bmv2Handshaker extends AbstractHandlerBehaviour
+public class P4RuntimeHandshaker extends AbstractHandlerBehaviour
         implements DeviceHandshaker {
 
     private final Logger log = getLogger(getClass());
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
similarity index 95%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java
rename to drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
index 50dfe1d..7a11376 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2;
+package org.onosproject.drivers.p4runtime;
 
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
@@ -36,7 +36,7 @@
 /**
  * Packet Programmable behaviour for BMv2 devices.
  */
-public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements PacketProgrammable {
+public class P4RuntimePacketProgrammable extends AbstractHandlerBehaviour implements PacketProgrammable {
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     @Override
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/package-info.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/package-info.java
new file mode 100644
index 0000000..07f7ede
--- /dev/null
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/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.
+ */
+
+/**
+ * Package for p4runtime device drivers.
+ */
+package org.onosproject.drivers.p4runtime;
\ No newline at end of file
diff --git a/drivers/p4runtime/src/main/resources/p4runtime-drivers.xml b/drivers/p4runtime/src/main/resources/p4runtime-drivers.xml
new file mode 100644
index 0000000..9457cac
--- /dev/null
+++ b/drivers/p4runtime/src/main/resources/p4runtime-drivers.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2017-present Open Networking Foundation
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<drivers>
+    <driver name="p4runtime" manufacturer="p4.org" hwVersion="master" swVersion="master">
+        <behaviour api="org.onosproject.net.device.DeviceHandshaker"
+                   impl="org.onosproject.drivers.p4runtime.P4RuntimeHandshaker"/>
+        <behaviour api="org.onosproject.net.packet.PacketProgrammable"
+                   impl="org.onosproject.drivers.p4runtime.P4RuntimePacketProgrammable"/>
+        <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
+                   impl="org.onosproject.drivers.p4runtime.P4RuntimeFlowRuleProgrammable"/>
+        <behaviour api="org.onosproject.net.group.GroupProgrammable"
+                   impl="org.onosproject.drivers.p4runtime.P4RuntimeGroupProgrammable"/>
+    </driver>
+</drivers>
+
diff --git a/modules.defs b/modules.defs
index fa8a16d..fbb83b9 100644
--- a/modules.defs
+++ b/modules.defs
@@ -106,6 +106,7 @@
     '//drivers/oplink:onos-drivers-oplink-oar',
     '//drivers/bmv2:onos-drivers-bmv2-oar',
     '//drivers/hp:onos-drivers-hp-oar',
+    '//drivers/p4runtime:onos-drivers-p4runtime-oar',
 ]
 
 ONOS_PROVIDERS = [
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleWrapper.java b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeFlowRuleWrapper.java
similarity index 85%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleWrapper.java
rename to protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeFlowRuleWrapper.java
index 879783b..d076cb4 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleWrapper.java
+++ b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeFlowRuleWrapper.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2;
+package org.onosproject.p4runtime.api;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
@@ -22,10 +22,10 @@
 import org.onosproject.net.flow.FlowRule;
 
 /**
- * A wrapper for a ONOS flow rule installed on a BMv2 device.
+ * A wrapper for a ONOS flow rule installed on a P4Runtime device.
  */
 @Beta
-final class Bmv2FlowRuleWrapper {
+public final class P4RuntimeFlowRuleWrapper {
 
     private final FlowRule rule;
     private final long installedOnMillis;
@@ -37,7 +37,7 @@
      * @param installedOnMillis the time (in milliseconds, since January 1, 1970 UTC) when the flow rule was installed
      *                          on the device
      */
-    Bmv2FlowRuleWrapper(FlowRule rule, long installedOnMillis) {
+    public P4RuntimeFlowRuleWrapper(FlowRule rule, long installedOnMillis) {
         this.rule = rule;
         this.installedOnMillis = installedOnMillis;
     }
@@ -47,7 +47,7 @@
      *
      * @return a flow rule
      */
-    FlowRule rule() {
+    public FlowRule rule() {
         return rule;
     }
 
@@ -56,7 +56,7 @@
      *
      * @return an integer value
      */
-    long lifeInSeconds() {
+    public long lifeInSeconds() {
         return (System.currentTimeMillis() - installedOnMillis) / 1000;
     }
 
@@ -73,7 +73,7 @@
         if (obj == null || getClass() != obj.getClass()) {
             return false;
         }
-        final Bmv2FlowRuleWrapper other = (Bmv2FlowRuleWrapper) obj;
+        final P4RuntimeFlowRuleWrapper other = (P4RuntimeFlowRuleWrapper) obj;
         return Objects.equal(this.rule, other.rule)
                 && Objects.equal(this.installedOnMillis, other.installedOnMillis);
     }
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2TableEntryReference.java b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeTableEntryReference.java
similarity index 87%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2TableEntryReference.java
rename to protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeTableEntryReference.java
index 9b99faa..5a0e9ca 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2TableEntryReference.java
+++ b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeTableEntryReference.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2;
+package org.onosproject.p4runtime.api;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
@@ -24,7 +24,10 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-public final class Bmv2TableEntryReference {
+/**
+ * Class containing the reference for a table entry in P4Runtime.
+ */
+public final class P4RuntimeTableEntryReference {
 
     private final DeviceId deviceId;
     private final PiTableId tableId;
@@ -37,7 +40,7 @@
      * @param tableId  a table name
      * @param matchKey a match key
      */
-    public Bmv2TableEntryReference(DeviceId deviceId, PiTableId tableId, PiMatchKey matchKey) {
+    public P4RuntimeTableEntryReference(DeviceId deviceId, PiTableId tableId, PiMatchKey matchKey) {
         this.deviceId = checkNotNull(deviceId);
         this.tableId = checkNotNull(tableId);
         this.matchKey = checkNotNull(matchKey);
@@ -83,7 +86,7 @@
         if (obj == null || getClass() != obj.getClass()) {
             return false;
         }
-        final Bmv2TableEntryReference other = (Bmv2TableEntryReference) obj;
+        final P4RuntimeTableEntryReference other = (P4RuntimeTableEntryReference) obj;
         return Objects.equal(this.deviceId, other.deviceId)
                 && Objects.equal(this.tableId, other.tableId)
                 && Objects.equal(this.matchKey, other.matchKey);
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
index ff083c3..7f88249 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
@@ -208,34 +208,40 @@
             return false;
         }
 
-        if (!pipeconf.extension(targetConfigExtType).isPresent()) {
-            log.warn("Missing extension {} in pipeconf {}", targetConfigExtType, pipeconf.id());
-            return false;
-        }
 
-        InputStream targetConfig = pipeconf.extension(targetConfigExtType).get();
-        P4Config.P4DeviceConfig p4DeviceConfigMsg;
-        try {
-            p4DeviceConfigMsg = P4Config.P4DeviceConfig
-                    .newBuilder()
-                    .setExtras(P4Config.P4DeviceConfig.Extras.getDefaultInstance())
-                    .setReassign(true)
-                    .setDeviceData(ByteString.readFrom(targetConfig))
-                    .build();
-        } catch (IOException ex) {
-            log.warn("Unable to load target-specific config for {}: {}", deviceId, ex.getMessage());
-            return false;
+        ForwardingPipelineConfig.Builder pipelineConfigBuilder = ForwardingPipelineConfig
+                .newBuilder()
+                .setDeviceId(p4DeviceId)
+                .setP4Info(p4Info);
+
+        //if the target config extension is null we don't want to add the config.
+        if (targetConfigExtType != null) {
+            if (!pipeconf.extension(targetConfigExtType).isPresent()) {
+                log.warn("Missing extension {} in pipeconf {}", targetConfigExtType, pipeconf.id());
+                return false;
+            }
+            InputStream targetConfig = pipeconf.extension(targetConfigExtType).get();
+            P4Config.P4DeviceConfig p4DeviceConfigMsg;
+            try {
+                p4DeviceConfigMsg = P4Config.P4DeviceConfig
+                        .newBuilder()
+                        .setExtras(P4Config.P4DeviceConfig.Extras.getDefaultInstance())
+                        .setReassign(true)
+                        .setDeviceData(ByteString.readFrom(targetConfig))
+                        .build();
+
+                pipelineConfigBuilder.setP4DeviceConfig(p4DeviceConfigMsg.toByteString());
+
+            } catch (IOException ex) {
+                log.warn("Unable to load target-specific config for {}: {}", deviceId, ex.getMessage());
+                return false;
+            }
         }
 
         SetForwardingPipelineConfigRequest request = SetForwardingPipelineConfigRequest
                 .newBuilder()
                 .setAction(VERIFY_AND_COMMIT)
-                .addConfigs(ForwardingPipelineConfig
-                                    .newBuilder()
-                                    .setDeviceId(p4DeviceId)
-                                    .setP4Info(p4Info)
-                                    .setP4DeviceConfig(p4DeviceConfigMsg.toByteString())
-                                    .build())
+                .addConfigs(pipelineConfigBuilder.build())
                 .build();
 
         try {
@@ -434,7 +440,7 @@
 
         private void doNext(StreamMessageResponse message) {
             try {
-                log.info("Received message on stream channel from {}: {}", deviceId, message.getUpdateCase());
+                log.debug("Received message on stream channel from {}: {}", deviceId, message.getUpdateCase());
                 switch (message.getUpdateCase()) {
                     case PACKET:
                         // Packet-in
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
index 6b345eb..0dd82f3 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
@@ -140,6 +140,7 @@
 
         TableEntry.Builder tableEntryMsgBuilder = TableEntry.newBuilder();
 
+        //FIXME this thorws some kind of NPE
         P4InfoOuterClass.Table tableInfo = browser.tables().getByName(piTableEntry.table().id());
 
         // Table id.