Various Bmv2 protocol refactorings in preparation of the flow rule
translator (ONOS-4044)

- Added new classes for different match parameters (exact, ternary, lpm,
  valid)
- Divided api package in two sub-packages, model (previously under
  drivers) and runtime (old api package)
- Improved Bmv2ThriftClient caching and table entry handling

Change-Id: I23c174cf3e8f9f6ecddb99c2d09dc531e8f1c73f
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleDriver.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleDriver.java
index c000f52..c226e60 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleDriver.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2FlowRuleDriver.java
@@ -20,10 +20,10 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
-import org.onosproject.bmv2.api.Bmv2ExtensionSelector;
-import org.onosproject.bmv2.api.Bmv2ExtensionTreatment;
-import org.onosproject.bmv2.api.Bmv2TableEntry;
-import org.onosproject.bmv2.api.Bmv2Exception;
+import org.onosproject.bmv2.api.runtime.Bmv2ExtensionSelector;
+import org.onosproject.bmv2.api.runtime.Bmv2ExtensionTreatment;
+import org.onosproject.bmv2.api.runtime.Bmv2TableEntry;
+import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
 import org.onosproject.bmv2.ctl.Bmv2ThriftClient;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.net.flow.DefaultFlowEntry;
@@ -70,7 +70,7 @@
         Bmv2ThriftClient deviceClient;
         try {
             deviceClient = getDeviceClient();
-        } catch (Bmv2Exception e) {
+        } catch (Bmv2RuntimeException e) {
             return Collections.emptyList();
         }
 
@@ -107,7 +107,7 @@
                     tableEntryIdsMap.put(rule, entryId);
                     deviceEntriesMap.put(rule, new DefaultFlowEntry(
                             rule, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
-                } catch (Bmv2Exception e) {
+                } catch (Bmv2RuntimeException e) {
                     log.error("Unable to update flow rule", e);
                     continue;
                 }
@@ -121,7 +121,7 @@
                     tableEntryIdsMap.put(rule, entryId);
                     deviceEntriesMap.put(rule, new DefaultFlowEntry(
                             rule, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
-                } catch (Bmv2Exception e) {
+                } catch (Bmv2RuntimeException e) {
                     log.error("Unable to add flow rule", e);
                     continue;
                 }
@@ -138,7 +138,7 @@
         Bmv2ThriftClient deviceClient;
         try {
             deviceClient = getDeviceClient();
-        } catch (Bmv2Exception e) {
+        } catch (Bmv2RuntimeException e) {
             return Collections.emptyList();
         }
 
@@ -152,7 +152,7 @@
 
                 try {
                     deviceClient.deleteTableEntry(tableName, entryId);
-                } catch (Bmv2Exception e) {
+                } catch (Bmv2RuntimeException e) {
                     log.error("Unable to delete flow rule", e);
                     continue;
                 }
@@ -225,10 +225,10 @@
         return "table" + String.valueOf(tableId);
     }
 
-    private Bmv2ThriftClient getDeviceClient() throws Bmv2Exception {
+    private Bmv2ThriftClient getDeviceClient() throws Bmv2RuntimeException {
         try {
             return Bmv2ThriftClient.of(handler().data().deviceId());
-        } catch (Bmv2Exception e) {
+        } catch (Bmv2RuntimeException e) {
             log.error("Failed to connect to Bmv2 device", e);
             throw e;
         }
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PortGetterDriver.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PortGetterDriver.java
index fa2dde0..927b77d 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PortGetterDriver.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PortGetterDriver.java
@@ -18,7 +18,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
-import org.onosproject.bmv2.api.Bmv2Exception;
+import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
 import org.onosproject.bmv2.ctl.Bmv2ThriftClient;
 import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.PortNumber;
@@ -44,7 +44,7 @@
         Bmv2ThriftClient deviceClient;
         try {
             deviceClient = Bmv2ThriftClient.of(handler().data().deviceId());
-        } catch (Bmv2Exception e) {
+        } catch (Bmv2RuntimeException e) {
             log.error("Failed to connect to Bmv2 device", e);
             return Collections.emptyList();
         }
@@ -68,7 +68,7 @@
                                 annotations
                         ));
                     });
