Refactored fabric PipeconfLoader to automatically build pipeconfs

Fabric.p4 is evolving in a way that will allow multiple profiles (e.g.
fabric, fabric-spgw, fabric-int, etc). Moreover, we need to support
multiple targets (e.g. BMv2, Tofino, etc.) as well as platforms
(variant of a target). Maintaining a pipeconf for each
profile/target/platform is time-consuming.

The new PipeconfLoader automatically builds pipeconfs based on the
available p4c compiler outputs available in the 'resources' directory.
This approach removes the need to maintain separate pipeconfs like
fabric-pro. Those interested in using fabric.p4 with targets other than
BMv2, will simply need to place the appropriate target/platform-specific
P4 compiler outputs in the resource directory.

Change-Id: I58d208a1837e747357373b2296cb950f13799ed6
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/PipeconfLoader.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/PipeconfLoader.java
index 4a62311..4ed38b5 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/PipeconfLoader.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/PipeconfLoader.java
@@ -16,7 +16,6 @@
 
 package org.onosproject.pipelines.fabric;
 
-import com.google.common.collect.ImmutableList;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -33,31 +32,51 @@
 import org.onosproject.p4runtime.model.P4InfoParser;
 import org.onosproject.p4runtime.model.P4InfoParserException;
 import org.onosproject.pipelines.fabric.pipeliner.FabricPipeliner;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.wiring.BundleWiring;
+import org.slf4j.Logger;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.net.URL;
 import java.util.Collection;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
