diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFActionBigSwitchVendor.java b/src/main/java/com/bigswitch/floodlight/vendor/OFActionBigSwitchVendor.java
new file mode 100644
index 0000000000000000000000000000000000000000..147820f479bea7596961e29225931f5856118648
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFActionBigSwitchVendor.java
@@ -0,0 +1,70 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.action.OFActionVendor;
+
+public abstract class OFActionBigSwitchVendor extends OFActionVendor {
+    public static int MINIMUM_LENGTH = 12;
+    public static int BSN_VENDOR_ID = OFBigSwitchVendorData.BSN_VENDOR_ID;
+
+    protected int subtype;
+
+    protected OFActionBigSwitchVendor(int subtype) {
+        super();
+        super.setLength((short)MINIMUM_LENGTH);
+        super.setVendor(BSN_VENDOR_ID);
+        this.subtype = subtype;
+    }
+
+    public int getSubtype() {
+        return this.subtype;
+    }
+
+    public void setSubtype(int subtype) {
+        this.subtype = subtype;
+    }
+
+    @Override
+    public void readFrom(ChannelBuffer data) {
+        super.readFrom(data);
+        this.subtype = data.readInt();
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeInt(this.subtype);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 379;
+        int result = super.hashCode();
+        result = prime * result + vendor;
+        result = prime * result + subtype;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (!(obj instanceof OFActionBigSwitchVendor)) {
+            return false;
+        }
+        OFActionBigSwitchVendor other = (OFActionBigSwitchVendor) obj;
+        if (subtype != other.subtype) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "; subtype=" + subtype;
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFActionMirror.java b/src/main/java/com/bigswitch/floodlight/vendor/OFActionMirror.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8a5bbfc153b652286d0601780d24cdffd7de641
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFActionMirror.java
@@ -0,0 +1,98 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+
+public class OFActionMirror extends OFActionBigSwitchVendor {
+    public final static int MINIMUM_LENGTH = 12;
+    public final static int BSN_ACTION_MIRROR = 1;
+
+    protected int destPort;
+    protected int vlanTag;
+    protected byte copyStage;
+    protected byte pad0;
+    protected byte pad1;
+    protected byte pad2;
+
+    public OFActionMirror(short portNumber) {
+        super(BSN_ACTION_MIRROR);
+        super.setLength((short) (OFActionBigSwitchVendor.MINIMUM_LENGTH + OFActionMirror.MINIMUM_LENGTH));
+        this.destPort = portNumber;
+        this.vlanTag = 0;
+        this.copyStage = 0;
+    }
+
+    public int getDestPort() {
+        return destPort;
+    }
+
+    public void setDestPort(int destPort) {
+        this.destPort = destPort;
+    }
+
+    public int getVlanTag() {
+        return vlanTag;
+    }
+
+    public void setVlanTag(int vlanTag) {
+        this.vlanTag = vlanTag;
+    }
+
+    public byte getCopyStage() {
+        return copyStage;
+    }
+
+    public void setCopyStage(byte copyStage) {
+        this.copyStage = copyStage;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + copyStage;
+        result = prime * result + destPort;
+        result = prime * result + pad0;
+        result = prime * result + pad1;
+        result = prime * result + pad2;
+        result = prime * result + vlanTag;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (!super.equals(obj)) return false;
+        if (getClass() != obj.getClass()) return false;
+        OFActionMirror other = (OFActionMirror) obj;
+        if (copyStage != other.copyStage) return false;
+        if (destPort != other.destPort) return false;
+        if (pad0 != other.pad0) return false;
+        if (pad1 != other.pad1) return false;
+        if (pad2 != other.pad2) return false;
+        if (vlanTag != other.vlanTag) return false;
+        return true;
+    }
+
+    @Override
+    public void readFrom(ChannelBuffer data) {
+        super.readFrom(data);
+        this.destPort = data.readInt();
+        this.vlanTag = data.readInt();
+        this.copyStage = data.readByte();
+        this.pad0 = data.readByte();
+        this.pad1 = data.readByte();
+        this.pad2 = data.readByte();
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeInt(this.destPort);
+        data.writeInt(this.vlanTag);
+        data.writeByte(this.copyStage);
+        data.writeByte(this.pad0);
+        data.writeByte(this.pad1);
+        data.writeByte(this.pad2);
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFActionNiciraTtlDecrement.java b/src/main/java/com/bigswitch/floodlight/vendor/OFActionNiciraTtlDecrement.java
new file mode 100644
index 0000000000000000000000000000000000000000..943fb26de2a109c75e05ede2dc2fe8b207e0c9ca
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFActionNiciraTtlDecrement.java
@@ -0,0 +1,28 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class OFActionNiciraTtlDecrement extends OFActionNiciraVendor {
+    public static int MINIMUM_LENGTH_TTL_DECREMENT = 16;
+    public static final short TTL_DECREMENT_SUBTYPE = 18;
+    
+    
+    public OFActionNiciraTtlDecrement() {
+        super(TTL_DECREMENT_SUBTYPE);
+        super.setLength((short)MINIMUM_LENGTH_TTL_DECREMENT);
+    }
+    
+    @Override
+    public void readFrom(ChannelBuffer data) {
+        super.readFrom(data);
+        data.skipBytes(6);  // pad
+    }
+    
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeZero(6);
+    }
+
+    
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFActionNiciraVendor.java b/src/main/java/com/bigswitch/floodlight/vendor/OFActionNiciraVendor.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4d9fa523baff8fb12150d2e5665300b7b4cd39a
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFActionNiciraVendor.java
@@ -0,0 +1,77 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.action.OFActionVendor;
+import org.openflow.vendor.nicira.OFNiciraVendorData;
+
+/**
+ * FIXME: this should really be handled by a consistent parse tree for
+ * different vendor actions but for the time being this works and gets the
+ * job done. 
+ * 
+ * @author gregor
+ *
+ */
+public class OFActionNiciraVendor extends OFActionVendor {
+    public static int MINIMUM_LENGTH = 16;
+    public static int NICIRA_VENDOR_ID = OFNiciraVendorData.NX_VENDOR_ID;
+    
+    protected short subtype;
+
+    protected OFActionNiciraVendor(short subtype) {
+        // We don't allow direct instantiation of this class because its 
+        // minimum length is 16 and the only way to guarantee this is by 
+        // having a subclass that properly adds padding. 
+        super();
+        super.setLength((short)MINIMUM_LENGTH);
+        super.setVendor(NICIRA_VENDOR_ID);
+        this.subtype = subtype;
+    }
+    
+    public short getSubtype() {
+        return this.subtype;
+    }
+    
+    public void setSubtype(short subtype) {
+        this.subtype = subtype;
+    }
+
+    @Override
+    public void readFrom(ChannelBuffer data) {
+        super.readFrom(data);
+        this.subtype = data.readShort();
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeShort(this.subtype);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 379;
+        int result = super.hashCode();
+        result = prime * result + vendor;
+        result = prime * result + subtype;
+        return result;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (!(obj instanceof OFActionNiciraVendor)) {
+            return false;
+        }
+        OFActionNiciraVendor other = (OFActionNiciraVendor) obj;
+        if (subtype != other.subtype) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFActionTunnelDstIP.java b/src/main/java/com/bigswitch/floodlight/vendor/OFActionTunnelDstIP.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9a37efe9b2b46378a2957d982f05894540366d3
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFActionTunnelDstIP.java
@@ -0,0 +1,65 @@
+package com.bigswitch.floodlight.vendor;
+
+import net.floodlightcontroller.packet.IPv4;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class OFActionTunnelDstIP extends OFActionBigSwitchVendor {
+    public final static int MINIMUM_LENGTH_TUNNEL_DST = 16;
+    public  final static int SET_TUNNEL_DST_SUBTYPE = 2;
+
+    protected int dstIPAddr;
+
+    public OFActionTunnelDstIP() {
+        super(SET_TUNNEL_DST_SUBTYPE);
+        super.setLength((short)MINIMUM_LENGTH_TUNNEL_DST);
+    }
+
+    public OFActionTunnelDstIP(int dstIPAddr) {
+        this();
+        this.dstIPAddr = dstIPAddr;
+    }
+
+    public int getTunnelDstIP() {
+        return this.dstIPAddr;
+    }
+
+    public void setTunnelDstIP(int ipAddr) {
+        this.dstIPAddr = ipAddr;
+    }
+
+    @Override
+    public void readFrom(ChannelBuffer data) {
+        super.readFrom(data);
+        this.dstIPAddr = data.readInt();
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeInt(this.dstIPAddr);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + dstIPAddr;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (!super.equals(obj)) return false;
+        if (getClass() != obj.getClass()) return false;
+        OFActionTunnelDstIP other = (OFActionTunnelDstIP) obj;
+        if (dstIPAddr != other.dstIPAddr) return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "; dstIP=" + IPv4.fromIPv4Address(dstIPAddr);
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorActionFactory.java b/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorActionFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b58cabf632df06fbbc187e3f8e0bdf14efa05cd
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorActionFactory.java
@@ -0,0 +1,41 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.action.OFActionVendor;
+import org.openflow.protocol.factory.OFVendorActionFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OFBigSwitchVendorActionFactory implements OFVendorActionFactory {
+    protected static Logger logger =
+            LoggerFactory.getLogger(OFBigSwitchVendorActionFactory.class);
+
+    static class OFActionBigSwitchVendorDemux extends OFActionBigSwitchVendor {
+        OFActionBigSwitchVendorDemux() {
+            super((short) 0);
+        }
+    }
+
+    @Override
+    public OFActionVendor readFrom(ChannelBuffer data) {
+        data.markReaderIndex();
+        OFActionBigSwitchVendor demux = new OFActionBigSwitchVendorDemux();
+        demux.readFrom(data);
+        data.resetReaderIndex();
+
+        switch(demux.getSubtype()) {
+            case OFActionMirror.BSN_ACTION_MIRROR:
+                OFActionMirror mirrorAction = new OFActionMirror((short) 0);
+                mirrorAction.readFrom(data);
+                return mirrorAction;
+            case OFActionTunnelDstIP.SET_TUNNEL_DST_SUBTYPE:
+                OFActionTunnelDstIP tunnelAction = new OFActionTunnelDstIP();
+                tunnelAction.readFrom(data);
+                return tunnelAction;
+            default:
+                logger.error("Unknown BSN vendor action subtype: "+demux.getSubtype());
+                return null;
+        }
+    }
+
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7d34258d077a9a6d13d6d7a928e664f23aaf18e
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorData.java
@@ -0,0 +1,77 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.vendor.OFVendorData;
+
+/**
+ * Base class for vendor data corresponding to BigSwitch vendor extensions
+ * BigSwitch vendor data always starts with a 4-byte integer data type value
+ * 
+ * @author Munish Mehta (munish.mehta@bigswitch.com)
+ */
+public class OFBigSwitchVendorData implements OFVendorData {
+    
+    public static final int BSN_VENDOR_ID = 0x005c16c7;
+ 
+    /**
+     * The value of the integer data type at the beginning of the vendor data
+     */
+    protected int dataType;
+
+    /**
+     * Construct BigSwitch vendor data with the specified data type
+     * @param dataType : the data type value at the beginning (opcode)
+     */
+    public OFBigSwitchVendorData(int dataType) {
+        super();
+        this.dataType = dataType;
+    }
+    
+    /**
+     * Get the data type value at the beginning of the vendor data
+     * @return
+     */
+    public int getDataType() {
+        return dataType;
+    }
+
+    /**
+     * Set the data type value
+     * @param dataType
+     */
+    public void setDataType(int dataType) {
+        this.dataType = dataType;
+    }
+
+    /**
+     * Get the length of the vendor data. This implementation will normally be
+     * the superclass for another class that will override this to return the
+     * overall vendor data length. This implementation just returns the length
+     * of the part that includes the 4-byte integer data type value at the
+     * beginning of the vendor data
+     */
+    @Override
+    public int getLength() {
+        return 4;
+    }
+
+    /**
+     * Read the vendor data from the ChannelBuffer
+     * @param data the channel buffer from which we're deserializing
+     * @param length the length to the end of the enclosing message
+     */
+    @Override
+    public void readFrom(ChannelBuffer data, int length) {
+        dataType = data.readInt();
+    }
+
+    /**
+     * Write the vendor data to the ChannelBuffer
+     * @param data the channel buffer to which we're serializing
+     */
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        data.writeInt(dataType);
+    }
+
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorExtensions.java b/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorExtensions.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b3d069c4a1af871433509094f7a73e001fda17e
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFBigSwitchVendorExtensions.java
@@ -0,0 +1,52 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.openflow.protocol.vendor.OFBasicVendorDataType;
+import org.openflow.protocol.vendor.OFBasicVendorId;
+import org.openflow.protocol.vendor.OFVendorId;
+
+public class OFBigSwitchVendorExtensions {
+    private static boolean initialized = false;
+
+    public static synchronized void initialize() {
+        if (initialized)
+            return;
+    
+        OFBasicVendorId bsnVendorId = 
+                new OFBasicVendorId(OFBigSwitchVendorData.BSN_VENDOR_ID, 4);
+        OFVendorId.registerVendorId(bsnVendorId);
+
+        // register data types used for big tap
+        OFBasicVendorDataType setEntryVendorData =
+                new OFBasicVendorDataType(
+                         OFNetmaskSetVendorData.BSN_SET_IP_MASK_ENTRY,
+                         OFNetmaskSetVendorData.getInstantiable());
+        bsnVendorId.registerVendorDataType(setEntryVendorData);
+
+        OFBasicVendorDataType getEntryVendorDataRequest =
+                new OFBasicVendorDataType(
+                         OFNetmaskGetVendorDataRequest.BSN_GET_IP_MASK_ENTRY_REQUEST,
+                         OFNetmaskGetVendorDataRequest.getInstantiable());
+        bsnVendorId.registerVendorDataType(getEntryVendorDataRequest);
+
+        OFBasicVendorDataType getEntryVendorDataReply =
+                new OFBasicVendorDataType(
+                         OFNetmaskGetVendorDataReply.BSN_GET_IP_MASK_ENTRY_REPLY,
+                         OFNetmaskGetVendorDataReply.getInstantiable());
+        bsnVendorId.registerVendorDataType(getEntryVendorDataReply);
+
+        // register data types used for tunneling
+        OFBasicVendorDataType getIntfIPVendorDataRequest = 
+                new OFBasicVendorDataType(
+                          OFInterfaceIPRequestVendorData.BSN_GET_INTERFACE_IP_REQUEST,
+                          OFInterfaceIPRequestVendorData.getInstantiable());
+        bsnVendorId.registerVendorDataType(getIntfIPVendorDataRequest);
+
+        OFBasicVendorDataType getIntfIPVendorDataReply = 
+                new OFBasicVendorDataType(
+                          OFInterfaceIPReplyVendorData.BSN_GET_INTERFACE_IP_REPLY,
+                          OFInterfaceIPReplyVendorData.getInstantiable());
+        bsnVendorId.registerVendorDataType(getIntfIPVendorDataReply);
+
+        
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFBsnL2TableSetVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFBsnL2TableSetVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..3dd8310148e423889250a281ee240ef6e13f7f3c
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFBsnL2TableSetVendorData.java
@@ -0,0 +1,33 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+public class OFBsnL2TableSetVendorData extends OFBsnL2TableVendorData {
+
+    protected static Instantiable<OFVendorData> instantiableSingleton = 
+        new Instantiable<OFVendorData>() {
+            public OFVendorData instantiate() {
+                return new OFBsnL2TableSetVendorData();
+            }
+        };
+        
+    public static final int BSN_L2_TABLE_SET = 12;
+        
+    /**
+     * @return a subclass of Instantiable<OFVendorData> that instantiates
+     *         an instance of OFBsnL2TableSetVendorData.
+     */
+    public static Instantiable<OFVendorData> getInstantiable() {
+        return instantiableSingleton;
+    }
+    
+    public OFBsnL2TableSetVendorData() {
+        super(BSN_L2_TABLE_SET);
+    }
+    
+    public OFBsnL2TableSetVendorData(boolean l2TableEnabled, 
+                                     short l2TablePriority) {
+        super(BSN_L2_TABLE_SET, l2TableEnabled, l2TablePriority);
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFBsnL2TableVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFBsnL2TableVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..14e6178d1b4793855b1b6ee8d0946c6f87fa79d0
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFBsnL2TableVendorData.java
@@ -0,0 +1,81 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class OFBsnL2TableVendorData extends OFBigSwitchVendorData {
+    /*
+     * uint8_t l2_table_enable;    // 1 == enabled, 0 == disabled
+     * uint8_t pad;
+     * uint16_t l2_table_priority;  // priority of all flows in L2 table
+     * uint8_t pad[4];
+     */
+    protected boolean l2TableEnabled;
+    protected short l2TablePriority;
+    
+    
+    public OFBsnL2TableVendorData(int dataType) {
+        super(dataType);
+        this.l2TableEnabled = false;
+        this.l2TablePriority = (short)0;
+    }
+
+
+    public OFBsnL2TableVendorData(int dataType, boolean l2TableEnabled,
+                                  short l2TablePriority) {
+        super(dataType);
+        this.l2TableEnabled = l2TableEnabled;
+        this.l2TablePriority = l2TablePriority;
+    }
+
+
+    public boolean isL2TableEnabled() {
+        return l2TableEnabled;
+    }
+
+
+    public short getL2TablePriority() {
+        return l2TablePriority;
+    }
+
+
+    public void setL2TableEnabled(boolean l2TableEnabled) {
+        this.l2TableEnabled = l2TableEnabled;
+    }
+
+
+    public void setL2TablePriority(short l2TablePriority) {
+        this.l2TablePriority = l2TablePriority;
+    }
+    
+    
+    @Override
+    public int getLength() {
+        return super.getLength() + 8; // 8 additional bytes
+    }
+    
+    /*
+     * (non-Javadoc)
+     * @see com.bigswitch.floodlight.vendor.OFBigSwitchVendorData#readFrom(org.jboss.netty.buffer.ChannelBuffer, int)
+     */
+    @Override 
+    public void readFrom(ChannelBuffer data, int length) {
+        super.readFrom(data, length);
+        l2TableEnabled = (data.readByte() == 0) ? false : true;
+        data.readByte();  // pad
+        l2TablePriority = data.readShort();
+        data.readInt();   // 4 bad bytes
+    }
+    
+    /*
+     * (non-Javadoc)
+     * @see com.bigswitch.floodlight.vendor.OFBigSwitchVendorData#writeTo(org.jboss.netty.buffer.ChannelBuffer)
+     */
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeByte(isL2TableEnabled() ? 1 : 0);
+        data.writeByte(0);  // pad
+        data.writeShort(l2TablePriority);
+        data.writeInt(0);   // 4 pad bytes
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceIPReplyVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceIPReplyVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..380ba43c299c7ccaaccafbdd846e92ea72a848ef
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceIPReplyVendorData.java
@@ -0,0 +1,124 @@
+package com.bigswitch.floodlight.vendor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+public class OFInterfaceIPReplyVendorData extends OFBigSwitchVendorData {
+    
+    protected List<OFInterfaceVendorData> interfaces;
+    protected int length;
+    
+    protected static Instantiable<OFVendorData> instantiable =
+            new Instantiable<OFVendorData>() {
+                public OFVendorData instantiate() {
+                    return new OFInterfaceIPReplyVendorData();
+                }
+    };
+    
+    /**
+     * @return a subclass of Instantiable<OFVendorData> that instantiates
+     *         an instance of OFInterfaceIPReplyVendorData.
+     */
+    public static Instantiable<OFVendorData> getInstantiable() {
+        return instantiable;
+    }
+
+    /**
+     * Opcode/dataType to reply with IP addresses of all interfaces
+     */
+    public static final int BSN_GET_INTERFACE_IP_REPLY = 10;
+
+    /**
+     * Construct an interface IP reply vendor data 
+     */
+    public OFInterfaceIPReplyVendorData() {
+        super(BSN_GET_INTERFACE_IP_REPLY);   
+    }
+    
+    /**
+     * @return the total length of the vendor-data part of the interface IP reply 
+     * message. The OF header (8B) and vendor (4B) are taken care of by the
+     * OFVendor class MINIMUM_LENGTH. This method returns the length of the 
+     * vendor-extension-subtype (4B) + the length of the interfaces
+     */
+    @Override
+    public int getLength() {
+        return length;
+    }
+    
+    /**
+     * Set the length of this message
+     *
+     * @param length
+     */
+    public void setLength(int length) {
+        this.length = length;
+        
+    }
+    
+    /**
+     * @return the interfaces
+     */
+    public List<OFInterfaceVendorData> getInterfaces() {
+        return interfaces;
+    }
+    
+    /**
+     * @param intfs  the ones to set
+     */
+    public void setInterfaces(List<OFInterfaceVendorData> intfs) {
+        this.interfaces = intfs;
+        if (intfs == null) {
+            this.setLength(super.getLength());
+        } else {
+            this.setLength(super.getLength() + intfs.size()
+                    * OFInterfaceVendorData.MINIMUM_LENGTH);
+        }
+    }
+    
+    /**
+     * Read from the ChannelBuffer
+     * @param data the channel buffer from which we're deserializing
+     * @param length the length to the end of the enclosing message
+     */
+    @Override
+    public void readFrom(ChannelBuffer data, int length) {
+        //datatype read by super class
+        super.readFrom(data, length);
+        
+        if (this.interfaces == null) {
+            this.interfaces = new ArrayList<OFInterfaceVendorData>();
+        } else {
+            this.interfaces.clear();
+        }
+        int intfCount = (length - 4)
+                / OFInterfaceVendorData.MINIMUM_LENGTH;
+        
+        OFInterfaceVendorData intf;
+        for (int i = 0; i < intfCount; ++i) {
+            intf = new OFInterfaceVendorData();
+            intf.readFrom(data);
+            this.interfaces.add(intf);
+        }
+    }
+
+    /**
+     * Write to the ChannelBuffer
+     * @param data the channel buffer to which we're serializing
+     */
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        // datatype written by super class
+        super.writeTo(data);
+        if (this.interfaces != null) {
+            for (OFInterfaceVendorData intf : this.interfaces) {
+                intf.writeTo(data);
+            }
+        }
+    }
+    
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceIPRequestVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceIPRequestVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..9caf6e54ad299e488b217722941d7b4ae057fc72
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceIPRequestVendorData.java
@@ -0,0 +1,64 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+public class OFInterfaceIPRequestVendorData extends OFBigSwitchVendorData {
+ 
+    protected static Instantiable<OFVendorData> instantiable =
+            new Instantiable<OFVendorData>() {
+                public OFVendorData instantiate() {
+                    return new OFInterfaceIPRequestVendorData();
+                }
+    };
+    
+    /**
+     * @return a subclass of Instantiable<OFVendorData> that instantiates
+     *         an instance of OFInterfaceIPRequestVendorData.
+     */
+    public static Instantiable<OFVendorData> getInstantiable() {
+        return instantiable;
+    }
+
+    /**
+     * Opcode/dataType to request IP addresses of all interfaces
+     */
+    public static final int BSN_GET_INTERFACE_IP_REQUEST = 9;
+
+    /**
+     * Construct an interface IP request vendor data 
+     */
+    public OFInterfaceIPRequestVendorData() {
+        super(BSN_GET_INTERFACE_IP_REQUEST);   
+    }
+    
+    /**
+     * @return the total length of the interface IP request message
+     *         the length is already accounted for in the super class 
+     */
+    @Override
+    public int getLength() {
+        return super.getLength();
+    }
+    
+    /**
+     * Read from the ChannelBuffer
+     * @param data the channel buffer from which we're deserializing
+     * @param length the length to the end of the enclosing message
+     */
+    @Override
+    public void readFrom(ChannelBuffer data, int length) {
+        super.readFrom(data, length);
+    }
+    
+    /**
+     * Write to the ChannelBuffer
+     * @param data the channel buffer to which we're serializing
+     */
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+    }
+    
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b6f30de4c677b5c694fb2037b759462c1827c29
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFInterfaceVendorData.java
@@ -0,0 +1,123 @@
+package com.bigswitch.floodlight.vendor;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import net.floodlightcontroller.core.web.serializers.ByteArrayMACSerializer;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class OFInterfaceVendorData {
+    public static int MINIMUM_LENGTH = 32;
+    private static int OFP_ETH_ALEN = 6;
+    private static int OFP_MAX_PORT_NAME_LEN = 16;
+
+    protected byte[] hardwareAddress;
+    protected String name;
+    protected int ipv4Addr;
+    protected int ipv4AddrMask;
+
+    /**
+     * @return the hardwareAddress
+     */
+    @JsonSerialize(using=ByteArrayMACSerializer.class)
+    public byte[] getHardwareAddress() {
+        return hardwareAddress;
+    }
+
+    /**
+     * @param hardwareAddress the hardwareAddress to set
+     */
+    public void setHardwareAddress(byte[] hardwareAddress) {
+        if (hardwareAddress.length != OFP_ETH_ALEN)
+            throw new RuntimeException("Hardware address must have length "
+                    + OFP_ETH_ALEN);
+        this.hardwareAddress = hardwareAddress;
+    }
+
+    public int getIpv4Addr() {
+        return ipv4Addr;
+    }
+
+    public void setIpv4Addr(int ipv4Addr) {
+        this.ipv4Addr = ipv4Addr;
+    }
+
+    public int getIpv4AddrMask() {
+        return ipv4AddrMask;
+    }
+
+    public void setIpv4AddrMask(int ipv4AddrMask) {
+        this.ipv4AddrMask = ipv4AddrMask;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name the name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Write this message's binary format to the specified ByteBuffer
+     * @param data
+     */
+    public void writeTo(ChannelBuffer data) {
+        data.writeBytes(hardwareAddress);
+        data.writeBytes(new byte[] {0, 0});
+
+        try {
+            byte[] name = this.name.getBytes("ASCII");
+            if (name.length < OFP_MAX_PORT_NAME_LEN) {
+                data.writeBytes(name);
+                for (int i = name.length; i < OFP_MAX_PORT_NAME_LEN; ++i) {
+                    data.writeByte((byte) 0);
+                }
+            } else {
+                data.writeBytes(name, 0, 15);
+                data.writeByte((byte) 0);
+            }
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+
+        data.writeInt(ipv4Addr);
+        data.writeInt(ipv4AddrMask);
+    }
+
+    /**
+     * Read this message off the wire from the specified ByteBuffer
+     * @param data
+     */
+    public void readFrom(ChannelBuffer data) {
+        if (this.hardwareAddress == null)
+            this.hardwareAddress = new byte[OFP_ETH_ALEN];
+        data.readBytes(this.hardwareAddress);
+        data.readBytes(new byte[2]);
+
+        byte[] name = new byte[16];
+        data.readBytes(name);
+        // find the first index of 0
+        int index = 0;
+        for (byte b : name) {
+            if (0 == b)
+                break;
+            ++index;
+        }
+        this.name = new String(Arrays.copyOf(name, index),
+                Charset.forName("ascii"));
+        ipv4Addr = data.readInt();
+        ipv4AddrMask = data.readInt();
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorGetVendorDataReply.java b/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorGetVendorDataReply.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8d83b404eb8b3a31d369e3e49fb9a15ed3760c6
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorGetVendorDataReply.java
@@ -0,0 +1,46 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+
+/**
+ * Subclass of OFVendorData 
+ */
+public class OFMirrorGetVendorDataReply extends OFNetmaskVendorData {
+
+
+    protected static Instantiable<OFVendorData> instantiable =
+        new Instantiable<OFVendorData>() {
+        public OFVendorData instantiate() {
+            return new OFMirrorGetVendorDataReply();
+        }
+    };
+
+    /**
+     * @return a subclass of Instantiable<OFVendorData> that instantiates
+     *         an instance of OFNetmaskGetVendorData.
+     */
+    public static Instantiable<OFVendorData> getInstantiable() {
+        return instantiable;
+    }
+
+    /**
+     * Opcode/dataType to represent REPLY of GET_MASK request
+     */
+    public static final int BSN_GET_MIRRORING_REPLY = 5;
+
+    /**
+     * Construct a get network mask vendor data
+     */
+    public OFMirrorGetVendorDataReply() {
+        super(BSN_GET_MIRRORING_REPLY);   
+    }
+    
+    /**
+     * Construct a get network mask vendor data for a specific table entry
+     */
+    public OFMirrorGetVendorDataReply(byte tableIndex, int netMask) {
+        super(BSN_GET_MIRRORING_REPLY, tableIndex, netMask);
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorGetVendorDataRequest.java b/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorGetVendorDataRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6692cdfdde002140a87256f62cdb8cfa7a26f52d
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorGetVendorDataRequest.java
@@ -0,0 +1,46 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+
+/**
+ * Subclass of OFVendorData
+ */
+public class OFMirrorGetVendorDataRequest extends OFNetmaskVendorData {
+
+
+    protected static Instantiable<OFVendorData> instantiable =
+        new Instantiable<OFVendorData>() {
+        public OFVendorData instantiate() {
+            return new OFMirrorGetVendorDataRequest();
+        }
+    };
+
+    /**
+     * @return a subclass of Instantiable<OFVendorData> that instantiates
+     *         an instance of OFNetmaskGetVendorData.
+     */
+    public static Instantiable<OFVendorData> getInstantiable() {
+        return instantiable;
+    }
+
+    /**
+     * Opcode/dataType to request an entry in the switch netmask table
+     */
+    public static final int BSN_GET_MIRRORING_REQUEST = 4;
+
+    /**
+     * Construct a get network mask vendor data
+     */
+    public OFMirrorGetVendorDataRequest() {
+        super(BSN_GET_MIRRORING_REQUEST);   
+    }
+    
+    /**
+     * Construct a get network mask vendor data for a specific table entry
+     */
+    public OFMirrorGetVendorDataRequest(byte tableIndex, int netMask) {
+        super(BSN_GET_MIRRORING_REQUEST, tableIndex, netMask);
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorSetVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorSetVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..5eba6512b7c4f07f9087aabe4f52e5cd0e300bee
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFMirrorSetVendorData.java
@@ -0,0 +1,62 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class OFMirrorSetVendorData extends OFBigSwitchVendorData {
+    
+    /**
+     * Opcode/dataType to set mirroring
+     */
+    public static final int BSN_SET_MIRRORING = 3;
+
+    protected byte reportMirrorPorts;
+    protected byte pad1;
+    protected byte pad2;
+    protected byte pad3;
+    
+    public OFMirrorSetVendorData() {
+        super(BSN_SET_MIRRORING);
+        this.reportMirrorPorts=1;
+    }
+
+    public byte getReportMirrorPorts() {
+        return reportMirrorPorts;
+    }
+
+    public void setReportMirrorPorts(byte report) {
+        this.reportMirrorPorts = report;
+    }
+    
+    /**
+     * @return the total length vendor date
+     */
+    @Override
+    public int getLength() {
+        return super.getLength() + 4; // 4 extra bytes
+    }
+    
+    /**
+     * Read the vendor data from the channel buffer
+     * @param data: the channel buffer from which we are deserializing
+     * @param length: the length to the end of the enclosing message
+     */
+    public void readFrom(ChannelBuffer data, int length) {
+        super.readFrom(data, length);
+        reportMirrorPorts = data.readByte();
+        pad1 = data.readByte();
+        pad2 = data.readByte();
+        pad3 = data.readByte();
+    }
+    
+    /**
+     * Write the vendor data to the channel buffer
+     */
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeByte(reportMirrorPorts);
+        data.writeByte(pad1);
+        data.writeByte(pad2);
+        data.writeByte(pad3);
+    }
+    
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskGetVendorDataReply.java b/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskGetVendorDataReply.java
new file mode 100644
index 0000000000000000000000000000000000000000..62d711020b71f8c962ff2fd068451acb3d9f9ab7
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskGetVendorDataReply.java
@@ -0,0 +1,48 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+
+/**
+ * Subclass of OFVendorData
+ * 
+ * @author munish_mehta
+ */
+public class OFNetmaskGetVendorDataReply extends OFNetmaskVendorData {
+
+
+    protected static Instantiable<OFVendorData> instantiable =
+        new Instantiable<OFVendorData>() {
+        public OFVendorData instantiate() {
+            return new OFNetmaskGetVendorDataReply();
+        }
+    };
+
+    /**
+     * @return a subclass of Instantiable<OFVendorData> that instantiates
+     *         an instance of OFNetmaskGetVendorData.
+     */
+    public static Instantiable<OFVendorData> getInstantiable() {
+        return instantiable;
+    }
+
+    /**
+     * Opcode/dataType to represent REPLY of GET_MASK request
+     */
+    public static final int BSN_GET_IP_MASK_ENTRY_REPLY = 2;
+
+    /**
+     * Construct a get network mask vendor data
+     */
+    public OFNetmaskGetVendorDataReply() {
+        super(BSN_GET_IP_MASK_ENTRY_REPLY);   
+    }
+    
+    /**
+     * Construct a get network mask vendor data for a specific table entry
+     */
+    public OFNetmaskGetVendorDataReply(byte tableIndex, int netMask) {
+        super(BSN_GET_IP_MASK_ENTRY_REPLY, tableIndex, netMask);
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskGetVendorDataRequest.java b/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskGetVendorDataRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d075e9a3b9a87584f92b6ad7ea04442457f5ac9
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskGetVendorDataRequest.java
@@ -0,0 +1,48 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+
+/**
+ * Subclass of OFVendorData
+ * 
+ * @author munish_mehta
+ */
+public class OFNetmaskGetVendorDataRequest extends OFNetmaskVendorData {
+
+
+    protected static Instantiable<OFVendorData> instantiable =
+        new Instantiable<OFVendorData>() {
+        public OFVendorData instantiate() {
+            return new OFNetmaskGetVendorDataRequest();
+        }
+    };
+
+    /**
+     * @return a subclass of Instantiable<OFVendorData> that instantiates
+     *         an instance of OFNetmaskGetVendorData.
+     */
+    public static Instantiable<OFVendorData> getInstantiable() {
+        return instantiable;
+    }
+
+    /**
+     * Opcode/dataType to request an entry in the switch netmask table
+     */
+    public static final int BSN_GET_IP_MASK_ENTRY_REQUEST = 1;
+
+    /**
+     * Construct a get network mask vendor data
+     */
+    public OFNetmaskGetVendorDataRequest() {
+        super(BSN_GET_IP_MASK_ENTRY_REQUEST);   
+    }
+    
+    /**
+     * Construct a get network mask vendor data for a specific table entry
+     */
+    public OFNetmaskGetVendorDataRequest(byte tableIndex, int netMask) {
+        super(BSN_GET_IP_MASK_ENTRY_REQUEST, tableIndex, netMask);
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskSetVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskSetVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..54421c10334acb5d7ca793c699f5005977a3a873
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskSetVendorData.java
@@ -0,0 +1,42 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+public class OFNetmaskSetVendorData extends OFNetmaskVendorData {
+
+
+    protected static Instantiable<OFVendorData> instantiable =
+        new Instantiable<OFVendorData>() {
+        public OFVendorData instantiate() {
+            return new OFNetmaskSetVendorData();
+        }
+    };
+
+    /**
+     * @return a subclass of Instantiable<OFVendorData> that instantiates
+     *         an instance of OFNetmaskSetVendorData.
+     */
+    public static Instantiable<OFVendorData> getInstantiable() {
+        return instantiable;
+    }
+
+    /**
+     * Opcode/dataType to set an entry in the switch netmask table
+     */
+    public static final int BSN_SET_IP_MASK_ENTRY = 0;
+    
+    /**
+     * Construct a get network mask vendor data
+     */
+    public OFNetmaskSetVendorData() {
+        super(BSN_SET_IP_MASK_ENTRY);   
+    }
+    
+    /**
+     * Construct a get network mask vendor data for a specific table entry
+     */
+    public OFNetmaskSetVendorData(byte tableIndex, int netMask) {
+        super(BSN_SET_IP_MASK_ENTRY, tableIndex, netMask);
+    }
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskVendorData.java b/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskVendorData.java
new file mode 100644
index 0000000000000000000000000000000000000000..66539f98e757e8b133eaf04c115557fad8904ebd
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFNetmaskVendorData.java
@@ -0,0 +1,88 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+
+/**
+ * Class that represents the vendor data in the netmask table request
+ * extension implemented by Arista switches
+ * 
+ * @author munish_mehta (munish.mehta@bigswitch.com)
+ */
+
+public class OFNetmaskVendorData extends OFBigSwitchVendorData {
+
+    /**
+     * Table index for set or get of the the entry from netmask table
+     */
+    protected byte tableIndex;
+    protected byte pad1;
+    protected byte pad2;
+    protected byte pad3;
+    protected int  netMask;
+    
+    public OFNetmaskVendorData(int dataType) {
+        super(dataType);
+        this.tableIndex = 0;
+        this.netMask = (int)0xffffffffL;
+    }
+
+    public OFNetmaskVendorData(int dataType, byte table_index, int netmask) {
+        super(dataType);
+        this.tableIndex = table_index;
+        this.netMask = netmask;
+    }
+
+
+    public byte getTableIndex() {
+        return tableIndex;
+    }
+
+    public void setTableIndex(byte tableIndex) {
+        this.tableIndex = tableIndex;
+    }
+
+    public int getNetMask() {
+        return netMask;
+    }
+
+    public void setNetMask(int netMask) {
+        this.netMask = netMask;
+    }
+
+    /**
+     * @return the total length of the netmask vendor data
+     */
+    @Override
+    public int getLength() {
+        return super.getLength() + 8; // 8 extra bytes
+    }
+    
+    /**
+     * Read the vendor data from the channel buffer
+     * @param data: the channel buffer from which we are deserializing
+     * @param length: the length to the end of the enclosing message
+     */
+    public void readFrom(ChannelBuffer data, int length) {
+        super.readFrom(data, length);
+        tableIndex = data.readByte();
+        pad1 = data.readByte();
+        pad2 = data.readByte();
+        pad3 = data.readByte();
+        netMask = data.readInt();
+    }
+    
+    /**
+     * Write the vendor data to the channel buffer
+     */
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeByte(tableIndex);
+        data.writeByte(pad1);
+        data.writeByte(pad2);
+        data.writeByte(pad3);
+        data.writeInt(netMask);
+    }
+    
+
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFNiciraVendorActionFactory.java b/src/main/java/com/bigswitch/floodlight/vendor/OFNiciraVendorActionFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..716373794f263aa3db5a60d316d982f7ce668a5f
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFNiciraVendorActionFactory.java
@@ -0,0 +1,37 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.action.OFActionVendor;
+import org.openflow.protocol.factory.OFVendorActionFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OFNiciraVendorActionFactory implements OFVendorActionFactory {
+    protected static Logger logger =
+            LoggerFactory.getLogger(OFNiciraVendorActionFactory.class);
+
+    static class OFActionNiciraVendorDemux extends OFActionNiciraVendor {
+        OFActionNiciraVendorDemux() {
+            super((short) 0);
+        }
+    }
+
+    @Override
+    public OFActionVendor readFrom(ChannelBuffer data) {
+        data.markReaderIndex();
+        OFActionNiciraVendorDemux demux = new OFActionNiciraVendorDemux();
+        demux.readFrom(data);
+        data.resetReaderIndex();
+
+        switch(demux.getSubtype()) {
+            case OFActionNiciraTtlDecrement.TTL_DECREMENT_SUBTYPE:
+                OFActionNiciraTtlDecrement ttlAction = new OFActionNiciraTtlDecrement();
+                ttlAction.readFrom(data);
+                return ttlAction;
+            default:
+                logger.error("Unknown Nicira vendor action subtype: "+demux.getSubtype());
+                return null;
+        }
+    }
+
+}
diff --git a/src/main/java/com/bigswitch/floodlight/vendor/OFVendorActions.java b/src/main/java/com/bigswitch/floodlight/vendor/OFVendorActions.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b555340cea7abe3364d1c05b7feaa7be0b3ff0d
--- /dev/null
+++ b/src/main/java/com/bigswitch/floodlight/vendor/OFVendorActions.java
@@ -0,0 +1,11 @@
+package com.bigswitch.floodlight.vendor;
+
+import org.openflow.protocol.factory.OFVendorActionRegistry;
+
+public final class OFVendorActions {
+    public static final void registerStandardVendorActions() {
+        OFVendorActionRegistry registry = OFVendorActionRegistry.getInstance();
+        registry.register(OFActionBigSwitchVendor.BSN_VENDOR_ID, new OFBigSwitchVendorActionFactory());
+        registry.register(OFActionNiciraVendor.NICIRA_VENDOR_ID, new OFNiciraVendorActionFactory());
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
index 9b7d3344f7708f4e7c0b6cb7c8d042b90db5bb65..112f30c8d1b192aee16bda5ffd66a8139684459b 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
@@ -612,4 +612,28 @@ public interface IOFSwitch {
      * Set the flow table full flag in the switch
      */
     public void setTableFull(boolean isFull);
+
+    /**
+     * Set the suggested priority to use when installing access flows in
+     * this switch.
+     */
+    public void setAccessFlowPriority(short prio);
+
+    /**
+     * Set the suggested priority to use when installing core flows in
+     * this switch.
+     */
+    public void setCoreFlowPriority(short prio);
+
+    /**
+     * Get the suggested priority to use when installing access flows in
+     * this switch.
+     */
+    public short getAccessFlowPriority();
+
+    /**
+     * Get the suggested priority to use when installing core flows in
+     * this switch.
+     */
+    public short getCoreFlowPriority();
 }
diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java b/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java
index 56b9818022cb7cf255b7aa174237797adb102cf6..8bef78fe80722453e2e4ca690764c0743f333486 100644
--- a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java
+++ b/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java
@@ -104,6 +104,9 @@ public abstract class OFSwitchBase implements IOFSwitch {
     protected long datapathId;
     protected String stringId;
 
+    protected short accessFlowPriority;
+    protected short coreFlowPriority;
+
     /**
      * Members hidden from subclasses
      */
@@ -1504,4 +1507,28 @@ public abstract class OFSwitchBase implements IOFSwitch {
         }
         flowTableFull = isFull;
     }
+
+
+    @Override
+    public short getAccessFlowPriority() {
+        return accessFlowPriority;
+    }
+
+
+    @Override
+    public short getCoreFlowPriority() {
+        return coreFlowPriority;
+    }
+
+
+    @Override
+    public void setAccessFlowPriority(short accessFlowPriority) {
+        this.accessFlowPriority = accessFlowPriority;
+    }
+
+
+    @Override
+    public void setCoreFlowPriority(short coreFlowPriority) {
+        this.coreFlowPriority = coreFlowPriority;
+    }
 }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 53b619f2586b58580a99203372d5d19acb20f0bf..2b424f7475690c53629880004b04d341f7421794 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -202,6 +202,24 @@ public class Controller implements IFloodlightProviderService,
     protected static final String CONTROLLER_INTERFACE_NUMBER = "number";
     protected static final String CONTROLLER_INTERFACE_DISCOVERED_IP = "discovered_ip";
 
+    // FIXME: don't use "forwardingconfig" as table name
+    private static final String FLOW_PRIORITY_TABLE_NAME = "controller_forwardingconfig";
+    private static final String FLOW_COLUMN_PRIMARY_KEY = "id";
+    private static final String FLOW_VALUE_PRIMARY_KEY = "forwarding";
+    private static final String FLOW_COLUMN_ACCESS_PRIORITY = "access_priority";
+    private static final String FLOW_COLUMN_CORE_PRIORITY = "core_priority";
+    private static final String[] FLOW_COLUMN_NAMES = new String[] {
+            FLOW_COLUMN_PRIMARY_KEY,
+            FLOW_COLUMN_ACCESS_PRIORITY,
+            FLOW_COLUMN_CORE_PRIORITY
+    };
+
+    private static final short DEFAULT_ACCESS_PRIORITY = 10;
+    private static final short DEFAULT_CORE_PRIORITY = 1000;
+    private short accessPriority = DEFAULT_ACCESS_PRIORITY;
+    private short corePriority = DEFAULT_CORE_PRIORITY;
+
+
     // Perf. related configuration
     protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
     public static final int BATCH_MAX_SIZE = 100;
@@ -2233,6 +2251,12 @@ public class Controller implements IFloodlightProviderService,
                                              CONTROLLER_ID);
         storageSource.addListener(CONTROLLER_INTERFACE_TABLE_NAME, this);
 
+        storageSource.createTable(FLOW_PRIORITY_TABLE_NAME, null);
+        storageSource.setTablePrimaryKeyName(FLOW_PRIORITY_TABLE_NAME,
+                                             FLOW_COLUMN_PRIMARY_KEY);
+        storageSource.addListener(FLOW_PRIORITY_TABLE_NAME, this);
+        readFlowPriorityConfigurationFromStorage();
+
         // Startup load monitoring
         if (overload_drop) {
             this.loadmonitor.startMonitoring(
@@ -2264,6 +2288,47 @@ public class Controller implements IFloodlightProviderService,
         registerControllerDebugEvents();
     }
 
+    @LogMessageDoc(level="ERROR",
+            message="failed to access storage: {reason}",
+            explanation="Could not retrieve forwarding configuration",
+            recommendation=LogMessageDoc.CHECK_CONTROLLER)
+    private void readFlowPriorityConfigurationFromStorage() {
+        try {
+            Map<String, Object> row;
+            IResultSet resultSet = storageSource.executeQuery(
+                FLOW_PRIORITY_TABLE_NAME, FLOW_COLUMN_NAMES, null, null);
+            if (resultSet == null)
+                return;
+
+            for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) {
+                row = it.next().getRow();
+                if (row.containsKey(FLOW_COLUMN_PRIMARY_KEY)) {
+                    String primary_key = (String) row.get(FLOW_COLUMN_PRIMARY_KEY);
+                    if (primary_key.equals(FLOW_VALUE_PRIMARY_KEY)) {
+                        if (row.containsKey(FLOW_COLUMN_ACCESS_PRIORITY)) {
+                            accessPriority =
+                                Short.valueOf((String) row.get(FLOW_COLUMN_ACCESS_PRIORITY));
+                        }
+                        if (row.containsKey(FLOW_COLUMN_CORE_PRIORITY)) {
+                            corePriority =
+                                    Short.valueOf((String) row.get(FLOW_COLUMN_CORE_PRIORITY));
+                        }
+                    }
+                }
+            }
+        }
+        catch (StorageException e) {
+            log.error("Failed to access storage for forwarding configuration: {}",
+                      e.getMessage());
+        }
+        catch (NumberFormatException e) {
+            // log error, no stack-trace
+            log.error("Failed to read core or access flow priority from " +
+                      "storage. Illegal number: {}", e.getMessage());
+        }
+    }
+
+
     private void registerControllerDebugEvents() {
         if (debugEvents == null) {
             debugEvents = new NullDebugEvent();
@@ -2398,18 +2463,34 @@ public class Controller implements IFloodlightProviderService,
         return retval;
     }
 
+    private static final String FLOW_PRIORITY_CHANGED_AFTER_STARTUP =
+            "Flow priority configuration has changed after " +
+            "controller startup. Restart controller for new " +
+            "configuration to take effect.";
+    @LogMessageDoc(level="WARN",
+            message=FLOW_PRIORITY_CHANGED_AFTER_STARTUP,
+            explanation="A user has changed the priority with which access " +
+                    "and core flows are installed after controller startup. " +
+                    "Changing this setting will only take affect after a " +
+                    "controller restart",
+            recommendation="Restart controller")
     @Override
     public void rowsModified(String tableName, Set<Object> rowKeys) {
         if (tableName.equals(CONTROLLER_INTERFACE_TABLE_NAME)) {
             handleControllerNodeIPChanges();
+        } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) {
+            log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP);
         }
 
+
     }
 
     @Override
     public void rowsDeleted(String tableName, Set<Object> rowKeys) {
         if (tableName.equals(CONTROLLER_INTERFACE_TABLE_NAME)) {
             handleControllerNodeIPChanges();
+        } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) {
+            log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP);
         }
     }
 
@@ -2492,6 +2573,14 @@ public class Controller implements IFloodlightProviderService,
         debugEvents.flushEvents();
     }
 
+    short getAccessFlowPriority() {
+        return accessPriority;
+    }
+
+    short getCoreFlowPriority() {
+        return corePriority;
+    }
+
     /**
      * FOR TESTING ONLY.
      * Dispatch all updates in the update queue until queue is empty
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
index 0d987d1a78f2682e7af937a011131390eb20a799..68f6b8db8181a1b7a33c9ab7388d543abe3ecee7 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
@@ -70,6 +70,9 @@ import org.openflow.vendor.nicira.OFRoleRequestVendorData;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.bigswitch.floodlight.vendor.OFBigSwitchVendorData;
+import com.bigswitch.floodlight.vendor.OFBsnL2TableSetVendorData;
+
 
 
 /**
@@ -83,9 +86,7 @@ class OFChannelHandler
     private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
 
     private static final long DEFAULT_ROLE_TIMEOUT_MS = 10*1000; // 10 sec
-    /**
-     *
-     */
+
     private final Controller controller;
     private final Counters counters;
     private IOFSwitch sw;
@@ -463,15 +464,58 @@ class OFChannelHandler
         /**
          * We are waiting for a features reply message. Once we receive it
          * we send a SetConfig request, barrier, and GetConfig request.
-         * Next stats is WAIT_CONFIG_REPLY
+         * Next stats is WAIT_CONFIG_REPLY or WAIT_SET_L2_TABLE_REPLY
          */
         WAIT_FEATURES_REPLY(false) {
             @Override
             void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
                     throws IOException {
                 h.featuresReply = m;
+                if (m.getTables() > 1) {
+                    log.debug("Have {} table for switch {}", m.getTables(),
+                              h.getSwitchInfoString());
+                    // likely supports L2 table extensions. Send set
+                    h.sendHandshakeL2TableSet();
+                    // TODO: no L2 SET reply yet, so fire and forget the set
+                    // table message and move directly to sendHandshakeConfig
+                    h.sendHandshakeSetConfig();
+                    h.setState(WAIT_CONFIG_REPLY);
+                    //h.setState(WAIT_SET_L2_TABLE_REPLY);
+                } else {
+                    h.sendHandshakeSetConfig();
+                    h.setState(WAIT_CONFIG_REPLY);
+                }
+            }
+            @Override
+            void processOFStatisticsReply(OFChannelHandler h,
+                                          OFStatisticsReply  m)
+                    throws IOException {
+                illegalMessageReceived(h, m);
+            }
+            @Override
+            void processOFError(OFChannelHandler h, OFError m) {
+                logErrorDisconnect(h, m);
+            }
+        },
+
+        WAIT_SET_L2_TABLE_REPLY(false) {
+            @Override void processOFVendor(OFChannelHandler h, OFVendor m)
+                    throws IOException {
+                // TODO: actually parse the response
                 h.sendHandshakeSetConfig();
                 h.setState(WAIT_CONFIG_REPLY);
+            };
+
+            @Override
+            void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) {
+                // do nothing;
+            }
+
+            @Override
+            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
+                    throws IOException {
+                // TODO: we could re-set the features reply
+                illegalMessageReceived(h, m);
             }
             @Override
             void processOFStatisticsReply(OFChannelHandler h,
@@ -479,10 +523,17 @@ class OFChannelHandler
                     throws IOException {
                 illegalMessageReceived(h, m);
             }
+
             @Override
             void processOFError(OFChannelHandler h, OFError m) {
                 logErrorDisconnect(h, m);
             }
+
+            @Override
+            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+                    throws IOException {
+                h.pendingPortStatusMsg.add(m);
+            }
         },
 
         /**
@@ -541,6 +592,14 @@ class OFChannelHandler
 
             @Override
             void processOFError(OFChannelHandler h, OFError m) {
+                if (m.getErrorType() == OFErrorType.OFPET_BAD_REQUEST.getValue()
+                        && m.getErrorCode() ==
+                            OFBadRequestCode.OFPBRC_BAD_VENDOR.ordinal()) {
+                    log.debug("Switch {} has multiple tables but does not " +
+                            "support L2 table extension",
+                            h.getSwitchInfoString());
+                    return;
+                }
                 logErrorDisconnect(h, m);
             }
 
@@ -592,6 +651,8 @@ class OFChannelHandler
                     h.sw.setFloodlightProvider(h.controller);
                     h.sw.setThreadPoolService(h.controller.getThreadPoolService());
                     h.sw.setDebugCounterService(h.controller.getDebugCounter());
+                    h.sw.setAccessFlowPriority(h.controller.getAccessFlowPriority());
+                    h.sw.setCoreFlowPriority(h.controller.getCoreFlowPriority());
                     for (OFPortStatus ps: h.pendingPortStatusMsg)
                         handlePortStatusMessage(h, ps, false);
                     h.pendingPortStatusMsg.clear();
@@ -1251,9 +1312,14 @@ class OFChannelHandler
                    explanation="The specified switch has disconnected.")
     public void channelDisconnected(ChannelHandlerContext ctx,
                                     ChannelStateEvent e) throws Exception {
-        controller.switchDisconnected(this.sw);
         controller.removeSwitchChannel(this);
-        this.sw.setConnected(false);
+        if (this.sw != null) {
+            // TODO: switchDisconnected() will check if we've previously
+            // activated the switch. Nevertheless, we might want to check
+            // here as well.
+            controller.switchDisconnected(this.sw);
+            this.sw.setConnected(false);
+        }
 
         log.info("Disconnected switch {}", getSwitchInfoString());
     }
@@ -1543,6 +1609,23 @@ class OFChannelHandler
         channel.write(Collections.singletonList(m));
     }
 
+    /**
+     * Send an setL2TableSet message to the switch.
+     */
+    private void sendHandshakeL2TableSet() {
+        OFVendor l2TableSet = (OFVendor)
+                BasicFactory.getInstance().getMessage(OFType.VENDOR);
+        l2TableSet.setXid(handshakeTransactionIds--);
+        OFBsnL2TableSetVendorData l2TableSetData =
+                new OFBsnL2TableSetVendorData(true,
+                                              controller.getCoreFlowPriority());
+        l2TableSet.setVendor(OFBigSwitchVendorData.BSN_VENDOR_ID);
+        l2TableSet.setVendorData(l2TableSetData);
+        l2TableSet.setLengthU(OFVendor.MINIMUM_LENGTH +
+                              l2TableSetData.getLength());
+        channel.write(Collections.singletonList(l2TableSet));
+    }
+
     /**
      * Send the configuration requests to tell the switch we want full
      * packets
diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java
index 37519ab8a0eb447cb3317d158a98e86dbb6caf24..ca13841030a5b2c2d39d7df29ab53cbaec9a4c58 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java
@@ -63,6 +63,8 @@ import static org.junit.Assert.*;
 
 
 public class OFChannelHandlerTest {
+    private static final short CORE_PRIORITY = 4242;
+    private static final short ACCESS_PRIORITY = 42;
     private Controller controller;
     private IThreadPoolService threadPool;
     private IDebugCounterService debugCounterService;
@@ -92,7 +94,7 @@ public class OFChannelHandlerTest {
                 .getMessage(OFType.FEATURES_REPLY);
         featuresReply.setDatapathId(0x42L);
         featuresReply.setBuffers(1);
-        featuresReply.setTables((byte)2);
+        featuresReply.setTables((byte)1);
         featuresReply.setCapabilities(3);
         featuresReply.setActions(4);
         List<OFPhysicalPort> ports = new ArrayList<OFPhysicalPort>();
@@ -206,14 +208,7 @@ public class OFChannelHandlerTest {
         verify(controller);
         reset(controller);
 
-        setupMessageEvent(messages);
-
-        // mock controller
-        controller.flushAll();
-        expectLastCall().atLeastOnce();
-        replay(controller);
-        handler.messageReceived(ctx, messageEvent);
-        verify(controller);
+        sendMessageToHandlerNoControllerReset(messages);
     }
 
     /** reset, setup, and replay the messageEvent mock for the given
@@ -516,6 +511,11 @@ public class OFChannelHandlerTest {
         expectLastCall().andReturn(cfg.dpid).atLeastOnce();
         sw.isWriteThrottleEnabled();  // used for log message only
         expectLastCall().andReturn(false).anyTimes();
+        sw.setAccessFlowPriority(ACCESS_PRIORITY);
+        expectLastCall().once();
+        sw.setCoreFlowPriority(CORE_PRIORITY);
+        expectLastCall().once();
+
         if (cfg.isPresent)
             sw.setAttribute(IOFSwitch.SWITCH_IS_CORE_SWITCH, cfg.isCoreSwitch);
         replay(sw);
@@ -530,6 +530,10 @@ public class OFChannelHandlerTest {
                 .andReturn(threadPool).once();
         expect(controller.getOFSwitchInstance(eq(desc)))
                 .andReturn(sw).once();
+        expect(controller.getCoreFlowPriority())
+                .andReturn(CORE_PRIORITY).once();
+        expect(controller.getAccessFlowPriority())
+                .andReturn(ACCESS_PRIORITY).once();
         controller.addSwitchChannelAndSendInitialRole(handler);
         expectLastCall().once();
         expect(controller.getStorageSourceService())
diff --git a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
index b527e4a1e21a59d29bd8fd6c2df8a29211c4a4b0..bfc6d5bfde78094ef8f983f8228944617b5d2d50 100644
--- a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
+++ b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
@@ -455,6 +455,29 @@ public class OFMessageDamperMockSwitch implements IOFSwitch {
 
     @Override
     public void setTableFull(boolean isFull) {
+        fail("Unexpected method call");
         // TODO Auto-generated method stub
     }
+
+    @Override
+    public void setAccessFlowPriority(short prio) {
+        fail("Unexpected method call");
+    }
+
+    @Override
+    public void setCoreFlowPriority(short prio) {
+        fail("Unexpected method call");
+    }
+
+    @Override
+    public short getAccessFlowPriority() {
+        fail("Unexpected method call");
+        return 0;
+    }
+
+    @Override
+    public short getCoreFlowPriority() {
+        fail("Unexpected method call");
+        return 0;
+    }
 }