Removed hardcoded model from BMv2 driver
Now it uses the model stored in device annotations. Also refactored flow
rule translator classes to reflect this change.
Change-Id: I46541bcc2ab5a267eef4becb6250b9a99684056a
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleProgrammable.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleProgrammable.java
index 082d1d6..e530235 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleProgrammable.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleProgrammable.java
@@ -16,10 +16,15 @@
package org.onosproject.drivers.bmv2;
+import com.eclipsesource.json.Json;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
+import org.onosproject.bmv2.api.model.Bmv2Model;
import org.onosproject.bmv2.api.runtime.Bmv2Client;
import org.onosproject.bmv2.api.runtime.Bmv2MatchKey;
import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
@@ -28,7 +33,10 @@
import org.onosproject.drivers.bmv2.translators.Bmv2DefaultFlowRuleTranslator;
import org.onosproject.drivers.bmv2.translators.Bmv2FlowRuleTranslator;
import org.onosproject.drivers.bmv2.translators.Bmv2FlowRuleTranslatorException;
+import org.onosproject.drivers.bmv2.translators.Bmv2SimpleTranslatorConfig;
+import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.FlowEntry;
@@ -41,6 +49,8 @@
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
/**
* Flow rule programmable device behaviour implementation for BMv2.
@@ -50,10 +60,21 @@
private static final Logger LOG =
LoggerFactory.getLogger(Bmv2FlowRuleProgrammable.class);
- // There's no Bmv2 client method to poll flow entries from the device device. gitNeed a local store.
+
+ // There's no Bmv2 client method to poll flow entries from the device device. Need a local store.
private static final ConcurrentMap<Triple<DeviceId, String, Bmv2MatchKey>, Pair<Long, FlowEntry>>
ENTRIES_MAP = Maps.newConcurrentMap();
- private static final Bmv2FlowRuleTranslator TRANSLATOR = new Bmv2DefaultFlowRuleTranslator();
+
+ // Cache model objects instead of parsing the JSON each time.
+ private static final LoadingCache<String, Bmv2Model> MODEL_CACHE = CacheBuilder.newBuilder()
+ .expireAfterAccess(60, TimeUnit.SECONDS)
+ .build(new CacheLoader<String, Bmv2Model>() {
+ @Override
+ public Bmv2Model load(String jsonString) throws Exception {
+ // Expensive call.
+ return Bmv2Model.parse(Json.parse(jsonString).asObject());
+ }
+ });
@Override
public Collection<FlowEntry> getFlowEntries() {
@@ -96,6 +117,8 @@
return Collections.emptyList();
}
+ Bmv2FlowRuleTranslator translator = getTranslator(deviceId);
+
List<FlowRule> processedFlowRules = Lists.newArrayList();
for (FlowRule rule : rules) {
@@ -103,7 +126,7 @@
Bmv2TableEntry bmv2Entry;
try {
- bmv2Entry = TRANSLATOR.translate(rule);
+ bmv2Entry = translator.translate(rule);
} catch (Bmv2FlowRuleTranslatorException e) {
LOG.error("Unable to translate flow rule: {}", e.getMessage());
continue;
@@ -159,6 +182,46 @@
return processedFlowRules;
}
+ /**
+ * Gets the appropriate flow rule translator based on the device running configuration.
+ *
+ * @param deviceId a device id
+ * @return a flow rule translator
+ */
+ private Bmv2FlowRuleTranslator getTranslator(DeviceId deviceId) {
+
+ DeviceService deviceService = handler().get(DeviceService.class);
+ if (deviceService == null) {
+ LOG.error("Unable to get device service");
+ return null;
+ }
+
+ Device device = deviceService.getDevice(deviceId);
+ if (device == null) {
+ LOG.error("Unable to get device {}", deviceId);
+ return null;
+ }
+
+ String jsonString = device.annotations().value("bmv2JsonConfigValue");
+ if (jsonString == null) {
+ LOG.error("Unable to read bmv2 JSON config from device {}", deviceId);
+ return null;
+ }
+
+ Bmv2Model model;
+ try {
+ model = MODEL_CACHE.get(jsonString);
+ } catch (ExecutionException e) {
+ LOG.error("Unable to parse bmv2 JSON config for device {}:", deviceId, e.getCause());
+ return null;
+ }
+
+ // TODO: get translator config dynamically.
+ // Now it's hardcoded, selection should be based on the device bmv2 model.
+ Bmv2FlowRuleTranslator.TranslatorConfig translatorConfig = new Bmv2SimpleTranslatorConfig(model);
+ return new Bmv2DefaultFlowRuleTranslator(translatorConfig);
+ }
+
private enum Operation {
APPLY, REMOVE
}
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2DefaultFlowRuleTranslator.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2DefaultFlowRuleTranslator.java
index a54a3c8..170e955 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2DefaultFlowRuleTranslator.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2DefaultFlowRuleTranslator.java
@@ -18,7 +18,6 @@
import com.google.common.annotations.Beta;
import org.onlab.util.ImmutableByteSequence;
-import org.onosproject.bmv2.api.model.Bmv2Model;
import org.onosproject.bmv2.api.model.Bmv2ModelField;
import org.onosproject.bmv2.api.model.Bmv2ModelTable;
import org.onosproject.bmv2.api.model.Bmv2ModelTableKey;
@@ -66,9 +65,11 @@
@Beta
public class Bmv2DefaultFlowRuleTranslator implements Bmv2FlowRuleTranslator {
- // TODO: config is harcoded now, instead it should be selected based on device model
- private final TranslatorConfig config = new Bmv2SimpleTranslatorConfig();
- private final Bmv2Model model = config.model();
+ private final TranslatorConfig config;
+
+ public Bmv2DefaultFlowRuleTranslator(TranslatorConfig config) {
+ this.config = config;
+ }
private static Bmv2TernaryMatchParam buildTernaryParam(Bmv2ModelField field, Criterion criterion, int byteWidth)
throws Bmv2FlowRuleTranslatorException {
@@ -201,7 +202,7 @@
int tableId = rule.tableId();
- Bmv2ModelTable table = model.table(tableId);
+ Bmv2ModelTable table = config.model().table(tableId);
if (table == null) {
throw new Bmv2FlowRuleTranslatorException("Unknown table ID: " + tableId);
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2DefaultTranslatorConfig.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2DefaultTranslatorConfig.java
new file mode 100644
index 0000000..dc7bdcd
--- /dev/null
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2DefaultTranslatorConfig.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.bmv2.translators;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.bmv2.api.model.Bmv2Model;
+import org.onosproject.net.flow.criteria.Criterion;
+
+import java.util.Map;
+
+import static org.onosproject.drivers.bmv2.translators.Bmv2FlowRuleTranslator.TranslatorConfig;
+
+/**
+ * Default implementation of a BMv2 flow rule translator configuration.
+ */
+@Beta
+public abstract class Bmv2DefaultTranslatorConfig implements TranslatorConfig {
+
+ private final Bmv2Model model;
+ private final Map<String, Criterion.Type> fieldMap;
+
+ /**
+ * Creates a new translator configuration.
+ *
+ * @param model a BMv2 packet processing model
+ * @param fieldMap a field-to-criterion type map
+ */
+ protected Bmv2DefaultTranslatorConfig(Bmv2Model model, Map<String, Criterion.Type> fieldMap) {
+ this.model = model;
+ this.fieldMap = fieldMap;
+ }
+
+ @Override
+ public Bmv2Model model() {
+ return this.model;
+ }
+
+ @Override
+ public Map<String, Criterion.Type> fieldToCriterionTypeMap() {
+ return this.fieldMap;
+ }
+}
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2SimpleTranslatorConfig.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2SimpleTranslatorConfig.java
index 565c1e4..4a105a3 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2SimpleTranslatorConfig.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2SimpleTranslatorConfig.java
@@ -16,10 +16,8 @@
package org.onosproject.drivers.bmv2.translators;
-import com.eclipsesource.json.Json;
-import com.eclipsesource.json.JsonObject;
import com.google.common.annotations.Beta;
-import com.google.common.collect.Maps;
+import com.google.common.collect.ImmutableMap;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.bmv2.api.model.Bmv2Model;
import org.onosproject.bmv2.api.runtime.Bmv2Action;
@@ -29,10 +27,6 @@
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.util.Map;
/**
@@ -40,24 +34,21 @@
* simple.p4 model.
*/
@Beta
-public class Bmv2SimpleTranslatorConfig implements Bmv2FlowRuleTranslator.TranslatorConfig {
+public class Bmv2SimpleTranslatorConfig extends Bmv2DefaultTranslatorConfig {
- private static final String JSON_CONFIG_PATH = "/simple.json";
- private final Map<String, Criterion.Type> fieldMap = Maps.newHashMap();
- private final Bmv2Model model;
+ // Lazily populate field map.
+ private static final Map<String, Criterion.Type> FIELD_MAP = ImmutableMap.of(
+ "standard_metadata.ingress_port", Criterion.Type.IN_PORT,
+ "ethernet.dstAddr", Criterion.Type.ETH_DST,
+ "ethernet.srcAddr", Criterion.Type.ETH_SRC,
+ "ethernet.etherType", Criterion.Type.ETH_TYPE);
/**
* Creates a new simple pipeline translator configuration.
*/
- public Bmv2SimpleTranslatorConfig() {
-
- this.model = getModel();
-
- // populate fieldMap
- fieldMap.put("standard_metadata.ingress_port", Criterion.Type.IN_PORT);
- fieldMap.put("ethernet.dstAddr", Criterion.Type.ETH_DST);
- fieldMap.put("ethernet.srcAddr", Criterion.Type.ETH_SRC);
- fieldMap.put("ethernet.etherType", Criterion.Type.ETH_TYPE);
+ public Bmv2SimpleTranslatorConfig(Bmv2Model model) {
+ // Populate fieldMap.
+ super(model, FIELD_MAP);
}
private static Bmv2Action buildDropAction() {
@@ -94,41 +85,16 @@
return actionBuilder.build();
}
- private static Bmv2Model getModel() {
- InputStream inputStream = Bmv2SimpleTranslatorConfig.class
- .getResourceAsStream(JSON_CONFIG_PATH);
- InputStreamReader reader = new InputStreamReader(inputStream);
- BufferedReader bufReader = new BufferedReader(reader);
- JsonObject json = null;
- try {
- json = Json.parse(bufReader).asObject();
- } catch (IOException e) {
- throw new RuntimeException("Unable to parse JSON file: " + e.getMessage());
- }
-
- return Bmv2Model.parse(json);
- }
-
- @Override
- public Bmv2Model model() {
- return this.model;
- }
-
- @Override
- public Map<String, Criterion.Type> fieldToCriterionTypeMap() {
- return fieldMap;
- }
-
@Override
public Bmv2Action buildAction(TrafficTreatment treatment)
throws Bmv2FlowRuleTranslatorException {
if (treatment.allInstructions().size() == 0) {
- // no instructions means drop
+ // No instructions means drop.
return buildDropAction();
} else if (treatment.allInstructions().size() > 1) {
- // otherwise, we understand treatments with only 1 instruction
+ // Otherwise, we understand treatments with only 1 instruction.
throw new Bmv2FlowRuleTranslatorException(
"Treatment not supported, more than 1 instructions found: "
+ treatment.toString());
diff --git a/drivers/bmv2/src/main/resources/simple.json b/drivers/bmv2/src/main/resources/simple.json
deleted file mode 100644
index f6e6752..0000000
--- a/drivers/bmv2/src/main/resources/simple.json
+++ /dev/null
@@ -1,397 +0,0 @@
-{
- "header_types": [
- {
- "name": "standard_metadata_t",
- "id": 0,
- "fields": [
- [
- "ingress_port",
- 9
- ],
- [
- "packet_length",
- 32
- ],
- [
- "egress_spec",
- 9
- ],
- [
- "egress_port",
- 9
- ],
- [
- "egress_instance",
- 32
- ],
- [
- "instance_type",
- 32
- ],
- [
- "clone_spec",
- 32
- ],
- [
- "_padding",
- 5
- ]
- ],
- "length_exp": null,
- "max_length": null
- },
- {
- "name": "ethernet_t",
- "id": 1,
- "fields": [
- [
- "dstAddr",
- 48
- ],
- [
- "srcAddr",
- 48
- ],
- [
- "etherType",
- 16
- ]
- ],
- "length_exp": null,
- "max_length": null
- },
- {
- "name": "intrinsic_metadata_t",
- "id": 2,
- "fields": [
- [
- "ingress_global_timestamp",
- 32
- ],
- [
- "lf_field_list",
- 32
- ],
- [
- "mcast_grp",
- 16
- ],
- [
- "egress_rid",
- 16
- ]
- ],
- "length_exp": null,
- "max_length": null
- }
- ],
- "headers": [
- {
- "name": "standard_metadata",
- "id": 0,
- "header_type": "standard_metadata_t",
- "metadata": true
- },
- {
- "name": "ethernet",
- "id": 1,
- "header_type": "ethernet_t",
- "metadata": false
- },
- {
- "name": "intrinsic_metadata",
- "id": 2,
- "header_type": "intrinsic_metadata_t",
- "metadata": true
- }
- ],
- "header_stacks": [],
- "parsers": [
- {
- "name": "parser",
- "id": 0,
- "init_state": "start",
- "parse_states": [
- {
- "name": "start",
- "id": 0,
- "parser_ops": [],
- "transition_key": [],
- "transitions": [
- {
- "value": "default",
- "mask": null,
- "next_state": "parse_ethernet"
- }
- ]
- },
- {
- "name": "parse_ethernet",
- "id": 1,
- "parser_ops": [
- {
- "op": "extract",
- "parameters": [
- {
- "type": "regular",
- "value": "ethernet"
- }
- ]
- }
- ],
- "transition_key": [],
- "transitions": [
- {
- "value": "default",
- "mask": null,
- "next_state": null
- }
- ]
- }
- ]
- }
- ],
- "deparsers": [
- {
- "name": "deparser",
- "id": 0,
- "order": [
- "ethernet"
- ]
- }
- ],
- "meter_arrays": [],
- "actions": [
- {
- "name": "flood",
- "id": 0,
- "runtime_data": [],
- "primitives": [
- {
- "op": "modify_field",
- "parameters": [
- {
- "type": "field",
- "value": [
- "intrinsic_metadata",
- "mcast_grp"
- ]
- },
- {
- "type": "field",
- "value": [
- "standard_metadata",
- "ingress_port"
- ]
- }
- ]
- }
- ]
- },
- {
- "name": "_drop",
- "id": 1,
- "runtime_data": [],
- "primitives": [
- {
- "op": "modify_field",
- "parameters": [
- {
- "type": "field",
- "value": [
- "standard_metadata",
- "egress_spec"
- ]
- },
- {
- "type": "hexstr",
- "value": "0x1ff"
- }
- ]
- }
- ]
- },
- {
- "name": "fwd",
- "id": 2,
- "runtime_data": [
- {
- "name": "port",
- "bitwidth": 9
- }
- ],
- "primitives": [
- {
- "op": "modify_field",
- "parameters": [
- {
- "type": "field",
- "value": [
- "standard_metadata",
- "egress_spec"
- ]
- },
- {
- "type": "runtime_data",
- "value": 0
- }
- ]
- }
- ]
- },
- {
- "name": "send_to_cpu",
- "id": 3,
- "runtime_data": [],
- "primitives": [
- {
- "op": "modify_field",
- "parameters": [
- {
- "type": "field",
- "value": [
- "standard_metadata",
- "egress_spec"
- ]
- },
- {
- "type": "hexstr",
- "value": "0xff"
- }
- ]
- }
- ]
- }
- ],
- "pipelines": [
- {
- "name": "ingress",
- "id": 0,
- "init_table": "table0",
- "tables": [
- {
- "name": "table0",
- "id": 0,
- "match_type": "ternary",
- "type": "simple",
- "max_size": 16384,
- "with_counters": false,
- "direct_meters": null,
- "support_timeout": false,
- "key": [
- {
- "match_type": "ternary",
- "target": [
- "standard_metadata",
- "ingress_port"
- ],
- "mask": null
- },
- {
- "match_type": "ternary",
- "target": [
- "ethernet",
- "dstAddr"
- ],
- "mask": null
- },
- {
- "match_type": "ternary",
- "target": [
- "ethernet",
- "srcAddr"
- ],
- "mask": null
- },
- {
- "match_type": "ternary",
- "target": [
- "ethernet",
- "etherType"
- ],
- "mask": null
- }
- ],
- "actions": [
- "fwd",
- "flood",
- "send_to_cpu",
- "_drop"
- ],
- "next_tables": {
- "fwd": null,
- "flood": null,
- "send_to_cpu": null,
- "_drop": null
- },
- "default_action": null,
- "base_default_next": null
- }
- ],
- "conditionals": []
- },
- {
- "name": "egress",
- "id": 1,
- "init_table": null,
- "tables": [],
- "conditionals": []
- }
- ],
- "calculations": [],
- "checksums": [],
- "learn_lists": [],
- "field_lists": [],
- "counter_arrays": [],
- "register_arrays": [],
- "force_arith": [
- [
- "standard_metadata",
- "ingress_port"
- ],
- [
- "standard_metadata",
- "packet_length"
- ],
- [
- "standard_metadata",
- "egress_spec"
- ],
- [
- "standard_metadata",
- "egress_port"
- ],
- [
- "standard_metadata",
- "egress_instance"
- ],
- [
- "standard_metadata",
- "instance_type"
- ],
- [
- "standard_metadata",
- "clone_spec"
- ],
- [
- "standard_metadata",
- "_padding"
- ],
- [
- "intrinsic_metadata",
- "ingress_global_timestamp"
- ],
- [
- "intrinsic_metadata",
- "lf_field_list"
- ],
- [
- "intrinsic_metadata",
- "mcast_grp"
- ],
- [
- "intrinsic_metadata",
- "egress_rid"
- ]
- ]
-}
\ No newline at end of file
diff --git a/drivers/bmv2/src/test/java/org/onosproject/drivers/bmv2/Bmv2DefaultFlowRuleTranslatorTest.java b/drivers/bmv2/src/test/java/org/onosproject/drivers/bmv2/Bmv2DefaultFlowRuleTranslatorTest.java
index 7b1b215..2f19696 100644
--- a/drivers/bmv2/src/test/java/org/onosproject/drivers/bmv2/Bmv2DefaultFlowRuleTranslatorTest.java
+++ b/drivers/bmv2/src/test/java/org/onosproject/drivers/bmv2/Bmv2DefaultFlowRuleTranslatorTest.java
@@ -16,7 +16,10 @@
package org.onosproject.drivers.bmv2;
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
import com.google.common.testing.EqualsTester;
+import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.MacAddress;
import org.onosproject.bmv2.api.model.Bmv2Model;
@@ -26,6 +29,7 @@
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.drivers.bmv2.translators.Bmv2DefaultFlowRuleTranslator;
import org.onosproject.drivers.bmv2.translators.Bmv2FlowRuleTranslator;
+import org.onosproject.drivers.bmv2.translators.Bmv2SimpleTranslatorConfig;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
@@ -35,6 +39,10 @@
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.util.Random;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -46,9 +54,30 @@
*/
public class Bmv2DefaultFlowRuleTranslatorTest {
+ private static final String JSON_CONFIG_PATH = "/simple.json";
private Random random = new Random();
- private Bmv2FlowRuleTranslator translator = new Bmv2DefaultFlowRuleTranslator();
- private Bmv2Model model = translator.config().model();
+ private Bmv2Model model;
+ private Bmv2FlowRuleTranslator.TranslatorConfig config;
+ private Bmv2FlowRuleTranslator translator;
+
+ @Before
+ public void setUp() throws Exception {
+ InputStream inputStream = Bmv2SimpleTranslatorConfig.class
+ .getResourceAsStream(JSON_CONFIG_PATH);
+ InputStreamReader reader = new InputStreamReader(inputStream);
+ BufferedReader bufReader = new BufferedReader(reader);
+ JsonObject json = null;
+ try {
+ json = Json.parse(bufReader).asObject();
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to parse JSON file: " + e.getMessage());
+ }
+
+ this.model = Bmv2Model.parse(json);
+ this.config = new Bmv2SimpleTranslatorConfig(model);
+ this.translator = new Bmv2DefaultFlowRuleTranslator(config);
+
+ }
@Test
diff --git a/drivers/bmv2/src/test/resources/simple.json b/drivers/bmv2/src/test/resources/simple.json
new file mode 100644
index 0000000..7ff6446
--- /dev/null
+++ b/drivers/bmv2/src/test/resources/simple.json
@@ -0,0 +1,397 @@
+{
+ "header_types": [
+ {
+ "name": "standard_metadata_t",
+ "id": 0,
+ "fields": [
+ [
+ "ingress_port",
+ 9
+ ],
+ [
+ "packet_length",
+ 32
+ ],
+ [
+ "egress_spec",
+ 9
+ ],
+ [
+ "egress_port",
+ 9
+ ],
+ [
+ "egress_instance",
+ 32
+ ],
+ [
+ "instance_type",
+ 32
+ ],
+ [
+ "clone_spec",
+ 32
+ ],
+ [
+ "_padding",
+ 5
+ ]
+ ],
+ "length_exp": null,
+ "max_length": null
+ },
+ {
+ "name": "ethernet_t",
+ "id": 1,
+ "fields": [
+ [
+ "dstAddr",
+ 48
+ ],
+ [
+ "srcAddr",
+ 48
+ ],
+ [
+ "etherType",
+ 16
+ ]
+ ],
+ "length_exp": null,
+ "max_length": null
+ },
+ {
+ "name": "intrinsic_metadata_t",
+ "id": 2,
+ "fields": [
+ [
+ "ingress_global_timestamp",
+ 32
+ ],
+ [
+ "lf_field_list",
+ 32
+ ],
+ [
+ "mcast_grp",
+ 16
+ ],
+ [
+ "egress_rid",
+ 16
+ ]
+ ],
+ "length_exp": null,
+ "max_length": null
+ }
+ ],
+ "headers": [
+ {
+ "name": "standard_metadata",
+ "id": 0,
+ "header_type": "standard_metadata_t",
+ "metadata": true
+ },
+ {
+ "name": "ethernet",
+ "id": 1,
+ "header_type": "ethernet_t",
+ "metadata": false
+ },
+ {
+ "name": "intrinsic_metadata",
+ "id": 2,
+ "header_type": "intrinsic_metadata_t",
+ "metadata": true
+ }
+ ],
+ "header_stacks": [],
+ "parsers": [
+ {
+ "name": "parser",
+ "id": 0,
+ "init_state": "start",
+ "parse_states": [
+ {
+ "name": "start",
+ "id": 0,
+ "parser_ops": [],
+ "transition_key": [],
+ "transitions": [
+ {
+ "value": "default",
+ "mask": null,
+ "next_state": "parse_ethernet"
+ }
+ ]
+ },
+ {
+ "name": "parse_ethernet",
+ "id": 1,
+ "parser_ops": [
+ {
+ "op": "extract",
+ "parameters": [
+ {
+ "type": "regular",
+ "value": "ethernet"
+ }
+ ]
+ }
+ ],
+ "transition_key": [],
+ "transitions": [
+ {
+ "value": "default",
+ "mask": null,
+ "next_state": null
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "deparsers": [
+ {
+ "name": "deparser",
+ "id": 0,
+ "order": [
+ "ethernet"
+ ]
+ }
+ ],
+ "meter_arrays": [],
+ "actions": [
+ {
+ "name": "flood",
+ "id": 0,
+ "runtime_data": [],
+ "primitives": [
+ {
+ "op": "modify_field",
+ "parameters": [
+ {
+ "type": "field",
+ "value": [
+ "intrinsic_metadata",
+ "mcast_grp"
+ ]
+ },
+ {
+ "type": "field",
+ "value": [
+ "standard_metadata",
+ "ingress_port"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "_drop",
+ "id": 1,
+ "runtime_data": [],
+ "primitives": [
+ {
+ "op": "modify_field",
+ "parameters": [
+ {
+ "type": "field",
+ "value": [
+ "standard_metadata",
+ "egress_spec"
+ ]
+ },
+ {
+ "type": "hexstr",
+ "value": "0x1ff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "fwd",
+ "id": 2,
+ "runtime_data": [
+ {
+ "name": "port",
+ "bitwidth": 9
+ }
+ ],
+ "primitives": [
+ {
+ "op": "modify_field",
+ "parameters": [
+ {
+ "type": "field",
+ "value": [
+ "standard_metadata",
+ "egress_spec"
+ ]
+ },
+ {
+ "type": "runtime_data",
+ "value": 0
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "push_to_cp",
+ "id": 3,
+ "runtime_data": [],
+ "primitives": [
+ {
+ "op": "modify_field",
+ "parameters": [
+ {
+ "type": "field",
+ "value": [
+ "standard_metadata",
+ "egress_spec"
+ ]
+ },
+ {
+ "type": "hexstr",
+ "value": "0x200"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "pipelines": [
+ {
+ "name": "ingress",
+ "id": 0,
+ "init_table": "table0",
+ "tables": [
+ {
+ "name": "table0",
+ "id": 0,
+ "match_type": "ternary",
+ "type": "simple",
+ "max_size": 16384,
+ "with_counters": false,
+ "direct_meters": null,
+ "support_timeout": false,
+ "key": [
+ {
+ "match_type": "ternary",
+ "target": [
+ "standard_metadata",
+ "ingress_port"
+ ],
+ "mask": null
+ },
+ {
+ "match_type": "ternary",
+ "target": [
+ "ethernet",
+ "dstAddr"
+ ],
+ "mask": null
+ },
+ {
+ "match_type": "ternary",
+ "target": [
+ "ethernet",
+ "srcAddr"
+ ],
+ "mask": null
+ },
+ {
+ "match_type": "ternary",
+ "target": [
+ "ethernet",
+ "etherType"
+ ],
+ "mask": null
+ }
+ ],
+ "actions": [
+ "fwd",
+ "flood",
+ "push_to_cp",
+ "_drop"
+ ],
+ "next_tables": {
+ "fwd": null,
+ "flood": null,
+ "push_to_cp": null,
+ "_drop": null
+ },
+ "default_action": null,
+ "base_default_next": null
+ }
+ ],
+ "conditionals": []
+ },
+ {
+ "name": "egress",
+ "id": 1,
+ "init_table": null,
+ "tables": [],
+ "conditionals": []
+ }
+ ],
+ "calculations": [],
+ "checksums": [],
+ "learn_lists": [],
+ "field_lists": [],
+ "counter_arrays": [],
+ "register_arrays": [],
+ "force_arith": [
+ [
+ "standard_metadata",
+ "ingress_port"
+ ],
+ [
+ "standard_metadata",
+ "packet_length"
+ ],
+ [
+ "standard_metadata",
+ "egress_spec"
+ ],
+ [
+ "standard_metadata",
+ "egress_port"
+ ],
+ [
+ "standard_metadata",
+ "egress_instance"
+ ],
+ [
+ "standard_metadata",
+ "instance_type"
+ ],
+ [
+ "standard_metadata",
+ "clone_spec"
+ ],
+ [
+ "standard_metadata",
+ "_padding"
+ ],
+ [
+ "intrinsic_metadata",
+ "ingress_global_timestamp"
+ ],
+ [
+ "intrinsic_metadata",
+ "lf_field_list"
+ ],
+ [
+ "intrinsic_metadata",
+ "mcast_grp"
+ ],
+ [
+ "intrinsic_metadata",
+ "egress_rid"
+ ]
+ ]
+}
\ No newline at end of file