-import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
-import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
+import static java.lang.String.format;
+import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType;
+import static org.osgi.framework.wiring.BundleWiring.LISTRESOURCES_RECURSE;
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
- * Pipeline config loader for fabric pipeline.
+ * Pipeconf loader for fabric.p4 which uses p4c output available in the resource
+ * path to automatically build pipeconfs for different profiles, target and
+ * platforms.
  */
 @Component(immediate = true)
 public class PipeconfLoader {
 
-    public static final PiPipeconfId FABRIC_PIPECONF_ID =
-            new PiPipeconfId("org.onosproject.pipelines.fabric");
+    // TODO: allow adding properties to pipeconf instead of adding it to driver
 
-    private static final String FABRIC_JSON_PATH = "/p4c-out/bmv2/fabric.json";
-    private static final String FABRIC_P4INFO_PATH = "/p4c-out/bmv2/fabric.p4info";
+    private static Logger log = getLogger(PipeconfLoader.class);
 
-    private static final PiPipeconf FABRIC_PIPECONF = buildFabricPipeconf();
+    private static final String BASE_PIPECONF_ID = "org.onosproject.pipelines";
 
-    // XXX: Use a collection to hold only one pipeconf because we might separate
-    // fabric pipeconf to leaf/spine pipeconf in the future.
-    private static final Collection<PiPipeconf> ALL_PIPECONFS =
-            ImmutableList.of(FABRIC_PIPECONF);
+    private static final String P4C_OUT_PATH = "/p4c-out";
+
+    // profile/target/platform
+    private static final String P4C_RES_BASE_PATH = P4C_OUT_PATH + "/%s/%s/%s/";
+
+    private static final String SEP = File.separator;
+    private static final String TOFINO = "tofino";
+    private static final String BMV2 = "bmv2";
+    private static final String DEFAULT_PLATFORM = "default";
+    private static final String BMV2_JSON = "bmv2.json";
+    private static final String P4INFO_TXT = "p4info.txt";
+    private static final String TOFINO_BIN = "tofino.bin";
+    private static final String TOFINO_CTX_JSON = "context.json";
+
+    private static final Collection<PiPipeconf> PIPECONFS = buildAllPipeconf();
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     private PiPipeconfService piPipeconfService;
@@ -65,30 +84,107 @@
     @Activate
     public void activate() {
         // Registers all pipeconf at component activation.
-        ALL_PIPECONFS.forEach(piPipeconfService::register);
+        PIPECONFS.forEach(piPipeconfService::register);
     }
 
     @Deactivate
     public void deactivate() {
-        ALL_PIPECONFS.stream().map(PiPipeconf::id).forEach(piPipeconfService::remove);
+        PIPECONFS.stream().map(PiPipeconf::id).forEach(piPipeconfService::remove);
     }
 
-    private static PiPipeconf buildFabricPipeconf() {
-        final URL jsonUrl = PipeconfLoader.class.getResource(FABRIC_JSON_PATH);
-        final URL p4InfoUrl = PipeconfLoader.class.getResource(FABRIC_P4INFO_PATH);
-        final PiPipelineModel model = parseP4Info(p4InfoUrl);
-        // TODO: add properties to pipeconf instead of adding it to driver
-        return DefaultPiPipeconf.builder()
-                .withId(FABRIC_PIPECONF_ID)
-                .withPipelineModel(model)
-                .addBehaviour(PiPipelineInterpreter.class, FabricInterpreter.class)
-                .addBehaviour(Pipeliner.class, FabricPipeliner.class)
-                .addBehaviour(PortStatisticsDiscovery.class, FabricPortStatisticsDiscovery.class)
-                .addExtension(P4_INFO_TEXT, p4InfoUrl)
-                .addExtension(BMV2_JSON, jsonUrl)
+    private static Collection<PiPipeconf> buildAllPipeconf() {
+        return FrameworkUtil
+                .getBundle(PipeconfLoader.class)
+                .adapt(BundleWiring.class)
+                // List all resource files in /p4c-out
+                .listResources(P4C_OUT_PATH, "*", LISTRESOURCES_RECURSE)
+                .stream()
+                // Filter only directories
+                .filter(name -> name.endsWith(SEP))
+                // Derive profile, target, and platform and build pipeconf.
+                .map(PipeconfLoader::buildPipeconfFromPath)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+    }
+
+    private static PiPipeconf buildPipeconfFromPath(String path) {
+        String[] pieces = path.split(SEP);
+        // We expect a path of 4 elements, e.g.
+        // p4c-out/<profile>/<target>/<platform>
+        if (pieces.length != 4) {
+            return null;
+        }
+        String profile = pieces[1];
+        String target = pieces[2];
+        String platform = pieces[3];
+        try {
+            switch (target) {
+                case BMV2:
+                    return buildBmv2Pipeconf(profile, platform);
+                case TOFINO:
+                    return buildTofinoPipeconf(profile, platform);
+                default:
+                    log.warn("Unknown target '{}', skipping pipeconf build...",
+                             target);
+                    return null;
+            }
+        } catch (FileNotFoundException e) {
+            log.warn("Unable to build pipeconf at {} because one or more p4c outputs are missing",
+                     path);
+            return null;
+        }
+    }
+
+    private static PiPipeconf buildBmv2Pipeconf(String profile, String platform)
+            throws FileNotFoundException {
+        final URL bmv2JsonUrl = PipeconfLoader.class.getResource(format(
+                P4C_RES_BASE_PATH + BMV2_JSON, profile, BMV2, platform));
+        final URL p4InfoUrl = PipeconfLoader.class.getResource(format(
+                P4C_RES_BASE_PATH + P4INFO_TXT, profile, BMV2, platform));
+        if (bmv2JsonUrl == null || p4InfoUrl == null) {
+            throw new FileNotFoundException();
+        }
+        return basePipeconfBuilder(profile, platform, p4InfoUrl)
+                .addExtension(ExtensionType.BMV2_JSON, bmv2JsonUrl)
                 .build();
     }
 
+    private static PiPipeconf buildTofinoPipeconf(String profile, String platform)
+            throws FileNotFoundException {
+        final URL tofinoBinUrl = PipeconfLoader.class.getResource(format(
+                P4C_RES_BASE_PATH + TOFINO_BIN, profile, TOFINO, platform));
+        final URL contextJsonUrl = PipeconfLoader.class.getResource(format(
+                P4C_RES_BASE_PATH + TOFINO_CTX_JSON, profile, TOFINO, platform));
+        final URL p4InfoUrl = PipeconfLoader.class.getResource(format(
+                P4C_RES_BASE_PATH + P4INFO_TXT, profile, TOFINO, platform));
+        if (tofinoBinUrl == null || contextJsonUrl == null || p4InfoUrl == null) {
+            throw new FileNotFoundException();
+        }
+        return basePipeconfBuilder(profile, platform, p4InfoUrl)
+                .addExtension(ExtensionType.TOFINO_BIN, tofinoBinUrl)
+                .addExtension(ExtensionType.TOFINO_CONTEXT_JSON, contextJsonUrl)
+                .build();
+    }
+
+    private static DefaultPiPipeconf.Builder basePipeconfBuilder(
+            String profile, String platform, URL p4InfoUrl) {
+        final String pipeconfId = platform.equals(DEFAULT_PLATFORM)
+                // Omit platform if default, e.g. with BMv2 pipeconf
+                ? format("%s.%s", BASE_PIPECONF_ID, profile)
+                : format("%s.%s.%s", BASE_PIPECONF_ID, profile, platform);
+        final PiPipelineModel model = parseP4Info(p4InfoUrl);
+        return DefaultPiPipeconf.builder()
+                .withId(new PiPipeconfId(pipeconfId))
+                .withPipelineModel(model)
+                .addBehaviour(PiPipelineInterpreter.class,
+                              FabricInterpreter.class)
+                .addBehaviour(Pipeliner.class,
+                              FabricPipeliner.class)
+                .addBehaviour(PortStatisticsDiscovery.class,
+                              FabricPortStatisticsDiscovery.class)
+                .addExtension(ExtensionType.P4_INFO_TEXT, p4InfoUrl);
+    }
+
     private static PiPipelineModel parseP4Info(URL p4InfoUrl) {
         try {
             return P4InfoParser.parse(p4InfoUrl);
diff --git a/pipelines/fabric/src/main/resources/.gitignore b/pipelines/fabric/src/main/resources/.gitignore
new file mode 100644
index 0000000..4832ef2
--- /dev/null
+++ b/pipelines/fabric/src/main/resources/.gitignore
@@ -0,0 +1 @@
+p4c-out/*/tofino
diff --git a/pipelines/fabric/src/main/resources/Makefile b/pipelines/fabric/src/main/resources/Makefile
index c3016f8..0528576 100644
--- a/pipelines/fabric/src/main/resources/Makefile
+++ b/pipelines/fabric/src/main/resources/Makefile
@@ -1,23 +1,10 @@
-BMV2_CPU_PORT=255
+all: fabric fabric-spgw
 
-BMV2_OPTIONS=-DTARGET_BMV2 -DCPU_PORT=$(BMV2_CPU_PORT)
+fabric:
+	@./bmv2-compile.sh "fabric" ""
 
-all: bmv2 bmv2-spgw
-
-bmv2: makedir
-	p4c-bm2-ss --arch v1model -o p4c-out/bmv2/fabric.json \
-		$(BMV2_OPTIONS) \
-		--p4runtime-file p4c-out/bmv2/fabric.p4info \
-		--p4runtime-format text fabric.p4
-
-bmv2-spgw: makedir
-	p4c-bm2-ss --arch v1model -o p4c-out/bmv2/fabric-spgw.json \
-		$(BMV2_OPTIONS) -DWITH_SPGW \
-		--p4runtime-file p4c-out/bmv2/fabric-spgw.p4info \
-		--p4runtime-format text fabric.p4
-
-makedir:
-	mkdir -p p4c-out/bmv2
+fabric-spgw:
+	@./bmv2-compile.sh "fabric-spgw" "-DWITH_SPGW"
 
 clean:
-	rm -rf p4c-out/bmv2/*
+	rm -rf p4c-out/*/bmv2
diff --git a/pipelines/fabric/src/main/resources/bmv2-compile.sh b/pipelines/fabric/src/main/resources/bmv2-compile.sh
new file mode 100755
index 0000000..d92a5c4
--- /dev/null
+++ b/pipelines/fabric/src/main/resources/bmv2-compile.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -ex
+
+BMV2_CPU_PORT="255"
+BMV2_PP_FLAGS="-DTARGET_BMV2 -DCPU_PORT=${BMV2_CPU_PORT}"
+
+PROFILE=$1
+OTHER_PP_FLAGS=$2
+
+OUT_DIR=./p4c-out/${PROFILE}/bmv2/default
+
+mkdir -p ${OUT_DIR}
+
+p4c-bm2-ss --arch v1model \
+        -o ${OUT_DIR}/bmv2.json \
+        ${BMV2_PP_FLAGS} ${OTHER_PP_FLAGS} \
+        --p4runtime-file ${OUT_DIR}/p4info.txt \
+        --p4runtime-format text \
+        fabric.p4
diff --git a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.json b/pipelines/fabric/src/main/resources/p4c-out/fabric-spgw/bmv2/default/bmv2.json
similarity index 98%
rename from pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.json
rename to pipelines/fabric/src/main/resources/p4c-out/fabric-spgw/bmv2/default/bmv2.json
index 6db1e8c..f3439fe 100644
--- a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.json
+++ b/pipelines/fabric/src/main/resources/p4c-out/fabric-spgw/bmv2/default/bmv2.json
@@ -1512,7 +1512,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 32,
+            "line" : 66,
             "column" : 31,
             "source_fragment" : "0x8100; ..."
           }
@@ -2258,7 +2258,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 33,
+            "line" : 67,
             "column" : 31,
             "source_fragment" : "0x8847; ..."
           }
@@ -2334,7 +2334,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 67,
+            "line" : 87,
             "column" : 32,
             "source_fragment" : "64; ..."
           }
@@ -2449,7 +2449,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 33,
+            "line" : 67,
             "column" : 31,
             "source_fragment" : "0x8847; ..."
           }
