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