ONOS-7066 ONOS-7067 PI abstractions refactoring and P4Info model parser

Includes changes previously reviewed in #15607, #15877, and #15955.

Change-Id: Ie2ff62e415f2099832ebfe05961a879b7b188fc3
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java b/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java
index 4e0fd16..20a2d0f 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java
@@ -80,10 +80,10 @@
 import org.onosproject.net.pi.impl.CriterionTranslators.UdpPortCriterionTranslator;
 import org.onosproject.net.pi.impl.CriterionTranslators.VlanIdCriterionTranslator;
 import org.onosproject.net.pi.impl.CriterionTranslators.VlanPcpCriterionTranslator;
+import org.onosproject.net.pi.model.PiMatchFieldId;
 import org.onosproject.net.pi.model.PiMatchType;
 import org.onosproject.net.pi.runtime.PiExactFieldMatch;
 import org.onosproject.net.pi.runtime.PiFieldMatch;
-import org.onosproject.net.pi.runtime.PiHeaderFieldId;
 import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
 import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
 
@@ -140,14 +140,14 @@
     /**
      * Translates a given criterion instance to a PiFieldMatch with the given id, match type, and bit-width.
      *
-     * @param fieldId   PI header field identifier
+     * @param fieldId   PI match field identifier
      * @param criterion criterion
      * @param matchType match type
      * @param bitWidth  size of the field match in bits
      * @return a PI field match
      * @throws PiTranslationException if the criterion cannot be translated (see exception message)
      */
-    static PiFieldMatch translateCriterion(Criterion criterion, PiHeaderFieldId fieldId, PiMatchType matchType,
+    static PiFieldMatch translateCriterion(Criterion criterion, PiMatchFieldId fieldId, PiMatchType matchType,
                                            int bitWidth)
             throws PiTranslationException {
 
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java
index 0a4ffbb..6f61c3b 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java
@@ -29,22 +29,22 @@
 import org.onosproject.net.flow.instructions.PiInstruction;
 import org.onosproject.net.pi.model.PiActionModel;
 import org.onosproject.net.pi.model.PiActionParamModel;
+import org.onosproject.net.pi.model.PiMatchFieldId;
+import org.onosproject.net.pi.model.PiMatchFieldModel;
 import org.onosproject.net.pi.model.PiPipeconf;
 import org.onosproject.net.pi.model.PiPipelineInterpreter;
 import org.onosproject.net.pi.model.PiPipelineModel;
-import org.onosproject.net.pi.model.PiTableMatchFieldModel;
+import org.onosproject.net.pi.model.PiTableId;
 import org.onosproject.net.pi.model.PiTableModel;
 import org.onosproject.net.pi.runtime.PiAction;
 import org.onosproject.net.pi.runtime.PiActionParam;
 import org.onosproject.net.pi.runtime.PiExactFieldMatch;
 import org.onosproject.net.pi.runtime.PiFieldMatch;
-import org.onosproject.net.pi.runtime.PiHeaderFieldId;
 import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
 import org.onosproject.net.pi.runtime.PiMatchKey;
 import org.onosproject.net.pi.runtime.PiRangeFieldMatch;
 import org.onosproject.net.pi.runtime.PiTableAction;
 import org.onosproject.net.pi.runtime.PiTableEntry;
-import org.onosproject.net.pi.runtime.PiTableId;
 import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -128,7 +128,7 @@
                 tableEntryBuilder.withTimeout((double) rule.timeout());
             } else {
                 log.warn("Flow rule is temporary, but table '{}' doesn't support " +
-                                 "aging, translating to permanent.", tableModel.name());
+                                 "aging, translating to permanent.", tableModel.id());
             }
 
         }
@@ -159,7 +159,7 @@
 
     private static PiTableModel getTableModel(PiTableId piTableId, PiPipelineModel pipelineModel)
             throws PiTranslationException {
-        return pipelineModel.table(piTableId.toString())
+        return pipelineModel.table(piTableId)
                 .orElseThrow(() -> new PiTranslationException(format(
                         "Not such a table in pipeline model: %s", piTableId)));
     }
