New P4RuntimeClient implementation that supports batching and error reporting

The new client API supports batching and provides detailed response for
write requests (e.g. if entity already exists when inserting), which was
not possible with the old one.

This patch includes:
- New more efficient implementation of P4RuntimeClient (no more locking,
use native gRPC executor, use stub deadlines)
- Ported all codecs to new AbstractCodec-based implementation (needed to
implement codec cache in the future)
- Uses batching in P4RuntimeFlowRuleProgrammable and
P4RuntimeGroupActionProgrammable
- Minor changes to PI framework runtime classes

Change-Id: I3fac42057bb4e1389d761006a32600c786598683
diff --git a/core/api/src/test/java/org/onosproject/net/pi/PiPipeconfServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/pi/PiPipeconfServiceAdapter.java
index 8eebf5f..66f9315 100644
--- a/core/api/src/test/java/org/onosproject/net/pi/PiPipeconfServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/pi/PiPipeconfServiceAdapter.java
@@ -49,6 +49,11 @@
     }
 
     @Override
+    public Optional<PiPipeconf> getPipeconf(DeviceId deviceId) {
+        return Optional.empty();
+    }
+
+    @Override
     public void bindToDevice(PiPipeconfId pipeconfId, DeviceId deviceId) {
 
     }
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiControlMetadataTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiControlMetadataTest.java
deleted file mode 100644
index ab80fd6..0000000
--- a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiControlMetadataTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.net.pi.runtime;
-
-import com.google.common.testing.EqualsTester;
-import org.junit.Test;
-import org.onosproject.net.pi.model.PiControlMetadataId;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
-import static org.onlab.util.ImmutableByteSequence.copyFrom;
-import static org.onosproject.net.pi.runtime.PiConstantsTest.EGRESS_PORT;
-
-/**
- * Unit tests for PiControlMetadata class.
- */
-public class PiControlMetadataTest {
-
-    final PiControlMetadataId piControlMetadataId = PiControlMetadataId.of(EGRESS_PORT);
-
-    final PiControlMetadata piControlMetadata1 = PiControlMetadata.builder()
-            .withId(piControlMetadataId)
-            .withValue(copyFrom(0x10))
-            .build();
-    final PiControlMetadata sameAsPiControlMetadata1 = PiControlMetadata.builder()
-            .withId(piControlMetadataId)
-            .withValue(copyFrom(0x10))
-            .build();
-    final PiControlMetadata piControlMetadata2 = PiControlMetadata.builder()
-            .withId(piControlMetadataId)
-            .withValue(copyFrom(0x20))
-            .build();
-
-    /**
-     * Checks that the PiControlMetadata class is immutable.
-     */
-    @Test
-    public void testImmutability() {
-
-        assertThatClassIsImmutable(PiControlMetadata.class);
-    }
-
-    /**
-     * Checks the operation of equals(), hashCode() and toString() methods.
-     */
-    @Test
-    public void testEquals() {
-
-        new EqualsTester()
-                .addEqualityGroup(piControlMetadata1, sameAsPiControlMetadata1)
-                .addEqualityGroup(piControlMetadata2)
-                .testEquals();
-    }
-
-    /**
-     * Checks the methods of PiControlMetadata.
-     */
-    @Test
-    public void testMethods() {
-
-        assertThat(piControlMetadata1, is(notNullValue()));
-        assertThat(piControlMetadata1.id(), is(PiControlMetadataId.of(EGRESS_PORT)));
-        assertThat(piControlMetadata1.value(), is(copyFrom(0x10)));
-    }
-}
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiControlMetadataIdTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketMetadataIdTest.java
similarity index 62%
rename from core/api/src/test/java/org/onosproject/net/pi/runtime/PiControlMetadataIdTest.java
rename to core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketMetadataIdTest.java
index d65ef2e..310b836 100644
--- a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiControlMetadataIdTest.java
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketMetadataIdTest.java
@@ -18,7 +18,7 @@
 
 import com.google.common.testing.EqualsTester;
 import org.junit.Test;
-import org.onosproject.net.pi.model.PiControlMetadataId;
+import org.onosproject.net.pi.model.PiPacketMetadataId;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -28,21 +28,21 @@
 import static org.onosproject.net.pi.runtime.PiConstantsTest.INGRESS_PORT;
 
 /**
- * Unit tests for PiControlMetadataId class.
+ * Unit tests for PiPacketMetadataId class.
  */