-        } catch (Bmv2Exception e) {
+        } catch (Bmv2RuntimeException e) {
             log.error("Unable to get port description from Bmv2 device", e);
         }
 
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2MatchKey.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2MatchKey.java
deleted file mode 100644
index d068328..0000000
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2MatchKey.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2014-2016 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.bmv2.api;
-
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.Lists;
-import org.p4.bmv2.thrift.BmMatchParam;
-import org.p4.bmv2.thrift.BmMatchParamExact;
-import org.p4.bmv2.thrift.BmMatchParamLPM;
-import org.p4.bmv2.thrift.BmMatchParamTernary;
-import org.p4.bmv2.thrift.BmMatchParamType;
-import org.p4.bmv2.thrift.BmMatchParamValid;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Bmv2 match key representation.
- */
-public final class Bmv2MatchKey {
-
-    private final List<BmMatchParam> matchParams;
-
-    /**
-     * Creates a new match key.
-     *
-     * @param matchParams The ordered list of match parameters
-     */
-    private Bmv2MatchKey(List<BmMatchParam> matchParams) {
-        this.matchParams = matchParams;
-    }
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    /**
-     * Returns the match parameters defined for this match key (read-only).
-     *
-     * @return match parameters
-     */
-    public final List<BmMatchParam> bmMatchParams() {
-        return Collections.unmodifiableList(matchParams);
-    }
-
-    @Override
-    public final int hashCode() {
-        return Objects.hashCode(matchParams);
-    }
-
-    @Override
-    public final boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        final Bmv2MatchKey other = (Bmv2MatchKey) obj;
-
-        return Objects.equals(this.matchParams, other.matchParams);
-    }
-
-    @Override
-    public final String toString() {
-        return MoreObjects.toStringHelper(this)
-                .addValue(matchParams)
-                .toString();
-    }
-
-    /**
-     * Builder of a Bmv2 match key.
-     */
-    public static final class Builder {
-
-        private List<BmMatchParam> matchParams;
-
-        private Builder() {
-            this.matchParams = Lists.newArrayList();
-        }
-
-        /**
-         * Adds an exact match parameter.
-         *
-         * @param key a ByteBuffer value
-         * @return this
-         */
-        public Builder withExact(ByteBuffer key) {
-            this.matchParams.add(
-                    new BmMatchParam(BmMatchParamType.EXACT)
-                            .setExact(new BmMatchParamExact(key)));
-            return this;
-        }
-
-
-        /**
-         * Adds a longest prefix match parameter.
-         *
-         * @param key          a ByteBuffer value
-         * @param prefixLength an integer value
-         * @return this
-         */
-        public Builder withLpm(ByteBuffer key, int prefixLength) {
-            this.matchParams.add(
-                    new BmMatchParam(BmMatchParamType.LPM)
-                            .setLpm(new BmMatchParamLPM(key, prefixLength)));
-            return this;
-        }
-
-        /**
-         * Adds a ternary match parameter.
-         *
-         * @param key  a ByteBuffer value
-         * @param mask an ByteBuffer value
-         * @return this
-         */
-        public Builder withTernary(ByteBuffer key, ByteBuffer mask) {
-            this.matchParams.add(
-                    new BmMatchParam(BmMatchParamType.TERNARY).
-                            setTernary(new BmMatchParamTernary(key, mask)));
-            return this;
-        }
-
-        /**
-         * Adds a ternary match parameter where all bits are don't-care.
-         *
-         * @param byteLength an integer value representing the length in byte of the parameter
-         * @return this
-         */
-        public Builder withWildcard(int byteLength) {
-            byte[] zeros = new byte[byteLength];
-            Arrays.fill(zeros, (byte) 0);
-            return this.withTernary(ByteBuffer.wrap(zeros), ByteBuffer.wrap(zeros));
-        }
-
-        /**
-         * Adds a valid match parameter.
-         *
-         * @param key a boolean value
-         * @return this
-         */
-        public Builder withValid(boolean key) {
-            this.matchParams.add(
-                    new BmMatchParam(BmMatchParamType.VALID)
-                            .setValid(new BmMatchParamValid(key)));
-            return this;
-        }
-
-        /**
-         * Builds a new match key object.
-         *
-         * @return match key
-         */
-        public Bmv2MatchKey build() {
-            return new Bmv2MatchKey(this.matchParams);
-        }
-    }
-}
\ No newline at end of file
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2Model.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2Model.java
similarity index 91%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2Model.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2Model.java
index 433fd95..7a5e8a0 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2Model.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2Model.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import com.eclipsesource.json.JsonArray;
 import com.eclipsesource.json.JsonObject;
@@ -24,6 +24,7 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import org.onosproject.bmv2.api.runtime.Bmv2MatchParam;
 
 import java.util.List;
 import java.util.Map;
@@ -67,6 +68,7 @@
      */
     public static Bmv2Model parse(JsonObject json) {
         checkArgument(json != null, "json cannot be null");
+        // TODO: implement caching, no need to parse a json if we already have the model
         Bmv2Model model = new Bmv2Model(json);
         model.doParse();
         return model;
@@ -335,7 +337,27 @@
                     Bmv2ModelField field = new Bmv2ModelField(
                             header, header.type().field(typeName));
 
-                    String matchType = jKey.asObject().get("match_type").asString();
+                    String matchTypeStr = jKey.asObject().get("match_type").asString();
+
+                    Bmv2MatchParam.Type matchType;
+
+                    switch (matchTypeStr) {
+                        case "ternary":
+                            matchType = Bmv2MatchParam.Type.TERNARY;
+                            break;
+                        case "exact":
+                            matchType = Bmv2MatchParam.Type.EXACT;
+                            break;
+                        case "lpm":
+                            matchType = Bmv2MatchParam.Type.LPM;
+                            break;
+                        case "valid":
+                            matchType = Bmv2MatchParam.Type.VALID;
+                            break;
+                        default:
+                            throw new RuntimeException(
+                                    "Unable to parse match type: " + matchTypeStr);
+                    }
 
                     keys.add(new Bmv2ModelTableKey(matchType, field));
                 });
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelAction.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelAction.java
similarity index 96%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelAction.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelAction.java
index be073a1..f53806b 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelAction.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelField.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelField.java
similarity index 95%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelField.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelField.java
index 63cdcce..f20ae3b 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelField.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelField.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import com.google.common.base.Objects;
 
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelFieldType.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelFieldType.java
similarity index 95%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelFieldType.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelFieldType.java
index 0cd1f11..c0147bbd 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelFieldType.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelFieldType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import com.google.common.base.Objects;
 
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelHeader.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelHeader.java
similarity index 96%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelHeader.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelHeader.java
index 5aa2f39..abab008 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelHeader.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelHeader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import com.google.common.base.Objects;
 
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelHeaderType.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelHeaderType.java
similarity index 96%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelHeaderType.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelHeaderType.java
index e70fd92..3865871 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelHeaderType.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelHeaderType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelRuntimeData.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelRuntimeData.java
similarity index 95%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelRuntimeData.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelRuntimeData.java
index 0de1d09..388c137 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelRuntimeData.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelRuntimeData.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import java.util.Objects;
 
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelTable.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelTable.java
similarity index 97%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelTable.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelTable.java
index 2351f49..2dc7e3f 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelTable.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelTable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import com.google.common.base.Objects;
 
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelTableKey.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelTableKey.java
similarity index 85%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelTableKey.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelTableKey.java
index a65b578..a98a7ec 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/Bmv2ModelTableKey.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/Bmv2ModelTableKey.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2.model;
+package org.onosproject.bmv2.api.model;
 
 import com.google.common.base.Objects;
+import org.onosproject.bmv2.api.runtime.Bmv2MatchParam;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
 
