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/core/api/src/main/java/org/onosproject/net/pi/model/PiActionParamModel.java b/core/api/src/main/java/org/onosproject/net/pi/model/PiActionParamModel.java
index 284d2b2..ff504be 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/model/PiActionParamModel.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/model/PiActionParamModel.java
@@ -33,8 +33,17 @@
 
     /**
      * Return the size in bits of this action parameter.
+     * It returns -1 if the bit width of the action parameters is not predefined.
      *
-     * @return size in bits
+     * @return size in bits, -1 if not predefined
      */
     int bitWidth();
+
+    /**
+     * Return true is the action parameters has a predefined bit width.
+     * It returns false if it can have arbitrary bit width.
+     *
+     * @return True if the action parameter has predefined bit width, false otherwise
+     */
+    boolean hasBitWidth();
 }
diff --git a/core/api/src/main/java/org/onosproject/net/pi/model/PiMatchFieldModel.java b/core/api/src/main/java/org/onosproject/net/pi/model/PiMatchFieldModel.java
index 57d817a..16020ce 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/model/PiMatchFieldModel.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/model/PiMatchFieldModel.java
@@ -33,12 +33,21 @@
 
     /**
      * Returns the number of bits matched by this field.
+     * It returns -1 if the bit width of the match field is not predefined.
      *
-     * @return number of bits
+     * @return number of bits, -1 in case it is not predefined
      */
     int bitWidth();
 
     /**
+     * Return true is the match field has a predefined bit width.
+     * It returns false if it can have arbitrary bit width.
+     *
+     * @return True if the match field has predefined bit width, false otherwise
+     */
+    boolean hasBitWidth();
+
+    /**
      * Returns the type of match applied to this field.
      *
      * @return a match type
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
index 3647427..8350549 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
@@ -277,7 +277,9 @@
                             "Not such parameter '%s' for action '%s'", param.id(), actionModel)));
             try {
                 newActionBuilder.withParameter(new PiActionParam(param.id(),
-                                                                 param.value().fit(paramModel.bitWidth())));
+                                                                 paramModel.hasBitWidth() ?
+                                                                         param.value().fit(paramModel.bitWidth()) :
+                                                                         param.value()));
             } catch (ByteSequenceTrimException e) {
                 throw new PiTranslationException(format(
                         "Size mismatch for parameter '%s' of action '%s': %s",
@@ -372,7 +374,8 @@
 
             PiFieldMatch fieldMatch = null;
 
-            if (criterion != null) {
+            // TODO: we currently do not support fields with arbitrary bit width
+            if (criterion != null && fieldModel.hasBitWidth()) {
                 // Criterion mapping is possible for this field id.
                 try {
                     fieldMatch = translateCriterion(criterion, fieldId, fieldModel.matchType(), bitWidth);
@@ -458,8 +461,12 @@
         try {
             switch (fieldModel.matchType()) {
                 case EXACT:
+                    // TODO: arbitrary bit width is supported only for the EXACT match case.
+                    PiExactFieldMatch exactField = (PiExactFieldMatch) fieldMatch;
                     return new PiExactFieldMatch(fieldMatch.fieldId(),
-                                                 ((PiExactFieldMatch) fieldMatch).value().fit(modelBitWidth));
+                                                 fieldModel.hasBitWidth() ?
+                                                         exactField.value().fit(modelBitWidth) :
+                                                         exactField.value());
                 case TERNARY:
                     PiTernaryFieldMatch ternField = (PiTernaryFieldMatch) fieldMatch;
                     ImmutableByteSequence ternMask = ternField.mask().fit(modelBitWidth);