@@ -2525,7 +2525,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 67,
+            "line" : 87,
             "column" : 32,
             "source_fragment" : "64; ..."
           }
@@ -2640,7 +2640,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 33,
+            "line" : 67,
             "column" : 31,
             "source_fragment" : "0x8847; ..."
           }
@@ -2716,7 +2716,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 67,
+            "line" : 87,
             "column" : 32,
             "source_fragment" : "64; ..."
           }
@@ -2955,7 +2955,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 88,
+            "line" : 98,
             "column" : 31,
             "source_fragment" : "1w0; ..."
           }
@@ -3070,7 +3070,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 89,
+            "line" : 99,
             "column" : 33,
             "source_fragment" : "1w1; ..."
           }
@@ -3121,7 +3121,7 @@
                   "left" : null,
                   "right" : {
                     "type" : "bool",
-                    "value" : false
+                    "value" : true
                   }
                 }
               }
@@ -3131,7 +3131,7 @@
             "filename" : "include/spgw.p4",
             "line" : 146,
             "column" : 8,
-            "source_fragment" : "spgw_meta.do_spgw = false"
+            "source_fragment" : "spgw_meta.do_spgw = true"
           }
         }
       ]
@@ -3277,7 +3277,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 35,
+            "line" : 69,
             "column" : 31,
             "source_fragment" : "0x0800; ..."
           }