@@ -25,7 +26,7 @@
  */
 public final class Bmv2ModelTableKey {
 
-    private final String matchType;
+    private final Bmv2MatchParam.Type matchType;
     private final Bmv2ModelField field;
 
     /**
@@ -34,7 +35,7 @@
      * @param matchType match type
      * @param field     field instance
      */
-    protected Bmv2ModelTableKey(String matchType, Bmv2ModelField field) {
+    protected Bmv2ModelTableKey(Bmv2MatchParam.Type matchType, Bmv2ModelField field) {
         this.matchType = matchType;
         this.field = field;
     }
@@ -45,7 +46,7 @@
      * @return a string value
      * TODO returns enum of match type
      */
-    public String matchType() {
+    public Bmv2MatchParam.Type matchType() {
         return matchType;
     }
 
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/package-info.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/package-info.java
similarity index 86%
rename from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/package-info.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/package-info.java
index 7e585dd..adadced 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/package-info.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/model/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -17,4 +17,4 @@
 /**
  * BMv2 configuration model classes.
  */
-package org.onosproject.drivers.bmv2.model;
\ No newline at end of file
+package org.onosproject.bmv2.api.model;
\ No newline at end of file
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/package-info.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/package-info.java
index d8946e3..4d982ed 100644
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/package-info.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/package-info.java
@@ -16,5 +16,10 @@
 
 /**
  * Bmv2 API abstractions.
+ * <p>
+ * Bmv2 APIs are divided in two sub-packages, runtime and model.
+ * Runtime APIs are used to represent operations that can be performed at runtime
+ * on a Bmv2 device, while model APIs are used to describe the Bmv2 packet
+ * processing model.
  */
 package org.onosproject.bmv2.api;
\ No newline at end of file
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2Action.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2Action.java
similarity index 75%
rename from protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2Action.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2Action.java
index 5bbc50b..9b2a209 100644
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2Action.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2Action.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,27 +14,28 @@
  * limitations under the License.
  */
 
-package org.onosproject.bmv2.api;
+package org.onosproject.bmv2.api.runtime;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.Lists;
+import org.onlab.util.ImmutableByteSequence;
 
-import java.nio.ByteBuffer;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 
 /**
- * Bmv2 Action representation.
+ * Bmv2 action representation.
  */
 public final class Bmv2Action {
 
     private final String name;
-    private final List<ByteBuffer> parameters;
+    private final List<ImmutableByteSequence> parameters;
 
-    private Bmv2Action(String name, List<ByteBuffer> parameters) {
+    private Bmv2Action(String name, List<ImmutableByteSequence> parameters) {
         // hide constructor
         this.name = name;
         this.parameters = parameters;
@@ -48,7 +49,7 @@
     }
 
     /**
-     * Get action name.
+     * Return the name of this action.
      *
      * @return action name
      */
@@ -57,11 +58,12 @@
     }
 
     /**
-     * Get list of action parameters ordered as per P4 action definition.
+     * Returns an immutable view of the ordered list of parameters of this
+     * action.
      *
-     * @return List of action parameters
+     * @return list of byte sequence
      */
-    public final List<ByteBuffer> parameters() {
+    public final List<ImmutableByteSequence> parameters() {
         return Collections.unmodifiableList(parameters);
     }
 
@@ -96,8 +98,8 @@
      */
     public static final class Builder {
 
-        private String name;
-        private List<ByteBuffer> parameters;
+        private String name = null;
+        private List<ImmutableByteSequence> parameters;
 
         private Builder() {
             this.parameters = Lists.newArrayList();
@@ -110,7 +112,7 @@
          * @return this
          */
         public Builder withName(String actionName) {
-            this.name = actionName;
+            this.name = checkNotNull(actionName);
             return this;
         }
 
@@ -120,8 +122,8 @@
          * @param parameter a ByteBuffer value
          * @return this
          */
-        public Builder addParameter(ByteBuffer parameter) {
-            parameters.add(parameter);
+        public Builder addParameter(ImmutableByteSequence parameter) {
+            parameters.add(checkNotNull(parameter));
             return this;
         }
 
@@ -131,7 +133,7 @@
          * @return a Bmv2 action
          */
         public Bmv2Action build() {
-            checkNotNull(name, "Action name not set");
+            checkState(name != null, "action name not set");
             return new Bmv2Action(name, parameters);
         }
     }
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExactMatchParam.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExactMatchParam.java
new file mode 100644
index 0000000..d23bfc6
--- /dev/null
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExactMatchParam.java
@@ -0,0 +1,79 @@
+/*
+ * 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.bmv2.api.runtime;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onlab.util.ImmutableByteSequence;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a Bmv2 exact match parameter.
+ */
+public class Bmv2ExactMatchParam implements Bmv2MatchParam {
+
+    private final ImmutableByteSequence value;
+
+    /**
+     * Creates a new match parameter object that matches exactly on the
+     * given byte sequence.
+     *
+     * @param value a byte sequence value
+     */
+    public Bmv2ExactMatchParam(ImmutableByteSequence value) {
+        this.value = checkNotNull(value, "value cannot be null");
+    }
+
+    @Override
+    public Type type() {
+        return Type.EXACT;
+    }
+
+    /**
+     * Return the byte sequence value matched by this parameter.
+     *
+     * @return an immutable byte buffer value
+     */
+    public ImmutableByteSequence value() {
+        return this.value;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(value);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final Bmv2ExactMatchParam other = (Bmv2ExactMatchParam) obj;
+        return Objects.equal(this.value, other.value);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("value", value)
+                .toString();
+    }
+}
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2ExtensionSelector.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExtensionSelector.java
similarity index 89%
rename from protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2ExtensionSelector.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExtensionSelector.java
index 1bd9f1c..bf44a0e 100644
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2ExtensionSelector.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExtensionSelector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
-package org.onosproject.bmv2.api;
+package org.onosproject.bmv2.api.runtime;
 
 import org.onlab.util.KryoNamespace;
 import org.onosproject.net.flow.AbstractExtension;
 import org.onosproject.net.flow.criteria.ExtensionSelector;
 import org.onosproject.net.flow.criteria.ExtensionSelectorType;
 
+/**
+ * Extension selector for Bmv2 used as a wrapper for a {@link Bmv2MatchKey}.
+ */
 public class Bmv2ExtensionSelector extends AbstractExtension implements ExtensionSelector {
 
     private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2ExtensionTreatment.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExtensionTreatment.java
similarity index 89%
rename from protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2ExtensionTreatment.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExtensionTreatment.java
index cf48e38..12ab1e3 100644
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2ExtensionTreatment.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ExtensionTreatment.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
-package org.onosproject.bmv2.api;
+package org.onosproject.bmv2.api.runtime;
 
 import org.onlab.util.KryoNamespace;
 import org.onosproject.net.flow.AbstractExtension;
 import org.onosproject.net.flow.instructions.ExtensionTreatment;
 import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
 
+/**
+ * Extension treatment for Bmv2 used as a wrapper for a {@link Bmv2Action}.
+ */
 public class Bmv2ExtensionTreatment extends AbstractExtension implements ExtensionTreatment {
 
     private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2LpmMatchParam.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2LpmMatchParam.java
new file mode 100644
index 0000000..29d5279
--- /dev/null
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2LpmMatchParam.java
@@ -0,0 +1,95 @@
+/*
+ * 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.bmv2.api.runtime;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onlab.util.ImmutableByteSequence;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a Bmv2 longest prefix match (LPM) parameter.
+ */
+public class Bmv2LpmMatchParam implements Bmv2MatchParam {
+
+    private final ImmutableByteSequence value;
+    private final int prefixLength;
+
+    /**
+     * Creates a new LPM parameter using the given byte sequence value and
+     * prefix length.
+     *
+     * @param value        a byte sequence value
+     * @param prefixLength an integer value
+     */
+    public Bmv2LpmMatchParam(ImmutableByteSequence value, int prefixLength) {
+        checkArgument(prefixLength >= 0, "prefix length cannot be negative");
+        this.value = checkNotNull(value);
+        this.prefixLength = prefixLength;
+    }
+
+    @Override
+    public Bmv2MatchParam.Type type() {
+        return Type.LPM;
+    }
+
+    /**
+     * Returns the byte sequence value of this parameter.
+     *
+     * @return a byte sequence value
+     */
+    public ImmutableByteSequence value() {
+        return this.value;
+    }
+
+    /**
+     * Returns the prefix length of this parameter.
+     *
+     * @return an integer value
+     */
+    public int prefixLength() {
+        return this.prefixLength;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(value, prefixLength);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final Bmv2LpmMatchParam other = (Bmv2LpmMatchParam) obj;
+        return Objects.equal(this.value, other.value)
+                && Objects.equal(this.prefixLength, other.prefixLength);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("value", value)
+                .add("prefixLength", prefixLength)
+                .toString();
+    }
+}
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2MatchKey.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2MatchKey.java
new file mode 100644
index 0000000..cdcfcd9
--- /dev/null
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2MatchKey.java
@@ -0,0 +1,119 @@
+/*
+ * 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.bmv2.api.runtime;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.Lists;
+import org.onlab.util.ImmutableByteSequence;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Bmv2 match key representation.
+ */
+public final class Bmv2MatchKey {
+
+    private final List<Bmv2MatchParam> matchParams;
+
+    private Bmv2MatchKey(List<Bmv2MatchParam> matchParams) {
+        // ban constructor
+        this.matchParams = matchParams;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Returns an immutable view of the ordered list of match parameters of this
+     * match key.
+     *
+     * @return list match parameters
+     */
+    public final List<Bmv2MatchParam> matchParams() {
+        return Collections.unmodifiableList(matchParams);
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hashCode(matchParams);
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final Bmv2MatchKey other = (Bmv2MatchKey) obj;
+
+        return Objects.equals(this.matchParams, other.matchParams);
+    }
+
+    @Override
+    public final String toString() {
+        return MoreObjects.toStringHelper(this)
+                .addValue(matchParams)
+                .toString();
+    }
+
+    /**
+     * Builder of a Bmv2 match key.
+     */
+    public static final class Builder {
+
+        private List<Bmv2MatchParam> matchParams;
+
+        private Builder() {
+            this.matchParams = Lists.newArrayList();
+        }
+
+        public Builder add(Bmv2MatchParam param) {
+            this.matchParams.add(checkNotNull(param));
+            return this;
+        }
+
+        /**
+         * Adds a ternary match parameter where all bits are don't-care.
+         *
+         * @param byteLength length in bytes of the parameter
+         * @return this
+         */
+        public Builder withWildcard(int byteLength) {
+            checkArgument(byteLength > 0, "length must be a positive integer");
+            return add(new Bmv2TernaryMatchParam(
+                    ImmutableByteSequence.ofZeros(byteLength),
+                    ImmutableByteSequence.ofZeros(byteLength)));
+        }
+
+        /**
+         * Builds a new match key object.
+         *
+         * @return match key
+         */
+        public Bmv2MatchKey build() {
+            return new Bmv2MatchKey(this.matchParams);
+        }
+    }
+}
\ No newline at end of file
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2MatchParam.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2MatchParam.java
new file mode 100644
index 0000000..35bac79
--- /dev/null
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2MatchParam.java
@@ -0,0 +1,52 @@
+/*
+ * 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.bmv2.api.runtime;
+
+/**
+ * Representation of a Bmv2 match parameter.
+ */
+public interface Bmv2MatchParam {
+
+    /**
+     * Returns the match type of this parameter.
+     *
+     * @return a match type value
+     */
+    Type type();
+
+    /**
+     * Bmv2 match types.
+     */
+    enum Type {
+        /**
+         * Exact match type.
+         */
+        EXACT,
+        /**
+         * Ternary match type.
+         */
+        TERNARY,
+        /**
+         * Longest-prefix match type.
+         */
+        LPM,
+        /**
+         * Valid match type.
+         */
+        VALID;
+    }
+}
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2PortInfo.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2PortInfo.java
similarity index 93%
rename from protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2PortInfo.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2PortInfo.java
index 3f36ade..c6be426 100644
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2PortInfo.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2PortInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onosproject.bmv2.api;
+package org.onosproject.bmv2.api.runtime;
 
 import com.google.common.base.MoreObjects;
 import org.p4.bmv2.thrift.DevMgrPortInfo;
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2Exception.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2RuntimeException.java
similarity index 63%
rename from protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2Exception.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2RuntimeException.java
index a428491..f7153c5 100644
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2Exception.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2RuntimeException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,14 +14,18 @@
  * limitations under the License.
  */
 
-package org.onosproject.bmv2.api;
+package org.onosproject.bmv2.api.runtime;
 
 /**
- * General Bmv2 exception.
+ * General exception of the Bmv2 runtime APIs.
  */
-public class Bmv2Exception extends Exception {
+public class Bmv2RuntimeException extends Exception {
 
-    public Bmv2Exception(String message, Throwable cause) {
+    public Bmv2RuntimeException(String message, Throwable cause) {
         super(message, cause);
     }
+
+    public Bmv2RuntimeException(String message) {
+        super(message);
+    }
 }
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2TableEntry.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2TableEntry.java
similarity index 87%
rename from protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2TableEntry.java
rename to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2TableEntry.java
index 4bf0291..96adadd 100644
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/Bmv2TableEntry.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2TableEntry.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package org.onosproject.bmv2.api;
-
-import com.google.common.base.Preconditions;
+package org.onosproject.bmv2.api.runtime;
 
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * Bmv2 representation of a table entry.
  */
@@ -43,6 +44,11 @@
         this.timeout = timeout;
     }
 
+    /**
+     * Returns a new Bmv2 table entry builder.
+     *
+     * @return a new builder.
+     */
     public static Builder builder() {
         return new Builder();
     }
@@ -159,7 +165,7 @@
          * @return this
          */
         public Builder withTableName(String tableName) {
-            this.tableName = tableName;
+            this.tableName = checkNotNull(tableName, "table name cannot be null");
             return this;
         }
 
@@ -170,7 +176,7 @@
          * @return this
          */
         public Builder withMatchKey(Bmv2MatchKey matchKey) {
-            this.matchKey = matchKey;
+            this.matchKey = checkNotNull(matchKey, "match key cannot be null");
             return this;
         }
 
@@ -181,11 +187,12 @@
          * @return this
          */
         public Builder withAction(Bmv2Action action) {
-            this.action = action;
+            this.action = checkNotNull(action, "action cannot be null");
             return this;
         }
 
         public Builder withPriority(int priority) {
+            checkArgument(priority >= 0, "priority cannot be negative");
             this.priority = priority;
             return this;
         }
@@ -197,6 +204,7 @@
          * @return this
          */
         public Builder withTimeout(double timeout) {
+            checkArgument(timeout > 0, "timeout must be a positive non-zero value");
             this.timeout = timeout;
             return this;
         }
@@ -207,10 +215,6 @@
          * @return a new table entry object
          */
         public Bmv2TableEntry build() {
-            Preconditions.checkNotNull(tableName);
-            Preconditions.checkNotNull(matchKey);
-            Preconditions.checkNotNull(action);
-
             return new Bmv2TableEntry(tableName, matchKey, action, priority,
                                       timeout);
 
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2TernaryMatchParam.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2TernaryMatchParam.java
new file mode 100644
index 0000000..76d42c3
--- /dev/null
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2TernaryMatchParam.java
@@ -0,0 +1,97 @@
+/*
+ * 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.bmv2.api.runtime;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onlab.util.ImmutableByteSequence;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Representation of a Bmv2 ternary match parameter.
+ */
+public class Bmv2TernaryMatchParam implements Bmv2MatchParam {
+
+    private final ImmutableByteSequence value;
+    private final ImmutableByteSequence mask;
+
+    /**
+     * Creates a new ternary match parameter using the given byte sequences of
+     * value and mask.
+     *
+     * @param value a byte sequence value
+     * @param mask  a byte sequence value
+     */
+    public Bmv2TernaryMatchParam(ImmutableByteSequence value,
+                                 ImmutableByteSequence mask) {
+        this.value = checkNotNull(value, "value cannot be null");
+        this.mask = checkNotNull(mask, "value cannot be null");
+        checkState(value.size() == mask.size(),
+                   "value and mask must have equal size");
+    }
+
+    @Override
+    public Type type() {
+        return Type.TERNARY;
+    }
+
+    /**
+     * Returns the byte sequence value of by this parameter.
+     *
+     * @return a byte sequence value
+     */
+    public ImmutableByteSequence value() {
+        return this.value;
+    }
+
+    /**
+     * Returns the byte sequence mask of by this parameter.
+     *
+     * @return a byte sequence value
+     */
+    public ImmutableByteSequence mask() {
+        return this.mask;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(value, mask);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final Bmv2TernaryMatchParam other = (Bmv2TernaryMatchParam) obj;
+        return Objects.equal(this.value, other.value)
+                && Objects.equal(this.mask, other.mask);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("value", value)
+                .add("mask", mask)
+                .toString();
+    }
+}
\ No newline at end of file
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ValidMatchParam.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ValidMatchParam.java
new file mode 100644
index 0000000..31080d5
--- /dev/null
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2ValidMatchParam.java
@@ -0,0 +1,77 @@
+/*
+ * 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.bmv2.api.runtime;
+
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Representation of a Bmv2 valid match parameter.
+ */
+public class Bmv2ValidMatchParam implements Bmv2MatchParam {
+
+    private final boolean flag;
+
+    /**
+     * Creates a new valid match parameter using the given boolean flag.
+     *
+     * @param flag a boolean value
+     */
+    public Bmv2ValidMatchParam(boolean flag) {
+        this.flag = flag;
+    }
+
+    @Override
+    public Type type() {
+        return Type.VALID;
+    }
+
+    /**
+     * Returns the boolean flag of this parameter.
+     *
+     * @return a boolean value
+     */
+    public boolean flag() {
+        return flag;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(flag);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final Bmv2ValidMatchParam other = (Bmv2ValidMatchParam) obj;
+        return this.flag == other.flag;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("flag", flag)
+                .toString();
+    }
+}
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/package-info.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/package-info.java
similarity index 81%
copy from drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/package-info.java
copy to protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/package-info.java
index 7e585dd..8c11944 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/model/package-info.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -15,6 +15,6 @@
  */
 
 /**
- * BMv2 configuration model classes.
+ * Bmv2 runtime APIs.
  */
-package org.onosproject.drivers.bmv2.model;
\ No newline at end of file
+package org.onosproject.bmv2.api.runtime;
\ No newline at end of file
diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/ctl/Bmv2ThriftClient.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/ctl/Bmv2ThriftClient.java
index c3c86c1..eb6687a 100644
--- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/ctl/Bmv2ThriftClient.java
+++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/ctl/Bmv2ThriftClient.java
@@ -31,15 +31,28 @@
 import org.apache.thrift.transport.TSocket;
 import org.apache.thrift.transport.TTransport;
 import org.apache.thrift.transport.TTransportException;
-import org.onosproject.bmv2.api.Bmv2Action;
-import org.onosproject.bmv2.api.Bmv2Exception;
-import org.onosproject.bmv2.api.Bmv2PortInfo;
-import org.onosproject.bmv2.api.Bmv2TableEntry;
+import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.bmv2.api.runtime.Bmv2Action;
+import org.onosproject.bmv2.api.runtime.Bmv2ExactMatchParam;
+import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
+import org.onosproject.bmv2.api.runtime.Bmv2LpmMatchParam;
+import org.onosproject.bmv2.api.runtime.Bmv2MatchKey;
+import org.onosproject.bmv2.api.runtime.Bmv2PortInfo;
+import org.onosproject.bmv2.api.runtime.Bmv2TableEntry;
+import org.onosproject.bmv2.api.runtime.Bmv2TernaryMatchParam;
+import org.onosproject.bmv2.api.runtime.Bmv2ValidMatchParam;
 import org.onosproject.net.DeviceId;
 import org.p4.bmv2.thrift.BmAddEntryOptions;
+import org.p4.bmv2.thrift.BmMatchParam;
+import org.p4.bmv2.thrift.BmMatchParamExact;
+import org.p4.bmv2.thrift.BmMatchParamLPM;
+import org.p4.bmv2.thrift.BmMatchParamTernary;
+import org.p4.bmv2.thrift.BmMatchParamType;
+import org.p4.bmv2.thrift.BmMatchParamValid;
 import org.p4.bmv2.thrift.DevMgrPortInfo;
 import org.p4.bmv2.thrift.Standard;
 
+import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
@@ -63,31 +76,37 @@
         - avoids opening a new transport session when there's one already open
         - close the connection after a predefined timeout of 5 seconds
      */
-    private static LoadingCache<DeviceId, Pair<TTransport, Standard.Iface>>
+    private static LoadingCache<DeviceId, Bmv2ThriftClient>
             clientCache = CacheBuilder.newBuilder()
             .expireAfterAccess(5, TimeUnit.SECONDS)
             .removalListener(new ClientRemovalListener())
             .build(new ClientLoader());
     private final Standard.Iface stdClient;
+    private final TTransport transport;
 
     // ban constructor
-    private Bmv2ThriftClient(Standard.Iface stdClient) {
+    private Bmv2ThriftClient(TTransport transport, Standard.Iface stdClient) {
+        this.transport = transport;
         this.stdClient = stdClient;
     }
 
+    private void closeTransport() {
+        this.transport.close();
+    }
+
     /**
      * Returns a client object to control the passed device.
      *
      * @param deviceId device id
      * @return bmv2 client object
-     * @throws Bmv2Exception if a connection to the device cannot be established
+     * @throws Bmv2RuntimeException if a connection to the device cannot be established
      */
-    public static Bmv2ThriftClient of(DeviceId deviceId) throws Bmv2Exception {
+    public static Bmv2ThriftClient of(DeviceId deviceId) throws Bmv2RuntimeException {
         try {
             checkNotNull(deviceId, "deviceId cannot be null");
-            return new Bmv2ThriftClient(clientCache.get(deviceId).getValue());
+            return clientCache.get(deviceId);
         } catch (ExecutionException e) {
-            throw new Bmv2Exception(e.getMessage(), e.getCause());
+            throw new Bmv2RuntimeException(e.getMessage(), e.getCause());
         }
     }
 
@@ -103,7 +122,7 @@
         try {
             of(deviceId).stdClient.bm_dev_mgr_show_ports();
             return true;
-        } catch (TException | Bmv2Exception e) {
+        } catch (TException | Bmv2RuntimeException e) {
             return false;
         }
     }
@@ -129,13 +148,70 @@
     }
 
     /**
+     * Builds a list of Bmv2/Thrift compatible match parameters.
+     *
+     * @param matchKey a bmv2 matchKey
+     * @return list of thrift-compatible bm match parameters
+     */
+    private static List<BmMatchParam> buildMatchParamsList(Bmv2MatchKey matchKey) {
+        List<BmMatchParam> paramsList = Lists.newArrayList();
+        matchKey.matchParams().forEach(x -> {
+            switch (x.type()) {
+                case EXACT:
+                    paramsList.add(
+                            new BmMatchParam(BmMatchParamType.EXACT)
+                                    .setExact(new BmMatchParamExact(
+                                            ((Bmv2ExactMatchParam) x).value().asReadOnlyBuffer())));
+                    break;
+                case TERNARY:
+                    paramsList.add(
+                            new BmMatchParam(BmMatchParamType.TERNARY)
+                                    .setTernary(new BmMatchParamTernary(
+                                            ((Bmv2TernaryMatchParam) x).value().asReadOnlyBuffer(),
+                                            ((Bmv2TernaryMatchParam) x).mask().asReadOnlyBuffer())));
+                    break;
+                case LPM:
+                    paramsList.add(
+                            new BmMatchParam(BmMatchParamType.LPM)
+                                    .setLpm(new BmMatchParamLPM(
+                                            ((Bmv2LpmMatchParam) x).value().asReadOnlyBuffer(),
+                                            ((Bmv2LpmMatchParam) x).prefixLength())));
+                    break;
+                case VALID:
+                    paramsList.add(
+                            new BmMatchParam(BmMatchParamType.VALID)
+                                    .setValid(new BmMatchParamValid(
+                                            ((Bmv2ValidMatchParam) x).flag())));
+                    break;
+                default:
+                    // should never be here
+                    throw new RuntimeException("Unknown match param type " + x.type().name());
+            }
+        });
+        return paramsList;
+    }
+
+    /**
+     * Build a list of Bmv2/Thrift compatible action parameters.
+     *
+     * @param action an action object
+     * @return list of ByteBuffers
+     */
+    private static List<ByteBuffer> buildActionParamsList(Bmv2Action action) {
+        return action.parameters()
+                .stream()
+                .map(ImmutableByteSequence::asReadOnlyBuffer)
+                .collect(Collectors.toList());
+    }
+
+    /**
      * Adds a new table entry.
      *
      * @param entry a table entry value
      * @return table-specific entry ID
-     * @throws Bmv2Exception if any error occurs
+     * @throws Bmv2RuntimeException if any error occurs
      */
-    public final long addTableEntry(Bmv2TableEntry entry) throws Bmv2Exception {
+    public final long addTableEntry(Bmv2TableEntry entry) throws Bmv2RuntimeException {
 
         long entryId = -1;
 
@@ -149,9 +225,9 @@
             entryId = stdClient.bm_mt_add_entry(
                     CONTEXT_ID,
                     entry.tableName(),
-                    entry.matchKey().bmMatchParams(),
+                    buildMatchParamsList(entry.matchKey()),
                     entry.action().name(),
-                    entry.action().parameters(),
+                    buildActionParamsList(entry.action()),
                     options);
 
             if (entry.hasTimeout()) {
@@ -170,10 +246,10 @@
                             CONTEXT_ID, entry.tableName(), entryId);
                 } catch (TException e1) {
                     // this should never happen as we know the entry is there
-                    throw new Bmv2Exception(e1.getMessage(), e1);
+                    throw new Bmv2RuntimeException(e1.getMessage(), e1);
                 }
             }
-            throw new Bmv2Exception(e.getMessage(), e);
+            throw new Bmv2RuntimeException(e.getMessage(), e);
         }
     }
 
@@ -183,11 +259,11 @@
      * @param tableName string value of table name
      * @param entryId   long value of entry ID
      * @param action    an action value
-     * @throws Bmv2Exception if any error occurs
+     * @throws Bmv2RuntimeException if any error occurs
      */
     public final void modifyTableEntry(String tableName,
                                        long entryId, Bmv2Action action)
-            throws Bmv2Exception {
+            throws Bmv2RuntimeException {
 
         try {
             stdClient.bm_mt_modify_entry(
@@ -195,10 +271,9 @@
                     tableName,
                     entryId,
                     action.name(),
-                    action.parameters()
-            );
+                    buildActionParamsList(action));
         } catch (TException e) {
-            throw new Bmv2Exception(e.getMessage(), e);
+            throw new Bmv2RuntimeException(e.getMessage(), e);
         }
     }
 
@@ -207,15 +282,15 @@
      *
      * @param tableName string value of table name
      * @param entryId   long value of entry ID
-     * @throws Bmv2Exception if any error occurs
+     * @throws Bmv2RuntimeException if any error occurs
      */
     public final void deleteTableEntry(String tableName,
-                                       long entryId) throws Bmv2Exception {
+                                       long entryId) throws Bmv2RuntimeException {
 
         try {
             stdClient.bm_mt_delete_entry(CONTEXT_ID, tableName, entryId);
         } catch (TException e) {
-            throw new Bmv2Exception(e.getMessage(), e);
+            throw new Bmv2RuntimeException(e.getMessage(), e);
         }
     }
 
@@ -224,19 +299,19 @@
      *
      * @param tableName string value of table name
      * @param action    an action value
-     * @throws Bmv2Exception if any error occurs
+     * @throws Bmv2RuntimeException if any error occurs
      */
     public final void setTableDefaultAction(String tableName, Bmv2Action action)
-            throws Bmv2Exception {
+            throws Bmv2RuntimeException {
 
         try {
             stdClient.bm_mt_set_default_action(
                     CONTEXT_ID,
                     tableName,
                     action.name(),
-                    action.parameters());
+                    buildActionParamsList(action));
         } catch (TException e) {
-            throw new Bmv2Exception(e.getMessage(), e);
+            throw new Bmv2RuntimeException(e.getMessage(), e);
         }
     }
 
@@ -244,9 +319,9 @@
      * Returns information of the ports currently configured in the switch.
      *
      * @return collection of port information
-     * @throws Bmv2Exception if any error occurs
+     * @throws Bmv2RuntimeException if any error occurs
      */
-    public Collection<Bmv2PortInfo> getPortsInfo() throws Bmv2Exception {
+    public Collection<Bmv2PortInfo> getPortsInfo() throws Bmv2RuntimeException {
 
         try {
             List<DevMgrPortInfo> portInfos = stdClient.bm_dev_mgr_show_ports();
@@ -261,7 +336,7 @@
             return bmv2PortInfos;
 
         } catch (TException e) {
-            throw new Bmv2Exception(e.getMessage(), e);
+            throw new Bmv2RuntimeException(e.getMessage(), e);
         }
     }
 
@@ -270,28 +345,28 @@
      *
      * @param tableName string value of table name
      * @return table string dump
-     * @throws Bmv2Exception if any error occurs
+     * @throws Bmv2RuntimeException if any error occurs
      */
-    public String dumpTable(String tableName) throws Bmv2Exception {
+    public String dumpTable(String tableName) throws Bmv2RuntimeException {
 
         try {
             return stdClient.bm_dump_table(CONTEXT_ID, tableName);
         } catch (TException e) {
-            throw new Bmv2Exception(e.getMessage(), e);
+            throw new Bmv2RuntimeException(e.getMessage(), e);
         }
     }
 
     /**
      * Reset the state of the switch (e.g. delete all entries, etc.).
      *
-     * @throws Bmv2Exception if any error occurs
+     * @throws Bmv2RuntimeException if any error occurs
      */
-    public void resetState() throws Bmv2Exception {
+    public void resetState() throws Bmv2RuntimeException {
 
         try {
             stdClient.bm_reset_state();
         } catch (TException e) {
-            throw new Bmv2Exception(e.getMessage(), e);
+            throw new Bmv2RuntimeException(e.getMessage(), e);
         }
     }
 
@@ -299,10 +374,10 @@
      * Transport/client cache loader.
      */
     private static class ClientLoader
-            extends CacheLoader<DeviceId, Pair<TTransport, Standard.Iface>> {
+            extends CacheLoader<DeviceId, Bmv2ThriftClient> {
 
         @Override
-        public Pair<TTransport, Standard.Iface> load(DeviceId deviceId)
+        public Bmv2ThriftClient load(DeviceId deviceId)
                 throws TTransportException {
             Pair<String, Integer> info = parseDeviceId(deviceId);
             //make the expensive call
@@ -314,7 +389,7 @@
 
             transport.open();
 
-            return ImmutablePair.of(transport, stdClient);
+            return new Bmv2ThriftClient(transport, stdClient);
         }
     }
 
@@ -322,14 +397,13 @@
      * Client cache removal listener. Close the connection on cache removal.
      */
     private static class ClientRemovalListener implements
-            RemovalListener<DeviceId, Pair<TTransport, Standard.Iface>> {
+            RemovalListener<DeviceId, Bmv2ThriftClient> {
 
         @Override
         public void onRemoval(
-                RemovalNotification<DeviceId, Pair<TTransport, Standard.Iface>>
-                        notification) {
+                RemovalNotification<DeviceId, Bmv2ThriftClient> notification) {
             // close the transport connection
-            notification.getValue().getKey().close();
+            notification.getValue().closeTransport();
         }
     }
 }
diff --git a/drivers/bmv2/src/test/java/org/onosproject/drivers/bmv2/Bmv2ModelTest.java b/protocols/bmv2/src/test/java/org/onosproject/bmv2/api/model/Bmv2ModelTest.java
similarity index 93%
rename from drivers/bmv2/src/test/java/org/onosproject/drivers/bmv2/Bmv2ModelTest.java
rename to protocols/bmv2/src/test/java/org/onosproject/bmv2/api/model/Bmv2ModelTest.java
index 666eb74..6550ee9 100644
--- a/drivers/bmv2/src/test/java/org/onosproject/drivers/bmv2/Bmv2ModelTest.java
+++ b/protocols/bmv2/src/test/java/org/onosproject/bmv2/api/model/Bmv2ModelTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2016 Open Networking Laboratory
+ * 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.
@@ -14,17 +14,14 @@
  * limitations under the License.
  */
 
-package org.onosproject.drivers.bmv2;
+package org.onosproject.bmv2.api.model;
 
 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.onosproject.drivers.bmv2.model.Bmv2Model;
-import org.onosproject.drivers.bmv2.model.Bmv2ModelAction;
-import org.onosproject.drivers.bmv2.model.Bmv2ModelHeaderType;
-import org.onosproject.drivers.bmv2.model.Bmv2ModelTable;
+import org.onosproject.bmv2.api.runtime.Bmv2MatchParam;
 
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
@@ -156,7 +153,7 @@
 
         // key match type
         assertThat("Incorrect value for table key match type",
-                table0.keys().get(0).matchType(), is(equalTo("ternary")));
+                   table0.keys().get(0).matchType(), is(equalTo(Bmv2MatchParam.Type.TERNARY)));
 
         // header type
         assertThat("Incorrect value for table key header type",
diff --git a/drivers/bmv2/src/test/resources/simple_pipeline.json b/protocols/bmv2/src/test/resources/simple_pipeline.json
similarity index 100%
rename from drivers/bmv2/src/test/resources/simple_pipeline.json
rename to protocols/bmv2/src/test/resources/simple_pipeline.json
diff --git a/utils/misc/src/main/java/org/onlab/util/ImmutableByteSequence.java b/utils/misc/src/main/java/org/onlab/util/ImmutableByteSequence.java
index 2d10bfb..57171de 100644
--- a/utils/misc/src/main/java/org/onlab/util/ImmutableByteSequence.java
+++ b/utils/misc/src/main/java/org/onlab/util/ImmutableByteSequence.java
@@ -21,6 +21,7 @@
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.Arrays;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static org.apache.commons.lang3.ArrayUtils.reverse;
@@ -62,7 +63,7 @@
      * the passed byte array.
      *
      * @param original a byte array value
-     * @return a new immutable byte buffer
+     * @return a new immutable byte sequence
      */
     public static ImmutableByteSequence copyFrom(byte[] original) {
         checkArgument(original != null && original.length > 0,
@@ -101,7 +102,7 @@
      * Creates a new byte sequence of 8 bytes containing the given long value.
      *
      * @param original a long value
-     * @return a new immutable byte buffer
+     * @return a new immutable byte sequence
      */
     public static ImmutableByteSequence copyFrom(long original) {
         return new ImmutableByteSequence(
@@ -112,7 +113,7 @@
      * Creates a new byte sequence of 4 bytes containing the given int value.
      *
      * @param original an int value
-     * @return a new immutable byte buffer
+     * @return a new immutable byte sequence
      */
     public static ImmutableByteSequence copyFrom(int original) {
         return new ImmutableByteSequence(
@@ -123,7 +124,7 @@
      * Creates a new byte sequence of 2 bytes containing the given short value.
      *
      * @param original a short value
-     * @return a new immutable byte buffer
+     * @return a new immutable byte sequence
      */
     public static ImmutableByteSequence copyFrom(short original) {
         return new ImmutableByteSequence(
@@ -134,7 +135,7 @@
      * Creates a new byte sequence of 1 byte containing the given value.
      *
      * @param original a byte value
-     * @return a new immutable byte buffer
+     * @return a new immutable byte sequence
      */
     public static ImmutableByteSequence copyFrom(byte original) {
         return new ImmutableByteSequence(
@@ -142,6 +143,30 @@
     }
 
     /**
+     * Creates a new byte sequence of the given size where alla bits are 0.
+     *
+     * @param size number of bytes
+     * @return a new immutable byte sequence
+     */
+    public static ImmutableByteSequence ofZeros(int size) {
+        byte[] bytes = new byte[size];
+        Arrays.fill(bytes, (byte) 0);
+        return new ImmutableByteSequence(ByteBuffer.wrap(bytes));
+    }
+
+    /**
+     * Creates a new byte sequence of the given size where alla bits are 1.
+     *
+     * @param size number of bytes
+     * @return a new immutable byte sequence
+     */
+    public static ImmutableByteSequence ofOnes(int size) {
+        byte[] bytes = new byte[size];
+        Arrays.fill(bytes, (byte) 0xFF);
+        return new ImmutableByteSequence(ByteBuffer.wrap(bytes));
+    }
+
+    /**
      * Returns a view of this sequence as a read-only {@link ByteBuffer}.
      * <p>
      * The returned buffer will have position 0, while limit and capacity will