Parse action profile max group size from P4Info annotations

This is a temporary workaround to the inability of p4c to
correctly interpret P4Runtime-defined @max_group_size annotations.

Change-Id: If2799786c135b2eb5b6a3b4c6d6022350d37237e
diff --git a/protocols/p4runtime/model/src/main/java/org/onosproject/p4runtime/model/P4InfoParser.java b/protocols/p4runtime/model/src/main/java/org/onosproject/p4runtime/model/P4InfoParser.java
index 6160881..d5bf2e6 100644
--- a/protocols/p4runtime/model/src/main/java/org/onosproject/p4runtime/model/P4InfoParser.java
+++ b/protocols/p4runtime/model/src/main/java/org/onosproject/p4runtime/model/P4InfoParser.java
@@ -28,8 +28,6 @@
 import org.onosproject.net.pi.model.PiActionParamModel;
 import org.onosproject.net.pi.model.PiActionProfileId;
 import org.onosproject.net.pi.model.PiActionProfileModel;
-import org.onosproject.net.pi.model.PiPacketMetadataId;
-import org.onosproject.net.pi.model.PiPacketMetadataModel;
 import org.onosproject.net.pi.model.PiCounterId;
 import org.onosproject.net.pi.model.PiCounterModel;
 import org.onosproject.net.pi.model.PiCounterType;
@@ -39,6 +37,8 @@
 import org.onosproject.net.pi.model.PiMeterId;
 import org.onosproject.net.pi.model.PiMeterModel;
 import org.onosproject.net.pi.model.PiMeterType;
+import org.onosproject.net.pi.model.PiPacketMetadataId;
+import org.onosproject.net.pi.model.PiPacketMetadataModel;
 import org.onosproject.net.pi.model.PiPacketOperationModel;
 import org.onosproject.net.pi.model.PiPacketOperationType;
 import org.onosproject.net.pi.model.PiPipelineModel;
@@ -47,6 +47,7 @@
 import org.onosproject.net.pi.model.PiTableId;
 import org.onosproject.net.pi.model.PiTableModel;
 import org.onosproject.net.pi.model.PiTableType;
+import org.slf4j.Logger;
 import p4.config.v1.P4InfoOuterClass;
 import p4.config.v1.P4InfoOuterClass.Action;
 import p4.config.v1.P4InfoOuterClass.ActionProfile;
@@ -71,12 +72,15 @@
 import java.util.stream.Collectors;
 
 import static java.lang.String.format;
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
  * Parser of P4Info to PI pipeline model instances.
  */
 public final class P4InfoParser {
 
+    private static final Logger log = getLogger(P4InfoParser.class);
+
     private static final String PACKET_IN = "packet_in";
     private static final String PACKET_OUT = "packet_out";
 
@@ -325,6 +329,26 @@
             for (int tableId : actProfileMsg.getTableIdsList()) {
                 tableIdSetBuilder.add(PiTableId.of(getTableName(tableId, p4info)));
             }
+            // TODO: we should copy all annotations to model classes for later
+            //  use in the PI framework.
+            // This is a temporary workaround to the inability of p4c to
+            // correctly interpret P4Runtime-defined max_group_size annotation:
+            // https://s3-us-west-2.amazonaws.com/p4runtime/docs/master/
+            // P4Runtime-Spec.html#sec-p4info-action-profile
+            final String maxSizeAnnString = findAnnotation(
+                    "max_group_size", actProfileMsg.getPreamble());
+            final int maxSizeAnn = maxSizeAnnString != null
+                    ? Integer.valueOf(maxSizeAnnString) : 0;
+            final int maxGroupSize;
+            if (actProfileMsg.getMaxGroupSize() == 0 && maxSizeAnn != 0) {
+                log.warn("Found valid 'max_group_size' annotation for " +
+                                 "ActionProfile {}, using that...",
+                         actProfileMsg.getPreamble().getName());
+                maxGroupSize = maxSizeAnn;
+            } else {
+                maxGroupSize = actProfileMsg.getMaxGroupSize();
+            }
+
             actProfileMap.put(
                     actProfileMsg.getPreamble().getId(),
                     new P4ActionProfileModel(
@@ -332,7 +356,7 @@
                             tableIdSetBuilder.build(),
                             actProfileMsg.getWithSelector(),
                             actProfileMsg.getSize(),
-                            actProfileMsg.getMaxGroupSize()));
+                            maxGroupSize));
         }
         return actProfileMap;
     }
