Support arbitrary bit width action parameter and match field

This commit goes into the direction of supporting user-defined types in P4Runtime.
The modification is focusing on supporting fields and params with arbitrary bit width, that is the
case of using a String with the p4runtime_translation annotation on the user-defined type.

Change-Id: I7db7a6d97211378ff78ab4f1b3734a0bec4558e6
diff --git a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/ActionCodec.java b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/ActionCodec.java
index 3ae46c9..69b31a8 100644
--- a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/ActionCodec.java
+++ b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/ActionCodec.java
@@ -48,8 +48,11 @@
             final P4InfoOuterClass.Action.Param paramInfo = browser.actionParams(actionId)
                     .getByName(p.id().toString());
             final ByteString paramValue = ByteString.copyFrom(p.value().asReadOnlyBuffer());
-            assertSize(format("param '%s' of action '%s'", p.id(), piAction.id()),
-                       paramValue, paramInfo.getBitwidth());
+            if (!browser.isTypeString(paramInfo.getTypeName())) {
+                // Check size only if the param type is not a sdn_string
+                assertSize(format("param '%s' of action '%s'", p.id(), piAction.id()),
+                           paramValue, paramInfo.getBitwidth());
+            }
             actionMsgBuilder.addParams(P4RuntimeOuterClass.Action.Param.newBuilder()
                                                .setParamId(paramInfo.getId())
                                                .setValue(paramValue)
diff --git a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/FieldMatchCodec.java b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/FieldMatchCodec.java
index f289d5d..5e2ec43 100644
--- a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/FieldMatchCodec.java
+++ b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/FieldMatchCodec.java
@@ -71,7 +71,10 @@
             case EXACT:
                 PiExactFieldMatch fieldMatch = (PiExactFieldMatch) piFieldMatch;
                 ByteString exactValue = ByteString.copyFrom(fieldMatch.value().asReadOnlyBuffer());
-                assertSize(VALUE_OF_PREFIX + entityName, exactValue, fieldBitwidth);
+                // We support string only for EXACT match (via p4runtime_translation)
+                if (!browser.isTypeString(matchFieldInfo.getTypeName())) {
+                    assertSize(VALUE_OF_PREFIX + entityName, exactValue, fieldBitwidth);
+                }
                 return messageBuilder.setExact(
                         P4RuntimeOuterClass.FieldMatch.Exact
                                 .newBuilder()
diff --git a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/utils/P4InfoBrowser.java b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/utils/P4InfoBrowser.java
index 8504202..85405ca 100644
--- a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/utils/P4InfoBrowser.java
+++ b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/utils/P4InfoBrowser.java
@@ -31,6 +31,7 @@
 import p4.config.v1.P4InfoOuterClass.Preamble;
 import p4.config.v1.P4InfoOuterClass.Table;
 import p4.config.v1.P4InfoOuterClass.Digest;
+import p4.config.v1.P4Types;
 
 import java.util.Map;
 
@@ -57,6 +58,7 @@
     private final Map<Integer, EntityBrowser<ControllerPacketMetadata.Metadata>> ctrlPktMetadatasMetadata =
             Maps.newHashMap();
     private final EntityBrowser<Digest> digests = new EntityBrowser<>("digest");
+    private final Map<String, Boolean> isTypeString = Maps.newHashMap();
 
     /**
      * Creates a new browser for the given P4Info.
@@ -121,6 +123,12 @@
 
         p4info.getDigestsList().forEach(
                 entity -> digests.addWithPreamble(entity.getPreamble(), entity));
+        p4info.getTypeInfo().getNewTypesMap().forEach(
+                (s, p4NewTypeSpec) ->
+                        isTypeString.put(s,
+                                         p4NewTypeSpec.hasTranslatedType()
+                                                 && p4NewTypeSpec.getTranslatedType().hasSdnString()
+                        ));
     }
 
     /**
@@ -245,6 +253,17 @@
     }
 
     /**
+     * Checks if the given type name is a sdn_string.
+     *
+     * @param typeName Type name to check
+     * @return True if the given type name is a sdn_string, false otherwise
+     */
+    public boolean isTypeString(P4Types.P4NamedType typeName) {
+        return isTypeString.containsKey(typeName.getName())
+                && isTypeString.get(typeName.getName());
+    }
+
+    /**
      * Browser of P4Info entities.
      *
      * @param <T> protobuf message type