Bump version of P4Runtime to 1.0.0rc3 and P4 tools

Change-Id: I3082b4bd772d692830bd5af8e326a0fd5fb2f167
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ClientKey.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ClientKey.java
index ee5e2a4..cc4bed0 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ClientKey.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ClientKey.java
@@ -22,7 +22,7 @@
 import java.util.Objects;
 
 /**
- * Key the uniquely identifies a P4Runtime client.
+ * Key that uniquely identifies a P4Runtime client.
  */
 final class ClientKey {
 
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/DistributedElectionIdGenerator.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/DistributedElectionIdGenerator.java
index ecfe35d..75c068e 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/DistributedElectionIdGenerator.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/DistributedElectionIdGenerator.java
@@ -38,6 +38,7 @@
 
     private final Logger log = getLogger(this.getClass());
 
+    // FIXME: counter map use long, but P4Runtime accepts 128bit election IDs
     private AtomicCounterMap<DeviceId> electionIds;
 
     /**
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/MulticastGroupEntryCodec.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/MulticastGroupEntryCodec.java
index 0be1ae8..f2ececb 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/MulticastGroupEntryCodec.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/MulticastGroupEntryCodec.java
@@ -22,6 +22,8 @@
 import p4.v1.P4RuntimeOuterClass.MulticastGroupEntry;
 import p4.v1.P4RuntimeOuterClass.Replica;
 
+import static java.lang.String.format;
+
 /**
  * A coded of {@link PiMulticastGroupEntry} to P4Runtime MulticastGroupEntry
  * messages, and vice versa.
@@ -38,16 +40,26 @@
      *
      * @param piEntry PiMulticastGroupEntry
      * @return P4Runtime MulticastGroupEntry message
+     * @throws EncodeException if the PiMulticastGroupEntry cannot be encoded.
      */
-    static MulticastGroupEntry encode(PiMulticastGroupEntry piEntry) {
+    static MulticastGroupEntry encode(PiMulticastGroupEntry piEntry) throws EncodeException {
         final MulticastGroupEntry.Builder msgBuilder = MulticastGroupEntry.newBuilder();
         msgBuilder.setMulticastGroupId(piEntry.groupId());
-        piEntry.replicas().stream()
-                .map(r -> Replica.newBuilder()
-                        .setEgressPort(r.egressPort().toLong())
-                        .setInstance(r.instanceId())
-                        .build())
-                .forEach(msgBuilder::addReplicas);
+        for (PiPreReplica replica : piEntry.replicas()) {
+            final int p4PortId;
+            try {
+                p4PortId = Math.toIntExact(replica.egressPort().toLong());
+            } catch (ArithmeticException e) {
+                throw new EncodeException(format(
+                        "Cannot cast 64bit port value '%s' to 32bit",
+                        replica.egressPort()));
+            }
+            msgBuilder.addReplicas(
+                    Replica.newBuilder()
+                            .setEgressPort(p4PortId)
+                            .setInstance(replica.instanceId())
+                            .build());
+        }
         return msgBuilder.build();
     }
 
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 54d284d..c291db4 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
@@ -1053,7 +1053,15 @@
             WriteOperationType opType) {
 
         final List<Update> updateMsgs = entries.stream()
-                .map(MulticastGroupEntryCodec::encode)
+                .map(piEntry -> {
+                    try {
+                        return MulticastGroupEntryCodec.encode(piEntry);
+                    } catch (EncodeException e) {
+                        log.warn("Unable to encode PiMulticastGroupEntry: {}", e.getMessage());
+                        return null;
+                    }
+                })
+                .filter(Objects::nonNull)
                 .map(mcMsg -> PacketReplicationEngineEntry.newBuilder()
                         .setMulticastGroupEntry(mcMsg)
                         .build())
@@ -1117,13 +1125,22 @@
                               WriteOperationType opType,
                               String entryType) {
         // True if all entities were successfully written.
-        return writeAndReturnSuccessEntities(updates, writeEntities, opType,
-                                             entryType).size() == writeEntities.size();
+        return writeAndReturnSuccessEntities(updates, writeEntities, opType, entryType)
+                .size() == writeEntities.size();
     }
 
     private <T> List<T> writeAndReturnSuccessEntities(
             List<Update> updates, List<T> writeEntities,
             WriteOperationType opType, String entryType) {
+        if (updates.isEmpty()) {
+            return Collections.emptyList();
+        }
+        if (updates.size() != writeEntities.size()) {
+            log.error("Cannot perform {} operation, provided {} " +
+                              "update messages for {} {} - BUG?",
+                      opType, updates.size(), writeEntities.size(), entryType);
+            return Collections.emptyList();
+        }
         try {
             //noinspection ResultOfMethodCallIgnored
             blockingStub.write(writeRequest(updates));