@@ -3296,7 +3296,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 35,
+            "line" : 69,
             "column" : 31,
             "source_fragment" : "0x0800; ..."
           }
@@ -3587,7 +3587,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 54,
+            "line" : 78,
             "column" : 28,
             "source_fragment" : "5; ..."
           }
@@ -3724,7 +3724,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 78,
+            "line" : 88,
             "column" : 32,
             "source_fragment" : "64; ..."
           }
@@ -3743,7 +3743,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 51,
+            "line" : 75,
             "column" : 25,
             "source_fragment" : "17; ..."
           }
@@ -5476,14 +5476,13 @@
             "filename" : "include/spgw.p4",
             "line" : 167,
             "column" : 12,
-            "source_fragment" : "!spgw_meta.do_spgw"
+            "source_fragment" : "spgw_meta.do_spgw == true"
           },
           "expression" : {
             "type" : "expression",
             "value" : {
-              "op" : "not",
-              "left" : null,
-              "right" : {
+              "op" : "==",
+              "left" : {
                 "type" : "expression",
                 "value" : {
                   "op" : "d2b",
@@ -5493,6 +5492,10 @@
                     "value" : ["userMetadata.spgw", "do_spgw"]
                   }
                 }
+              },
+              "right" : {
+                "type" : "bool",
+                "value" : true
               }
             }
           },
@@ -5989,7 +5992,7 @@
             "filename" : "include/control/packetio.p4",
             "line" : 43,
             "column" : 16,