-public class PiControlMetadataIdTest {
+public class PiPacketMetadataIdTest {
 
-    final PiControlMetadataId piControlMetadataId1 = PiControlMetadataId.of(EGRESS_PORT);
-    final PiControlMetadataId sameAsPiControlMetadataId1 = PiControlMetadataId.of(EGRESS_PORT);
-    final PiControlMetadataId piControlMetadataId2 = PiControlMetadataId.of(INGRESS_PORT);
+    final PiPacketMetadataId piPacketMetadataId1 = PiPacketMetadataId.of(EGRESS_PORT);
+    final PiPacketMetadataId sameAsPiPacketMetadataId1 = PiPacketMetadataId.of(EGRESS_PORT);
+    final PiPacketMetadataId piPacketMetadataId2 = PiPacketMetadataId.of(INGRESS_PORT);
 
     /**
-     * Checks that the PiControlMetadataId class is immutable.
+     * Checks that the PiPacketMetadataId class is immutable.
      */
     @Test
     public void testImmutability() {
 
-        assertThatClassIsImmutable(PiControlMetadataId.class);
+        assertThatClassIsImmutable(PiPacketMetadataId.class);
     }
 
     /**
@@ -52,17 +52,17 @@
     public void testEquals() {
 
         new EqualsTester()
-                .addEqualityGroup(piControlMetadataId1, sameAsPiControlMetadataId1)
-                .addEqualityGroup(piControlMetadataId2)
+                .addEqualityGroup(piPacketMetadataId1, sameAsPiPacketMetadataId1)
+                .addEqualityGroup(piPacketMetadataId2)
                 .testEquals();
     }
 
     /**
-     * Checks the methods of PiControlMetadataId.
+     * Checks the methods of PiPacketMetadataId.
      */
     @Test
     public void testMethods() {
-        assertThat(piControlMetadataId1, is(notNullValue()));
-        assertThat(piControlMetadataId1.id(), is(EGRESS_PORT));
+        assertThat(piPacketMetadataId1, is(notNullValue()));
+        assertThat(piPacketMetadataId1.id(), is(EGRESS_PORT));
     }
 }
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketMetadataTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketMetadataTest.java
new file mode 100644
index 0000000..58cd252
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketMetadataTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.net.pi.runtime;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.pi.model.PiPacketMetadataId;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.onlab.util.ImmutableByteSequence.copyFrom;
+import static org.onosproject.net.pi.runtime.PiConstantsTest.EGRESS_PORT;
+
+/**
+ * Unit tests for PiPacketMetadata class.
+ */
+public class PiPacketMetadataTest {
+
+    final PiPacketMetadataId piPacketMetadataId = PiPacketMetadataId.of(EGRESS_PORT);
+
+    final PiPacketMetadata piPacketMetadata1 = PiPacketMetadata.builder()
+            .withId(piPacketMetadataId)
+            .withValue(copyFrom(0x10))
+            .build();
+    final PiPacketMetadata sameAsPiPacketMetadata1 = PiPacketMetadata.builder()
+            .withId(piPacketMetadataId)
+            .withValue(copyFrom(0x10))
+            .build();
+    final PiPacketMetadata piPacketMetadata2 = PiPacketMetadata.builder()
+            .withId(piPacketMetadataId)
+            .withValue(copyFrom(0x20))
+            .build();
+
+    /**
+     * Checks that the PiPacketMetadata class is immutable.
+     */
+    @Test
+    public void testImmutability() {
+
+        assertThatClassIsImmutable(PiPacketMetadata.class);
+    }
+
+    /**
+     * Checks the operation of equals(), hashCode() and toString() methods.
+     */
+    @Test
+    public void testEquals() {
+
+        new EqualsTester()
+                .addEqualityGroup(piPacketMetadata1, sameAsPiPacketMetadata1)
+                .addEqualityGroup(piPacketMetadata2)
+                .testEquals();
+    }
+
+    /**
+     * Checks the methods of PiPacketMetadata.
+     */
+    @Test
+    public void testMethods() {
+
+        assertThat(piPacketMetadata1, is(notNullValue()));
+        assertThat(piPacketMetadata1.id(), is(PiPacketMetadataId.of(EGRESS_PORT)));
+        assertThat(piPacketMetadata1.value(), is(copyFrom(0x10)));
+    }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketOperationTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketOperationTest.java
index d675b51..e924914 100644
--- a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketOperationTest.java
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiPacketOperationTest.java
@@ -21,8 +21,7 @@
 import org.apache.commons.collections.CollectionUtils;
 import org.junit.Test;
 import org.onlab.util.ImmutableByteSequence;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.pi.model.PiControlMetadataId;
+import org.onosproject.net.pi.model.PiPacketMetadataId;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -37,34 +36,29 @@
  */
 public class PiPacketOperationTest {
 
-    private final DeviceId deviceId = DeviceId.deviceId("dummy");
-
     private final PiPacketOperation piPacketOperation1 = PiPacketOperation.builder()
-            .forDevice(deviceId)
             .withData(ImmutableByteSequence.ofOnes(512))
             .withType(PACKET_OUT)
-            .withMetadata(PiControlMetadata.builder()
-                                  .withId(PiControlMetadataId.of(EGRESS_PORT))
+            .withMetadata(PiPacketMetadata.builder()
+                                  .withId(PiPacketMetadataId.of(EGRESS_PORT))
                                   .withValue(copyFrom((short) 255))
                                   .build())
             .build();
 
     private final PiPacketOperation sameAsPiPacketOperation1 = PiPacketOperation.builder()
-            .forDevice(deviceId)
             .withData(ImmutableByteSequence.ofOnes(512))
             .withType(PACKET_OUT)
-            .withMetadata(PiControlMetadata.builder()
-                                  .withId(PiControlMetadataId.of(EGRESS_PORT))
+            .withMetadata(PiPacketMetadata.builder()
+                                  .withId(PiPacketMetadataId.of(EGRESS_PORT))
                                   .withValue(copyFrom((short) 255))
                                   .build())
             .build();
 
     private final PiPacketOperation piPacketOperation2 = PiPacketOperation.builder()
-            .forDevice(deviceId)
             .withData(ImmutableByteSequence.ofOnes(512))
             .withType(PACKET_OUT)
-            .withMetadata(PiControlMetadata.builder()
-                                  .withId(PiControlMetadataId.of(EGRESS_PORT))
+            .withMetadata(PiPacketMetadata.builder()
+                                  .withId(PiPacketMetadataId.of(EGRESS_PORT))
                                   .withValue(copyFrom((short) 200))
                                   .build())
             .build();
@@ -97,23 +91,21 @@
     public void testMethods() {
 
         final PiPacketOperation piPacketOperation = PiPacketOperation.builder()
-                .forDevice(deviceId)
                 .withData(ImmutableByteSequence.ofOnes(512))
                 .withType(PACKET_OUT)
-                .withMetadata(PiControlMetadata.builder()
-                                      .withId(PiControlMetadataId.of(EGRESS_PORT))
+                .withMetadata(PiPacketMetadata.builder()
+                                      .withId(PiPacketMetadataId.of(EGRESS_PORT))
                                       .withValue(copyFrom((short) 10))
                                       .build())
                 .build();
 
         assertThat(piPacketOperation, is(notNullValue()));
-        assertThat(piPacketOperation.deviceId(), is(deviceId));
         assertThat(piPacketOperation.type(), is(PACKET_OUT));
         assertThat(piPacketOperation.data(), is(ImmutableByteSequence.ofOnes(512)));
         assertThat("Incorrect metadatas value",
                    CollectionUtils.isEqualCollection(piPacketOperation.metadatas(),
-                                                     ImmutableList.of(PiControlMetadata.builder()
-                                                                              .withId(PiControlMetadataId
+                                                     ImmutableList.of(PiPacketMetadata.builder()
+                                                                              .withId(PiPacketMetadataId
                                                                                               .of(EGRESS_PORT))
                                                                               .withValue(copyFrom((short) 10))
                                                                               .build())));
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiTableEntryTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiTableEntryTest.java
index 087eb77..ee2fd78 100644
--- a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiTableEntryTest.java
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiTableEntryTest.java
@@ -110,7 +110,7 @@
         assertThat(piTableEntry.cookie(), is(cookie));
         assertThat("Priority must be set", piTableEntry.priority().isPresent());
         assertThat("Timeout must be set", piTableEntry.timeout().isPresent());
-        assertThat(piTableEntry.priority().get(), is(priority));
+        assertThat(piTableEntry.priority().getAsInt(), is(priority));
         assertThat(piTableEntry.timeout().get(), is(timeout));
         assertThat("Incorrect match param value",
                    CollectionUtils.isEqualCollection(piTableEntry.matchKey().fieldMatches(), fieldMatches.values()));