@@ -221,24 +221,24 @@
     private static PiTableAction checkPiAction(PiAction piAction, PiTableModel table)
             throws PiTranslationException {
         // Table supports this action?
-        PiActionModel actionModel = table.action(piAction.id().name()).orElseThrow(
+        PiActionModel actionModel = table.action(piAction.id()).orElseThrow(
                 () -> new PiTranslationException(format("Not such action '%s' for table '%s'",
-                                                        piAction.id(), table.name())));
+                                                        piAction.id(), table.id())));
 
         // Is the number of runtime parameters correct?
         if (actionModel.params().size() != piAction.parameters().size()) {
             throw new PiTranslationException(format(
                     "Wrong number of runtime parameters for action '%s', expected %d but found %d",
-                    actionModel.name(), actionModel.params().size(), piAction.parameters().size()));
+                    actionModel.id(), actionModel.params().size(), piAction.parameters().size()));
         }
 
         // Forge a new action instance with well-sized parameters.
         // The same comment as in typeCheckFieldMatch() about duplicating field match instances applies here.
         PiAction.Builder newActionBuilder = PiAction.builder().withId(piAction.id());
         for (PiActionParam param : piAction.parameters()) {
-            PiActionParamModel paramModel = actionModel.param(param.id().name())
+            PiActionParamModel paramModel = actionModel.param(param.id())
                     .orElseThrow(() -> new PiTranslationException(format(
-                            "Not such parameter '%s' for action '%s'", param.id(), actionModel.name())));
+                            "Not such parameter '%s' for action '%s'", param.id(), actionModel)));
             try {
                 newActionBuilder.withParameter(new PiActionParam(param.id(),
                                                                  fit(param.value(), paramModel.bitWidth())));
@@ -260,16 +260,16 @@
                                                                   TrafficSelector selector, PiTableModel tableModel)
             throws PiTranslationException {
 
-        Map<PiHeaderFieldId, PiFieldMatch> fieldMatches = Maps.newHashMap();
+        Map<PiMatchFieldId, PiFieldMatch> fieldMatches = Maps.newHashMap();
 
         // If present, find a PiCriterion and get its field matches as a map. Otherwise, use an empty map.
-        Map<PiHeaderFieldId, PiFieldMatch> piCriterionFields = selector.criteria().stream()
+        Map<PiMatchFieldId, PiFieldMatch> piCriterionFields = selector.criteria().stream()
                 .filter(c -> c.type().equals(PROTOCOL_INDEPENDENT))
                 .map(c -> (PiCriterion) c)
                 .findFirst()
                 .map(PiCriterion::fieldMatches)
                 .map(c -> {
-                    Map<PiHeaderFieldId, PiFieldMatch> fieldMap = Maps.newHashMap();
+                    Map<PiMatchFieldId, PiFieldMatch> fieldMap = Maps.newHashMap();
                     c.forEach(fieldMatch -> fieldMap.put(fieldMatch.fieldId(), fieldMatch));
                     return fieldMap;
                 })
@@ -277,31 +277,20 @@
 
         Set<Criterion> translatedCriteria = Sets.newHashSet();
         Set<Criterion> ignoredCriteria = Sets.newHashSet();
-        Set<PiHeaderFieldId> usedPiCriterionFields = Sets.newHashSet();
-        Set<PiHeaderFieldId> ignoredPiCriterionFields = Sets.newHashSet();
+        Set<PiMatchFieldId> usedPiCriterionFields = Sets.newHashSet();
+        Set<PiMatchFieldId> ignoredPiCriterionFields = Sets.newHashSet();
 
-        for (PiTableMatchFieldModel fieldModel : tableModel.matchFields()) {
+        for (PiMatchFieldModel fieldModel : tableModel.matchFields()) {
 
-            PiHeaderFieldId fieldId = PiHeaderFieldId.of(fieldModel.field().header().name(),
-                                                         fieldModel.field().type().name(),
-                                                         fieldModel.field().header().index());
+            PiMatchFieldId fieldId = fieldModel.id();
 
-            // FIXME: workaround until ONOS-7066 is resolved
-            if (fieldId.id().startsWith("scalars")) {
-                String newFieldId = fieldId.id()
-                        .replace("scalars.", "")
-                        .replace("_t.", ".");
-                String[] piecies = newFieldId.split("\\.");
-                fieldId = PiHeaderFieldId.of(piecies[0], piecies[1]);
-            }
-
-            int bitWidth = fieldModel.field().type().bitWidth();
+            int bitWidth = fieldModel.bitWidth();
             int fieldByteWidth = (int) Math.ceil((double) bitWidth / 8);
 
             Optional<Criterion.Type> criterionType =
                     interpreter == null
                             ? Optional.empty()
-                            : interpreter.mapPiHeaderFieldId(fieldId);
+                            : interpreter.mapPiMatchFieldId(fieldId);
 
             Criterion criterion = criterionType.map(selector::getCriterion).orElse(null);
 
@@ -378,7 +367,7 @@
         if (skippedCriteriaJoiner.length() > 0) {
             throw new PiTranslationException(format(
                     "The following criteria cannot be translated for table '%s': %s",
-                    tableModel.name(), skippedCriteriaJoiner.toString()));
+                    tableModel.id(), skippedCriteriaJoiner.toString()));
         }
 
         // Check if all fields found in PiCriterion have been used.
@@ -389,13 +378,13 @@
         if (skippedPiFieldsJoiner.length() > 0) {
             throw new PiTranslationException(format(
                     "The following PiCriterion field matches are not supported in table '%s': %s",
-                    tableModel.name(), skippedPiFieldsJoiner.toString()));
+                    tableModel.id(), skippedPiFieldsJoiner.toString()));
         }
 
         return fieldMatches.values();
     }
 