@@ -431,4 +455,13 @@
         }
         return MATCH_TYPE_MAP.get(type);
     }
+
+    private static String findAnnotation(String name, P4InfoOuterClass.Preamble preamble) {
+        return preamble.getAnnotationsList().stream()
+                .filter(a -> a.startsWith("@" + name))
+                // e.g. @my_annotaion(value)
+                .map(a -> a.substring(name.length() + 2, a.length() - 1))
+                .findFirst()
+                .orElse(null);
+    }
 }
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionProfileModelTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionProfileModelTest.java
index 021d341..f3b857e 100644
--- a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionProfileModelTest.java
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionProfileModelTest.java
@@ -50,17 +50,17 @@
     private final PiActionProfileId id = PiActionProfileId.of("name");
     private final PiActionProfileId id2 = PiActionProfileId.of("name2");
 
-    private final P4ActionProfileModel metadataModel = new P4ActionProfileModel(id, tables,
+    private final P4ActionProfileModel actProfModel = new P4ActionProfileModel(id, tables,
                                                                                 true, 64, 10);
-    private final P4ActionProfileModel sameAsMetadataModel = new P4ActionProfileModel(id, sameAsTables,
+    private final P4ActionProfileModel sameAsActProfModel = new P4ActionProfileModel(id, sameAsTables,
                                                                                       true, 64, 10);
-    private final P4ActionProfileModel metadataModel2 = new P4ActionProfileModel(id, tables2,
+    private final P4ActionProfileModel actProfModel2 = new P4ActionProfileModel(id, tables2,
                                                                                  true, 64, 10);
-    private final P4ActionProfileModel metadataModel3 = new P4ActionProfileModel(id2, tables,
+    private final P4ActionProfileModel actProfModel3 = new P4ActionProfileModel(id2, tables,
                                                                                  true, 64, 10);
-    private final P4ActionProfileModel metadataModel4 = new P4ActionProfileModel(id, tables,
+    private final P4ActionProfileModel actProfModel4 = new P4ActionProfileModel(id, tables,
                                                                                  false, 64, 10);
-    private final P4ActionProfileModel metadataModel5 = new P4ActionProfileModel(id, tables,
+    private final P4ActionProfileModel actProfModel5 = new P4ActionProfileModel(id, tables,
                                                                                  true, 32, 5);
 
     /**
@@ -77,11 +77,11 @@
     @Test
     public void testEquals() {
         new EqualsTester()
-                .addEqualityGroup(metadataModel, sameAsMetadataModel)
-                .addEqualityGroup(metadataModel2)
-                .addEqualityGroup(metadataModel3)
-                .addEqualityGroup(metadataModel4)
-                .addEqualityGroup(metadataModel5)
+                .addEqualityGroup(actProfModel, sameAsActProfModel)
+                .addEqualityGroup(actProfModel2)
+                .addEqualityGroup(actProfModel3)
+                .addEqualityGroup(actProfModel4)
+                .addEqualityGroup(actProfModel5)
                 .testEquals();
     }
 }
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4InfoParserTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4InfoParserTest.java
index 9d696e2..c05a84c 100644
--- a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4InfoParserTest.java
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4InfoParserTest.java
@@ -70,7 +70,7 @@
 
     private static final Long DEFAULT_MAX_TABLE_SIZE = 1024L;
     private static final Long DEFAULT_MAX_ACTION_PROFILE_SIZE = 64L;
-    private static final int DEFAULT_MAX_GROUP_SIZE = 0;
+    private static final int DEFAULT_MAX_GROUP_SIZE = 16;
 
     /**
      * Tests parse method.
diff --git a/protocols/p4runtime/model/src/test/resources/org/onosproject/p4runtime/model/basic.p4info b/protocols/p4runtime/model/src/test/resources/org/onosproject/p4runtime/model/basic.p4info
index 8010892..bc6ca71 100644
--- a/protocols/p4runtime/model/src/test/resources/org/onosproject/p4runtime/model/basic.p4info
+++ b/protocols/p4runtime/model/src/test/resources/org/onosproject/p4runtime/model/basic.p4info
@@ -147,6 +147,7 @@
     id: 285259294
     name: "wcmp_control.wcmp_selector"
     alias: "wcmp_selector"
+    annotations: "@max_group_size(16)"
   }
   table_ids: 33592597
   with_selector: true