-            "source_fragment" : "hdr.vlan_tag.isValid() && fabric_metadata.pop_vlan_when_packet_in"
+            "source_fragment" : "hdr.vlan_tag.isValid() && fabric_metadata.pop_vlan_when_packet_in == true"
           },
           "expression" : {
             "type" : "expression",
@@ -6009,11 +6012,21 @@
               "right" : {
                 "type" : "expression",
                 "value" : {
-                  "op" : "d2b",
-                  "left" : null,
+                  "op" : "==",
+                  "left" : {
+                    "type" : "expression",
+                    "value" : {
+                      "op" : "d2b",
+                      "left" : null,
+                      "right" : {
+                        "type" : "field",
+                        "value" : ["scalars", "fabric_metadata_t.pop_vlan_when_packet_in"]
+                      }
+                    }
+                  },
                   "right" : {
-                    "type" : "field",
-                    "value" : ["scalars", "fabric_metadata_t.pop_vlan_when_packet_in"]
+                    "type" : "bool",
+                    "value" : true
                   }
                 }
               }
@@ -6029,7 +6042,7 @@
             "filename" : "include/spgw.p4",
             "line" : 249,
             "column" : 12,
-            "source_fragment" : "spgw_meta.do_spgw && spgw_meta.direction == DIR_DOWNLINK"
+            "source_fragment" : "spgw_meta.do_spgw == true && spgw_meta.direction == DIR_DOWNLINK"
           },
           "expression" : {
             "type" : "expression",
@@ -6038,11 +6051,21 @@
               "left" : {
                 "type" : "expression",
                 "value" : {
-                  "op" : "d2b",
-                  "left" : null,
+                  "op" : "==",
+                  "left" : {
+                    "type" : "expression",
+                    "value" : {
+                      "op" : "d2b",
+                      "left" : null,
+                      "right" : {
+                        "type" : "field",
+                        "value" : ["userMetadata.spgw", "do_spgw"]
+                      }
+                    }
+                  },
                   "right" : {
-                    "type" : "field",
-                    "value" : ["userMetadata.spgw", "do_spgw"]
+                    "type" : "bool",
+                    "value" : true
                   }
                 }
               },
diff --git a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.p4info b/pipelines/fabric/src/main/resources/p4c-out/fabric-spgw/bmv2/default/p4info.txt
similarity index 100%
rename from pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.p4info
rename to pipelines/fabric/src/main/resources/p4c-out/fabric-spgw/bmv2/default/p4info.txt
diff --git a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.json b/pipelines/fabric/src/main/resources/p4c-out/fabric/bmv2/default/bmv2.json
similarity index 98%
rename from pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.json
rename to pipelines/fabric/src/main/resources/p4c-out/fabric/bmv2/default/bmv2.json
index 8aad592..52fab79 100644
--- a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.json
+++ b/pipelines/fabric/src/main/resources/p4c-out/fabric/bmv2/default/bmv2.json
@@ -1088,7 +1088,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 32,
+            "line" : 66,
             "column" : 31,
             "source_fragment" : "0x8100; ..."
           }
@@ -1834,7 +1834,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 33,
+            "line" : 67,
             "column" : 31,
             "source_fragment" : "0x8847; ..."
           }
@@ -1910,7 +1910,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 67,
+            "line" : 87,
             "column" : 32,
             "source_fragment" : "64; ..."
           }
@@ -2025,7 +2025,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 33,
+            "line" : 67,
             "column" : 31,
             "source_fragment" : "0x8847; ..."
           }
@@ -2101,7 +2101,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 67,
+            "line" : 87,
             "column" : 32,
             "source_fragment" : "64; ..."
           }
@@ -2216,7 +2216,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 33,
+            "line" : 67,
             "column" : 31,
             "source_fragment" : "0x8847; ..."
           }
@@ -2292,7 +2292,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 67,
+            "line" : 87,
             "column" : 32,
             "source_fragment" : "64; ..."
           }
@@ -2359,7 +2359,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 35,
+            "line" : 69,
             "column" : 31,
             "source_fragment" : "0x0800; ..."
           }
@@ -2378,7 +2378,7 @@
           ],
           "source_info" : {
             "filename" : "include/control/../define.p4",
-            "line" : 35,
+            "line" : 69,
             "column" : 31,
             "source_fragment" : "0x0800; ..."
           }
@@ -3737,7 +3737,7 @@
             "filename" : "include/control/packetio.p4",
             "line" : 43,
             "column" : 16,
-            "source_fragment" : "hdr.vlan_tag.isValid() && fabric_metadata.pop_vlan_when_packet_in"
+            "source_fragment" : "hdr.vlan_tag.isValid() && fabric_metadata.pop_vlan_when_packet_in == true"
           },
           "expression" : {
             "type" : "expression",
@@ -3757,11 +3757,21 @@
               "right" : {
                 "type" : "expression",
                 "value" : {
-                  "op" : "d2b",
-                  "left" : null,
+                  "op" : "==",
+                  "left" : {
+                    "type" : "expression",
+                    "value" : {
+                      "op" : "d2b",
+                      "left" : null,
+                      "right" : {
+                        "type" : "field",
+                        "value" : ["scalars", "fabric_metadata_t.pop_vlan_when_packet_in"]
+                      }
+                    }
+                  },
                   "right" : {
-                    "type" : "field",
-                    "value" : ["scalars", "fabric_metadata_t.pop_vlan_when_packet_in"]
+                    "type" : "bool",
+                    "value" : true
                   }
                 }
               }
diff --git a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.p4info b/pipelines/fabric/src/main/resources/p4c-out/fabric/bmv2/default/p4info.txt
similarity index 100%
rename from pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.p4info
rename to pipelines/fabric/src/main/resources/p4c-out/fabric/bmv2/default/p4info.txt