-    private static PiFieldMatch typeCheckFieldMatch(PiFieldMatch fieldMatch, PiTableMatchFieldModel fieldModel)
+    private static PiFieldMatch typeCheckFieldMatch(PiFieldMatch fieldMatch, PiMatchFieldModel fieldModel)
             throws PiTranslationException {
 
         // Check parameter type and size
@@ -405,7 +394,7 @@
                     fieldMatch.fieldId(), fieldModel.matchType().name(), fieldMatch.type().name()));
         }
 
-        int modelBitWidth = fieldModel.field().type().bitWidth();
+        int modelBitWidth = fieldModel.bitWidth();
 
         /*
         Here we try to be robust against wrong size fields with the goal of having PiCriterion independent of the
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java
index 7b798c0..a682409 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java
@@ -19,6 +19,7 @@
 import org.onosproject.net.Device;
 import org.onosproject.net.group.Group;
 import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.pi.model.PiActionGroupType;
 import org.onosproject.net.pi.model.PiPipeconf;
 import org.onosproject.net.pi.model.PiPipelineInterpreter;
 import org.onosproject.net.pi.runtime.PiAction;
@@ -64,7 +65,7 @@
 
         switch (group.type()) {
             case SELECT:
-                piActionGroupBuilder.withType(PiActionGroup.Type.SELECT);
+                piActionGroupBuilder.withType(PiActionGroupType.SELECT);
                 break;
             default:
                 throw new PiTranslationException(format("Group type %s not supported", group.type()));
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java
index aab8b40..f3270f4 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java
@@ -21,7 +21,7 @@
 import org.onosproject.net.flow.TableId;
 import org.onosproject.net.pi.model.PiPipeconf;
 import org.onosproject.net.pi.model.PiPipelineInterpreter;
-import org.onosproject.net.pi.runtime.PiTableId;
+import org.onosproject.net.pi.model.PiTableId;
 import org.onosproject.net.pi.runtime.PiTranslationService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/PiCriterionTranslatorsTest.java b/core/net/src/test/java/org/onosproject/net/pi/impl/PiCriterionTranslatorsTest.java
index 156be3a..1938c05 100644
--- a/core/net/src/test/java/org/onosproject/net/pi/impl/PiCriterionTranslatorsTest.java
+++ b/core/net/src/test/java/org/onosproject/net/pi/impl/PiCriterionTranslatorsTest.java
@@ -57,8 +57,8 @@
 import org.onosproject.net.flow.criteria.UdpPortCriterion;
 import org.onosproject.net.flow.criteria.VlanIdCriterion;
 import org.onosproject.net.flow.criteria.VlanPcpCriterion;
+import org.onosproject.net.pi.model.PiMatchFieldId;
 import org.onosproject.net.pi.runtime.PiExactFieldMatch;
-import org.onosproject.net.pi.runtime.PiHeaderFieldId;
 import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
 import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
 
@@ -67,7 +67,9 @@
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.onosproject.net.pi.impl.CriterionTranslatorHelper.translateCriterion;
-import static org.onosproject.net.pi.model.PiMatchType.*;
+import static org.onosproject.net.pi.model.PiMatchType.EXACT;
+import static org.onosproject.net.pi.model.PiMatchType.LPM;
+import static org.onosproject.net.pi.model.PiMatchType.TERNARY;
 
 /**
  * Tests for CriterionTranslators.
@@ -75,7 +77,7 @@
 public class PiCriterionTranslatorsTest {
 
     private Random random = new Random();
-    private final PiHeaderFieldId fieldId = PiHeaderFieldId.of("foo", "bar");
+    private final PiMatchFieldId fieldId = PiMatchFieldId.of("foo.bar");
 
     @Test
     public void testEthCriterion() throws Exception {
@@ -480,4 +482,4 @@
 
         assertThat(exactMatch.value().asReadOnlyBuffer().get(), is(criterion.ipEcn()));
     }
-}
\ No newline at end of file
+}
diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java b/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
index e7e3e23..d13def7 100644
--- a/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
+++ b/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
@@ -43,6 +43,7 @@
 import org.onosproject.net.group.GroupBucket;
 import org.onosproject.net.group.GroupBuckets;
 import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.pi.model.PiActionGroupType;
 import org.onosproject.net.pi.model.PiPipeconf;
 import org.onosproject.net.pi.runtime.PiAction;
 import org.onosproject.net.pi.runtime.PiActionGroup;
@@ -169,13 +170,13 @@
                 .addEqualityGroup(entry1, entry2)
                 .testEquals();
 
-        int numMatchParams = pipeconf.pipelineModel().table(TBL_TABLE0_ID.id()).get().matchFields().size();
+        int numMatchParams = pipeconf.pipelineModel().table(TBL_TABLE0_ID).get().matchFields().size();
         // parse values stored in entry1
         PiTernaryFieldMatch inPortParam = (PiTernaryFieldMatch) entry1.matchKey().fieldMatch(HDR_IN_PORT_ID).get();
         PiTernaryFieldMatch ethDstParam = (PiTernaryFieldMatch) entry1.matchKey().fieldMatch(HDR_ETH_DST_ID).get();
         PiTernaryFieldMatch ethSrcParam = (PiTernaryFieldMatch) entry1.matchKey().fieldMatch(HDR_ETH_SRC_ID).get();
         PiTernaryFieldMatch ethTypeParam = (PiTernaryFieldMatch) entry1.matchKey().fieldMatch(HDR_ETH_TYPE_ID).get();
-        Optional<Double> expectedTimeout = pipeconf.pipelineModel().table(TBL_TABLE0_ID.id()).get().supportsAging()
+        Optional<Double> expectedTimeout = pipeconf.pipelineModel().table(TBL_TABLE0_ID).get().supportsAging()
                 ? Optional.of((double) rule1.timeout()) : Optional.empty();
 
         // check that the number of parameters in the entry is the same as the number of table keys
@@ -245,7 +246,7 @@
         assertThat("Group ID must be equal",
                    piGroup1.id().id(), is(equalTo(GROUP_ID.id())));
         assertThat("Group type must be SELECT",
-                   piGroup1.type(), is(equalTo(PiActionGroup.Type.SELECT)));
+                   piGroup1.type(), is(equalTo(PiActionGroupType.SELECT)));
         assertThat("Action profile ID must be equal",
                    piGroup1.actionProfileId(), is(equalTo(ACT_PRF_WCMP_SELECTOR_ID)));