diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
index 6b165b5cab61b015996b90c3d9fd5af976e7bc38..7f3463bddb7f97410f1252afd51dd8021b16726d 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
@@ -2,7 +2,9 @@ package net.floodlightcontroller.core.internal;
 
 import java.io.IOException;
 import java.nio.channels.ClosedChannelException;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.RejectedExecutionException;
 
@@ -20,6 +22,7 @@ import org.jboss.netty.handler.timeout.IdleStateEvent;
 import org.jboss.netty.handler.timeout.IdleStateHandler;
 import org.jboss.netty.handler.timeout.ReadTimeoutException;
 import org.jboss.netty.util.Timer;
+
 import net.floodlightcontroller.core.IOFConnectionBackend;
 import net.floodlightcontroller.core.OFConnection;
 import net.floodlightcontroller.core.annotations.LogMessageDoc;
@@ -29,6 +32,7 @@ import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHa
 import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineIdleReadTimeout;
 import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineIdleWriteTimeout;
 import net.floodlightcontroller.debugcounter.IDebugCounterService;
+
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 import org.projectfloodlight.openflow.protocol.OFEchoReply;
 import org.projectfloodlight.openflow.protocol.OFEchoRequest;
@@ -39,9 +43,15 @@ import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
 import org.projectfloodlight.openflow.protocol.OFFeaturesRequest;
 import org.projectfloodlight.openflow.protocol.OFHello;
+import org.projectfloodlight.openflow.protocol.OFHelloElem;
+import org.projectfloodlight.openflow.protocol.OFHelloElemVersionbitmap;
 import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
 import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.ver13.OFHelloElemTypeSerializerVer13;
+import org.projectfloodlight.openflow.protocol.ver14.OFHelloElemTypeSerializerVer14;
 import org.projectfloodlight.openflow.types.OFAuxId;
+import org.projectfloodlight.openflow.types.U32;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,10 +72,11 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
 	private Channel channel;
 	private final Timer timer;
 	private volatile OFChannelState state;
-	private OFFactory factory = OFFactories.getFactory(OFVersion.OF_14);
+	private OFFactory factory;
 	private OFFeaturesReply featuresReply;
 	private volatile OFConnection connection;
 	private final IDebugCounterService debugCounters;
+	private final List<U32> ofBitmaps;
 
 	/** transaction Ids to use during handshake. Since only one thread
 	 * calls into the OFChannelHandler we don't need atomic.
@@ -111,6 +122,10 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
 			// we only expect features reply in the WAIT_FEATURES_REPLY state
 			illegalMessageReceived(m);
 		}
+		
+		void processOFPortStatus(OFPortStatus m) {
+			unhandledMessageReceived(m);
+		}
 
 		private final boolean channelHandshakeComplete;
 
@@ -253,13 +268,16 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
 				case EXPERIMENTER:
 					processOFExperimenter((OFExperimenter)m);
 					break;
-				/* echos can be sent at any time */
+					/* echos can be sent at any time */
 				case ECHO_REPLY:
 					processOFEchoReply((OFEchoReply)m);
 					break;
 				case ECHO_REQUEST:
 					processOFEchoRequest((OFEchoRequest)m);
 					break;
+				case PORT_STATUS:
+					processOFPortStatus((OFPortStatus)m);
+					break;
 				default:
 					illegalMessageReceived(m);
 					break;
@@ -305,14 +323,49 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
 
 		@Override
 		void processOFHello(OFHello m) throws IOException {
-			OFVersion version = m.getVersion();
-			/* Choose the lower of the two supported versions. */
-			if (version.compareTo(factory.getVersion()) < 0) {
-				factory = OFFactories.getFactory(version);
+			OFVersion theirVersion = m.getVersion();
+			OFVersion commonVersion = null;
+			/* First, check if there's a version bitmap supplied. WE WILL ALWAYS HAVE a controller-provided version bitmap. */
+			if (theirVersion.compareTo(OFVersion.OF_13) >= 0 && !m.getElements().isEmpty()) {
+				List<U32> bitmaps = new ArrayList<U32>();
+				List<OFHelloElem> elements = m.getElements();
+				/* Grab all bitmaps supplied */
+				for (OFHelloElem e : elements) {
+					if (m.getVersion().equals(OFVersion.OF_13) 
+							&& e.getType() == OFHelloElemTypeSerializerVer13.VERSIONBITMAP_VAL) {
+						bitmaps.addAll(((OFHelloElemVersionbitmap) e).getBitmaps());
+					} else if (m.getVersion().equals(OFVersion.OF_14) 
+							&& e.getType() == OFHelloElemTypeSerializerVer14.VERSIONBITMAP_VAL) {
+						bitmaps.addAll(((OFHelloElemVersionbitmap) e).getBitmaps());
+					}
+				}
+				/* Lookup highest, common supported OpenFlow version */
+				commonVersion = computeOFVersionFromBitmap(bitmaps);
+				if (commonVersion == null) {
+					log.error("Could not negotiate common OpenFlow version for {} with greatest version bitmap algorithm.", channel.getRemoteAddress());
+					channel.disconnect();
+					return;
+				} else {
+					log.info("Negotiated OpenFlow version of {} for {} with greatest version bitmap algorithm.", commonVersion.toString(), channel.getRemoteAddress());
+					factory = OFFactories.getFactory(commonVersion);
+					OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class);
+					decoder.setVersion(commonVersion);
+				}
+			}
+			/* If there's not a bitmap present, choose the lower of the two supported versions. */
+			else if (theirVersion.compareTo(factory.getVersion()) < 0) {
+				log.info("Negotiated down to switch OpenFlow version of {} for {} using lesser hello header algorithm.", theirVersion.toString(), channel.getRemoteAddress());
+				factory = OFFactories.getFactory(theirVersion);
+				OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class);
+				decoder.setVersion(theirVersion);
 			} /* else The controller's version is < or = the switch's, so keep original controller factory. */
-			
-			OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class);
-			decoder.setVersion(version);
+			else if (theirVersion.equals(factory.getVersion())) {
+				log.info("Negotiated equal OpenFlow version of {} for {} using lesser hello header algorithm.", factory.getVersion().toString(), channel.getRemoteAddress());
+			}
+			else {
+				log.info("Negotiated down to controller OpenFlow version of {} for {} using lesser hello header algorithm.", factory.getVersion().toString(), channel.getRemoteAddress());
+			}
+
 			setState(new WaitFeaturesReplyState());
 		}
 
@@ -341,6 +394,37 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
 			setState(new CompleteState());
 
 		}
+
+		@Override
+		void processOFHello(OFHello m) throws IOException {
+			/*
+			 * Brocade switches send a second hello after
+			 * the controller responds with its hello. This
+			 * might be to confirm the protocol version used,
+			 * but isn't defined in the OF specification.
+			 * 
+			 * We will ignore such hello messages assuming
+			 * the version of the hello is correct according
+			 * to the algorithm in the spec.
+			 * 
+			 * TODO Brocade also sets the XID of this second
+			 * hello as the same XID the controller used.
+			 * Checking for this might help to assure we're
+			 * really dealing with the situation we think
+			 * we are.
+			 */
+			if (m.getVersion().equals(factory.getVersion())) {
+				log.warn("Ignoring second hello from {} in state {}. Might be a Brocade.", channel.getRemoteAddress(), state.toString());
+			} else {
+				super.processOFHello(m); /* Versions don't match as they should; abort */
+			}
+		}
+		
+		@Override
+		void processOFPortStatus(OFPortStatus m) {
+			log.warn("Ignoring PORT_STATUS message from {} during OpenFlow channel establishment. Ports will be explicitly queried in a later state.", channel.getRemoteAddress());
+		}
+
 		@Override
 		void enterState() throws IOException {
 			sendFeaturesRequest();
@@ -402,7 +486,9 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
 			@Nonnull INewOFConnectionListener newConnectionListener,
 			@Nonnull ChannelPipeline pipeline,
 			@Nonnull IDebugCounterService debugCounters,
-			@Nonnull Timer timer) {
+			@Nonnull Timer timer,
+			@Nonnull List<U32> ofBitmaps,
+			@Nonnull OFFactory defaultFactory) {
 
 		Preconditions.checkNotNull(switchManager, "switchManager");
 		Preconditions.checkNotNull(newConnectionListener, "connectionOpenedListener");
@@ -416,10 +502,45 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
 		this.counters = switchManager.getCounters();
 		this.state = new InitState();
 		this.timer = timer;
+		this.ofBitmaps = ofBitmaps;
+		this.factory = defaultFactory;
 
 		log.debug("constructor on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this)));
 	}
 
+	/**
+	 * Determine the highest supported version of OpenFlow in common
+	 * between both our OFVersion bitmap and the switch's.
+	 * 
+	 * @param theirs, the version bitmaps of the switch
+	 * @return the highest OFVersion in common b/t the two
+	 */
+	private OFVersion computeOFVersionFromBitmap(List<U32> theirs) {		
+		Iterator<U32> theirsItr = theirs.iterator();
+		Iterator<U32> oursItr = ofBitmaps.iterator();
+		OFVersion version = null;
+		int pos = 0;
+		int size = 32;
+		while (theirsItr.hasNext() && oursItr.hasNext()) {
+			int t = theirsItr.next().getRaw();
+			int o = oursItr.next().getRaw();
+
+			int common = t & o; /* Narrow down the results to the common bits */
+			for (int i = 0; i < size; i++) { /* Iterate over and locate the 1's */
+				int tmp = common & (1 << i); /* Select the bit of interest, 0-31 */
+				if (tmp != 0) { /* Is the version of this bit in common? */
+					for (OFVersion v : OFVersion.values()) { /* Which version does this bit represent? */
+						if (v.getWireVersion() == i + (size * pos)) {
+							version = v;
+						}
+					}
+				}
+			}
+			pos++; /* OFVersion position. 1-31 = 1, 32 - 63 = 2, etc. Inc at end so it starts at 0. */
+		}
+		return version;
+	}
+
 	/**
 	 * Determines if the entire switch handshake is complete (channel+switch).
 	 * If the channel handshake is complete the call is forwarded to the
@@ -733,10 +854,13 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
 	 */
 	private void sendHelloMessage() throws IOException {
 		// Send initial hello message
-		// FIXME:LOJI: Haven't negotiated version yet, assume 1.3
+		List<OFHelloElem> he = new ArrayList<OFHelloElem>();
+		he.add(factory.buildHelloElemVersionbitmap()
+						.setBitmaps(ofBitmaps)
+						.build());
 		OFHello.Builder builder = factory.buildHello()
-				.setXid(handshakeTransactionIds--);
-		// FIXME: Need to add code here to set the version bitmap hello element
+				.setXid(handshakeTransactionIds--)
+				.setElements(he);
 		OFHello m = builder.build();
 		channel.write(Collections.singletonList(m));
 		log.debug("Send hello: {}", m);
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
index 99a1c4e80585d87a9f9297e7a5089a629644c8ca..532e895ef7b80a7f9ce74310004e656c1af411ca 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
@@ -3,8 +3,11 @@ package net.floodlightcontroller.core.internal;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -52,6 +55,7 @@ import net.floodlightcontroller.debugevent.IEventCategory;
 import net.floodlightcontroller.debugevent.MockDebugEventService;
 
 import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.projectfloodlight.openflow.protocol.OFFactories;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
 import org.projectfloodlight.openflow.protocol.OFMessage;
@@ -60,6 +64,7 @@ import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.types.DatapathId;
 import org.projectfloodlight.openflow.types.OFAuxId;
 import org.projectfloodlight.openflow.types.TableId;
+import org.projectfloodlight.openflow.types.U32;
 import org.sdnplatform.sync.IStoreClient;
 import org.sdnplatform.sync.IStoreListener;
 import org.sdnplatform.sync.ISyncService;
@@ -107,6 +112,9 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen
 	protected static Map<DatapathId, TableId> forwardToControllerFlowsUpToTableByDpid;
 	protected static TableId forwardToControllerFlowsUpToTable = TableId.of(4); /* this should cover most HW switches that have a couple SW-based flow tables */
 
+	protected static List<U32> ofBitmaps;
+	protected static OFFactory defaultFactory;
+	
 	private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers;
 	private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches;
 	private ConcurrentHashMap<DatapathId, IOFSwitch> syncedSwitches;
@@ -770,6 +778,127 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen
 		 * By default, 
 		 */
 		forwardToControllerFlowsUpToTableByDpid = jsonToSwitchTableIdMap(configParams.get("maxTableToReceiveTableMissFlowPerDpid"));
+	
+		/*
+		 * Get config to determine what versions of OpenFlow we will
+		 * support. The versions will determine the hello's header
+		 * version as well as the OF1.3.1 version bitmap contents.
+		 */
+		String protocols = configParams.get("supportedOpenFlowVersions");
+		Set<OFVersion> ofVersions = new HashSet<OFVersion>();
+		if (protocols != null && !protocols.isEmpty()) {
+			protocols = protocols.toLowerCase();
+			/* 
+			 * Brute-force check for all known versions. 
+			 */
+			if (protocols.contains("1.0") || protocols.contains("10")) {
+				ofVersions.add(OFVersion.OF_10);
+			}
+			if (protocols.contains("1.1") || protocols.contains("11")) {
+				ofVersions.add(OFVersion.OF_11);
+			}
+			if (protocols.contains("1.2") || protocols.contains("12")) {
+				ofVersions.add(OFVersion.OF_12);
+			}
+			if (protocols.contains("1.3") || protocols.contains("13")) {
+				ofVersions.add(OFVersion.OF_13);
+			}
+			if (protocols.contains("1.4") || protocols.contains("14")) {
+				ofVersions.add(OFVersion.OF_14);
+			}
+			/*
+			 * TODO This will need to be updated if/when 
+			 * Loxi is updated to support > 1.4.
+			 * 
+			 * if (protocols.contains("1.5") || protocols.contains("15")) {
+			 *     ofVersions.add(OFVersion.OF_15);
+			 * }
+			 */
+		} else {
+			log.warn("Supported OpenFlow versions not specified. Using Loxi-defined {}", OFVersion.values());
+			ofVersions.addAll(Arrays.asList(OFVersion.values()));
+		}
+		/* Sanity check */
+		if (ofVersions.isEmpty()) {
+			throw new IllegalStateException("OpenFlow version list should never be empty at this point. Make sure it's being populated in OFSwitchManager's init function.");
+		}
+		defaultFactory = computeInitialFactory(ofVersions);
+		ofBitmaps = computeOurVersionBitmaps(ofVersions);
+	}
+	
+	/**
+	 * Find the max version supplied in the supported
+	 * versions list and use it as the default, which
+	 * will subsequently be used in our hello message
+	 * header's version field.
+	 * 
+	 * The factory can be later "downgraded" to a lower
+	 * version depending on what's computed during the
+	 * version-negotiation part of the handshake.
+	 * 
+	 * Assumption: The Set of OFVersion ofVersions
+	 * variable has been set already and is NOT EMPTY.
+	 * 
+	 * @return the highest-version OFFactory we support
+	 */
+	private OFFactory computeInitialFactory(Set<OFVersion> ofVersions) {
+		/* This should NEVER happen. Double-checking. */
+		if (ofVersions == null || ofVersions.isEmpty()) {
+			throw new IllegalStateException("OpenFlow version list should never be null or empty at this point. Make sure it's set in the OFSwitchManager.");
+		}
+		OFVersion highest = null;
+		for (OFVersion v : ofVersions) {
+			if (highest == null) {
+				highest = v;
+			} else if (v.compareTo(highest) > 0) {
+				highest = v;
+			}
+		}
+		/* 
+		 * This assumes highest != null, which
+		 * it won't be if the list of versions
+		 * is not empty.
+		 */
+		return OFFactories.getFactory(highest);
+	}
+	
+	/**
+	 * Based on the list of OFVersions provided as input (or from Loxi),
+	 * create a list of bitmaps for use in version negotiation during a
+	 * cross-version OpenFlow handshake where both parties support 
+	 * OpenFlow versions >= 1.3.1.
+	 * 
+	 * Type Set is used as input to guarantee all unique versions.
+	 * 
+	 * @param ofVersions, the list of bitmaps. Supply to an OFHello message.
+	 * @return list of bitmaps for the versions of OpenFlow we support
+	 */
+	private List<U32> computeOurVersionBitmaps(Set<OFVersion> ofVersions) {
+		/* This should NEVER happen. Double-checking. */
+		if (ofVersions == null || ofVersions.isEmpty()) {
+			throw new IllegalStateException("OpenFlow version list should never be null or empty at this point. Make sure it's set in the OFSwitchManager.");
+		}
+		
+		int pos = 1; /* initial bitmap in list */
+		int size = 32; /* size of a U32 */
+		int tempBitmap = 0; /* maintain the current bitmap we're working on */
+		List<U32> bitmaps = new ArrayList<U32>();
+		ArrayList<OFVersion> sortedVersions = new ArrayList<OFVersion>(ofVersions);
+		Collections.sort(sortedVersions);
+		for (OFVersion v : sortedVersions) {
+			/* Move on to another bitmap */
+			if (v.getWireVersion() > pos * size - 1 ) {
+				bitmaps.add(U32.ofRaw(tempBitmap));
+				tempBitmap = 0;
+				pos++;
+			}
+			tempBitmap = tempBitmap | (1 << (v.getWireVersion() % size));
+		}
+		if (tempBitmap != 0) {
+			bitmaps.add(U32.ofRaw(tempBitmap));
+		}
+		log.info("Computed OpenFlow version bitmap as {}", Arrays.asList(tempBitmap));
+		return bitmaps;
 	}
 
 	private static Map<DatapathId, TableId> jsonToSwitchTableIdMap(String json) {
@@ -871,9 +1000,9 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen
 			bootstrap.setOption("child.keepAlive", true);
 			bootstrap.setOption("child.tcpNoDelay", true);
 			bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
-
-			ChannelPipelineFactory pfact = useSsl ? new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService, keyStore, keyStorePassword) :
-				new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService);
+			
+			ChannelPipelineFactory pfact = useSsl ? new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService, ofBitmaps, defaultFactory, keyStore, keyStorePassword) :
+				new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService, ofBitmaps, defaultFactory);
 
 			bootstrap.setPipelineFactory(pfact);
 			InetSocketAddress sa = new InetSocketAddress(floodlightProvider.getOFPort());
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java b/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java
index 7dbcbf32eb6869671a4859fed538986016ef1092..11827d02fb50a490c7661179bab38e9b2b46292a 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java
@@ -19,6 +19,7 @@ package net.floodlightcontroller.core.internal;
 
 import java.io.FileInputStream;
 import java.security.KeyStore;
+import java.util.List;
 
 import javax.annotation.Nonnull;
 import javax.net.ssl.KeyManager;
@@ -36,6 +37,8 @@ import org.jboss.netty.handler.timeout.IdleStateHandler;
 import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
 import org.jboss.netty.util.ExternalResourceReleasable;
 import org.jboss.netty.util.Timer;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.types.U32;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -56,14 +59,20 @@ implements ChannelPipelineFactory, ExternalResourceReleasable {
 	protected IDebugCounterService debugCounters;
 	private String keyStore;
 	private String keyStorePassword;
+	private OFFactory defaultFactory;
+	private List<U32> ofBitmaps;
 
 	private void init(IOFSwitchManager switchManager, Timer timer,
 			INewOFConnectionListener connectionListener,
-			IDebugCounterService debugCounters) {
+			IDebugCounterService debugCounters,
+			@Nonnull List<U32> ofBitmaps,
+			@Nonnull OFFactory defaultFactory) {
 		this.switchManager = switchManager;
 		this.connectionListener = connectionListener;
 		this.timer = timer;
 		this.debugCounters = debugCounters;
+		this.defaultFactory = defaultFactory;
+		this.ofBitmaps = ofBitmaps;
 		this.idleHandler = new IdleStateHandler(
 				timer,
 				PipelineIdleReadTimeout.MAIN,
@@ -74,9 +83,11 @@ implements ChannelPipelineFactory, ExternalResourceReleasable {
 
 	public OpenflowPipelineFactory(IOFSwitchManager switchManager, Timer timer,
 			INewOFConnectionListener connectionListener,
-			IDebugCounterService debugCounters) {
+			IDebugCounterService debugCounters,
+			@Nonnull List<U32> ofBitmaps,
+			@Nonnull OFFactory defaultFactory) {
 		super();
-		init(switchManager,timer, connectionListener, debugCounters);
+		init(switchManager,timer, connectionListener, debugCounters, ofBitmaps, defaultFactory);
 		this.keyStore = null;
 		this.keyStorePassword = null;
 	}
@@ -84,9 +95,11 @@ implements ChannelPipelineFactory, ExternalResourceReleasable {
 	public OpenflowPipelineFactory(IOFSwitchManager switchManager, Timer timer,
 			INewOFConnectionListener connectionListener,
 			IDebugCounterService debugCounters,
+			@Nonnull List<U32> ofBitmaps,
+			@Nonnull OFFactory defaultFactory,
 			@Nonnull String keyStore, @Nonnull String keyStorePassword) {
 		super();
-		init(switchManager,timer, connectionListener, debugCounters);   
+		init(switchManager,timer, connectionListener, debugCounters, ofBitmaps, defaultFactory);   
 		this.keyStore = keyStore;
 		this.keyStorePassword = keyStorePassword;
 	}
@@ -98,7 +111,9 @@ implements ChannelPipelineFactory, ExternalResourceReleasable {
 				connectionListener,
 				pipeline,
 				debugCounters,
-				timer);
+				timer,
+				ofBitmaps,
+				defaultFactory);
 
 		if (keyStore != null && keyStorePassword != null) {
 			try {
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OXMSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OXMSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0271d6838aec13d8ce97ec389ad5aeb6991f228
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OXMSerializer.java
@@ -0,0 +1,436 @@
+package net.floodlightcontroller.core.web.serializers;
+
+import net.floodlightcontroller.util.MatchUtils;
+
+import org.projectfloodlight.openflow.protocol.ver14.OFOxmClassSerializerVer14;
+import org.projectfloodlight.openflow.types.ArpOpcode;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.ICMPv4Code;
+import org.projectfloodlight.openflow.types.ICMPv4Type;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IPv6Address;
+import org.projectfloodlight.openflow.types.IPv6FlowLabel;
+import org.projectfloodlight.openflow.types.IpDscp;
+import org.projectfloodlight.openflow.types.IpEcn;
+import org.projectfloodlight.openflow.types.IpProtocol;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFBooleanValue;
+import org.projectfloodlight.openflow.types.OFMetadata;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TransportPort;
+import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U64;
+import org.projectfloodlight.openflow.types.U8;
+import org.projectfloodlight.openflow.types.VlanPcp;
+import org.projectfloodlight.openflow.types.VlanVid;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
+/**
+ * A handy class to convert OXMs (and NXMs) to and from
+ * their IDs (U32=[class]+[field]+[has_mask]+[length])
+ * and their string representations. The strings are
+ * defined in {@link net.floodlightcontroller.util.MatchUtils},
+ * with the exception of some unique NXMs and OpenFlow 1.5 OXMs 
+ * not technically supported by Loxi/Floodlight yet. Any NXM
+ * string is prefixed with an "nxm_" followed by the string
+ * used for the corresponding OXM. For example, an ingress port
+ * OXM is "in_port", while the NXM version is "nxm_in_port".
+ * 
+ * Any unique NXM without an OXM counterpart is assigned a string
+ * to inform of the NXM. For example, NXM 33, "nxm_pkt_mark", marks
+ * or matches on marked packets as Linux IP tables can do. This is
+ * not supported in the OpenFlow spec, thus the NXM is assigned the
+ * string "nxm_pkt_mark" within this class and does not have a string
+ * predefined in {@link net.floodlightcontroller.util.MatchUtils}.
+ * 
+ * Any OXM with the HAS_MASKED bit set will have it's string
+ * representation appended with an "_masked" or the string defined in
+ * the STR_MASKED class variable below.
+ * 
+ * As an implementation note, a Google BiMap is used as the storage
+ * mechanism. This allows fast lookup in both directions from U32 to 
+ * String or from String back to U32. Note that unique keys AND values
+ * are required in a BiMap.
+ * 
+ * @author Ryan Izard, rizard@g.clemson.edu, ryan.izard@bigswitch.com
+ *
+ */
+public class OXMSerializer {	
+	
+	/*
+	 * OXM IDs for OpenFlow versions 1.5 and below are the same, 
+	 * where each version simply adds to the already populated
+	 * list of OXM IDs. (IDs don't change b/t OF versions.)
+	 * As such, we'll assume OF1.4 here, which includes 1.3.
+	 * 
+	 * TODO Later, when Loxi supports 1.5, we'll change to
+	 * OFOxmClassSerializerVer15.
+	 */
+	
+	/* String constants */
+	private static final String STR_MASKED = "_masked";
+	private static final String STR_NXM = "nxm_";
+	
+	/* Bit shifting constants */
+	private static final int SHIFT_FIELD = 9;
+	private static final int SHIFT_CLASS = 16;
+	private static final int SHIFT_HAS_MASK = 8;
+	
+	/* Mask present bit */
+	private static final int MASKED = (1 << SHIFT_HAS_MASK);
+	
+	/* Classes */
+	private static final int OF_BASIC = (OFOxmClassSerializerVer14.OPENFLOW_BASIC_VAL << SHIFT_CLASS) & 0xFFffFFff;
+	//TODO private static final int OF_PKT_REG = (0x8001 << SHIFT_CLASS) & 0xFFffFFff;
+	private static final int NXM_0 = (OFOxmClassSerializerVer14.NXM_0_VAL << SHIFT_CLASS) & 0xFFffFFff;
+	private static final int NXM_1 = (OFOxmClassSerializerVer14.NXM_1_VAL << SHIFT_CLASS) & 0xFFffFFff;
+	
+	/* The bi-directional map we'll use to make this process more efficient */
+	private static final BiMap<U32, String> map = HashBiMap.create();
+	static { 
+		/*
+		 * OXM header is 4 bytes as follows, where C=oxm_class,
+		 * F=oxm_field, M=has_mask, and L=data_length.
+		 * 
+		 * CCCC CCCC CCCC CCCC FFFF FFFM LLLL LLLL
+		 * 
+		 * The OXM class has already been shifted to the proper
+		 * position and is represented as an integer (4 bytes),
+		 * but we need to shift the OXM field over. The length
+		 * does not need to be shifted.
+		 * 
+		 */
+		
+		/*
+		 * OpenFlow Basic OXM Definitions
+		 */
+		map.put(U32.ofRaw(OF_BASIC | (0 << SHIFT_FIELD) | OFPort.ZERO.getLength()), MatchUtils.STR_IN_PORT);
+		map.put(U32.ofRaw(OF_BASIC | (0 << SHIFT_FIELD) | OFPort.ZERO.getLength() * 2 | MASKED), MatchUtils.STR_IN_PORT + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (1 << SHIFT_FIELD) | OFPort.ZERO.getLength()), MatchUtils.STR_IN_PHYS_PORT);
+		map.put(U32.ofRaw(OF_BASIC | (1 << SHIFT_FIELD) | OFPort.ZERO.getLength() * 2 | MASKED), MatchUtils.STR_IN_PHYS_PORT + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (2 << SHIFT_FIELD) | OFMetadata.NONE.getLength()), MatchUtils.STR_METADATA);
+		map.put(U32.ofRaw(OF_BASIC | (2 << SHIFT_FIELD) | OFMetadata.NONE.getLength() * 2 | MASKED), MatchUtils.STR_METADATA + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (3 << SHIFT_FIELD) | MacAddress.NONE.getLength()), MatchUtils.STR_DL_DST);
+		map.put(U32.ofRaw(OF_BASIC | (3 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), MatchUtils.STR_DL_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (4 << SHIFT_FIELD) | MacAddress.NONE.getLength()), MatchUtils.STR_DL_SRC);
+		map.put(U32.ofRaw(OF_BASIC | (4 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), MatchUtils.STR_DL_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (5 << SHIFT_FIELD) | EthType.NONE.getLength()), MatchUtils.STR_DL_TYPE);
+		map.put(U32.ofRaw(OF_BASIC | (5 << SHIFT_FIELD) | EthType.NONE.getLength() * 2 | MASKED), MatchUtils.STR_DL_TYPE + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (6 << SHIFT_FIELD) | VlanVid.ZERO.getLength()), MatchUtils.STR_DL_VLAN);
+		map.put(U32.ofRaw(OF_BASIC | (6 << SHIFT_FIELD) | VlanVid.ZERO.getLength() * 2 | MASKED), MatchUtils.STR_DL_VLAN + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (7 << SHIFT_FIELD) | VlanPcp.NONE.getLength()), MatchUtils.STR_DL_VLAN_PCP);
+		map.put(U32.ofRaw(OF_BASIC | (7 << SHIFT_FIELD) | VlanPcp.NONE.getLength() * 2 | MASKED), MatchUtils.STR_DL_VLAN_PCP + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (8 << SHIFT_FIELD) | IpDscp.NONE.getLength()), MatchUtils.STR_NW_DSCP);
+		map.put(U32.ofRaw(OF_BASIC | (8 << SHIFT_FIELD) | IpDscp.NONE.getLength() * 2 | MASKED), MatchUtils.STR_NW_DSCP + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (9 << SHIFT_FIELD) | IpEcn.NONE.getLength()), MatchUtils.STR_NW_ECN);
+		map.put(U32.ofRaw(OF_BASIC | (9 << SHIFT_FIELD) | IpEcn.NONE.getLength() * 2 | MASKED), MatchUtils.STR_NW_ECN + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (10 << SHIFT_FIELD) | IpProtocol.NONE.getLength()), MatchUtils.STR_NW_PROTO);
+		map.put(U32.ofRaw(OF_BASIC | (10 << SHIFT_FIELD) | IpProtocol.NONE.getLength() * 2 | MASKED), MatchUtils.STR_NW_PROTO + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (11 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), MatchUtils.STR_NW_SRC);
+		map.put(U32.ofRaw(OF_BASIC | (11 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_NW_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (12 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), MatchUtils.STR_NW_DST);
+		map.put(U32.ofRaw(OF_BASIC | (12 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_NW_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (13 << SHIFT_FIELD) | TransportPort.NONE.getLength()), MatchUtils.STR_TCP_SRC);
+		map.put(U32.ofRaw(OF_BASIC | (13 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), MatchUtils.STR_TCP_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (14 << SHIFT_FIELD) | TransportPort.NONE.getLength()), MatchUtils.STR_TCP_DST);
+		map.put(U32.ofRaw(OF_BASIC | (14 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), MatchUtils.STR_TCP_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (15 << SHIFT_FIELD) | TransportPort.NONE.getLength()), MatchUtils.STR_UDP_SRC);
+		map.put(U32.ofRaw(OF_BASIC | (15 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), MatchUtils.STR_UDP_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (16 << SHIFT_FIELD) | TransportPort.NONE.getLength()), MatchUtils.STR_UDP_DST);
+		map.put(U32.ofRaw(OF_BASIC | (16 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), MatchUtils.STR_UDP_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (17 << SHIFT_FIELD) | TransportPort.NONE.getLength()), MatchUtils.STR_SCTP_SRC);
+		map.put(U32.ofRaw(OF_BASIC | (17 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), MatchUtils.STR_SCTP_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (18 << SHIFT_FIELD) | TransportPort.NONE.getLength()), MatchUtils.STR_SCTP_DST);
+		map.put(U32.ofRaw(OF_BASIC | (18 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), MatchUtils.STR_SCTP_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (19 << SHIFT_FIELD) | ICMPv4Type.NONE.getLength()), MatchUtils.STR_ICMP_TYPE);
+		map.put(U32.ofRaw(OF_BASIC | (19 << SHIFT_FIELD) | ICMPv4Type.NONE.getLength() * 2 | MASKED), MatchUtils.STR_ICMP_TYPE + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (20 << SHIFT_FIELD) | ICMPv4Code.NONE.getLength()), MatchUtils.STR_ICMP_CODE);
+		map.put(U32.ofRaw(OF_BASIC | (20 << SHIFT_FIELD) | ICMPv4Code.NONE.getLength() * 2 | MASKED), MatchUtils.STR_ICMP_CODE + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (21 << SHIFT_FIELD) | ArpOpcode.NONE.getLength()), MatchUtils.STR_ARP_OPCODE);
+		map.put(U32.ofRaw(OF_BASIC | (21 << SHIFT_FIELD) | ArpOpcode.NONE.getLength() * 2 | MASKED), MatchUtils.STR_ARP_OPCODE + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (22 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), MatchUtils.STR_ARP_SPA);
+		map.put(U32.ofRaw(OF_BASIC | (22 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_ARP_SPA + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (23 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), MatchUtils.STR_ARP_DPA);
+		map.put(U32.ofRaw(OF_BASIC | (23 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_ARP_DPA + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (24 << SHIFT_FIELD) | MacAddress.NONE.getLength()), MatchUtils.STR_ARP_SHA);
+		map.put(U32.ofRaw(OF_BASIC | (24 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), MatchUtils.STR_ARP_SHA + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (25 << SHIFT_FIELD) | MacAddress.NONE.getLength()), MatchUtils.STR_ARP_DHA);
+		map.put(U32.ofRaw(OF_BASIC | (25 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), MatchUtils.STR_ARP_DHA + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (26 << SHIFT_FIELD) | IPv6Address.NONE.getLength()), MatchUtils.STR_IPV6_SRC);
+		map.put(U32.ofRaw(OF_BASIC | (26 << SHIFT_FIELD) | IPv6Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_IPV6_SRC + STR_MASKED);
+		
+		
+		map.put(U32.ofRaw(OF_BASIC | (27 << SHIFT_FIELD) | IPv6Address.NONE.getLength()), MatchUtils.STR_IPV6_DST);
+		map.put(U32.ofRaw(OF_BASIC | (27 << SHIFT_FIELD) | IPv6Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_IPV6_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (28 << SHIFT_FIELD) | IPv6FlowLabel.NONE.getLength()), MatchUtils.STR_IPV6_FLOW_LABEL);
+		map.put(U32.ofRaw(OF_BASIC | (28 << SHIFT_FIELD) | IPv6FlowLabel.NONE.getLength() * 2 | MASKED), MatchUtils.STR_IPV6_FLOW_LABEL + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (29 << SHIFT_FIELD) | U8.ZERO.getLength()), MatchUtils.STR_ICMPV6_TYPE);
+		map.put(U32.ofRaw(OF_BASIC | (29 << SHIFT_FIELD) | U8.ZERO.getLength() * 2 | MASKED), MatchUtils.STR_ICMPV6_TYPE + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (30 << SHIFT_FIELD) | U8.ZERO.getLength()), MatchUtils.STR_ICMPV6_CODE);
+		map.put(U32.ofRaw(OF_BASIC | (30 << SHIFT_FIELD) | U8.ZERO.getLength() * 2 | MASKED), MatchUtils.STR_ICMPV6_CODE + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (31 << SHIFT_FIELD) | IPv6Address.NONE.getLength()), MatchUtils.STR_IPV6_ND_TARGET);
+		map.put(U32.ofRaw(OF_BASIC | (31 << SHIFT_FIELD) | IPv6Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_IPV6_ND_TARGET + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (32 << SHIFT_FIELD) | MacAddress.NONE.getLength()), MatchUtils.STR_IPV6_ND_SSL);
+		map.put(U32.ofRaw(OF_BASIC | (32 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), MatchUtils.STR_IPV6_ND_SSL + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (33 << SHIFT_FIELD) | MacAddress.NONE.getLength()), MatchUtils.STR_IPV6_ND_TTL);
+		map.put(U32.ofRaw(OF_BASIC | (33 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), MatchUtils.STR_IPV6_ND_TTL + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (34 << SHIFT_FIELD) | U32.ZERO.getLength()), MatchUtils.STR_MPLS_LABEL);
+		map.put(U32.ofRaw(OF_BASIC | (34 << SHIFT_FIELD) | U32.ZERO.getLength() * 2 | MASKED), MatchUtils.STR_MPLS_LABEL + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (35 << SHIFT_FIELD) | U8.ZERO.getLength()), MatchUtils.STR_MPLS_TC);
+		map.put(U32.ofRaw(OF_BASIC | (35 << SHIFT_FIELD) | U8.ZERO.getLength() * 2 | MASKED), MatchUtils.STR_MPLS_TC + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (36 << SHIFT_FIELD) | OFBooleanValue.TRUE.getLength()), MatchUtils.STR_MPLS_BOS);
+		map.put(U32.ofRaw(OF_BASIC | (36 << SHIFT_FIELD) | OFBooleanValue.TRUE.getLength() * 2 | MASKED), MatchUtils.STR_MPLS_BOS + STR_MASKED);
+		
+		/*
+		 * TODO in Loxi and MatchUtils
+		 * map.put(U32.ofRaw(OF_BASIC | (37 << SHIFT_FIELD) | ), MatchUtils.STR_PBB_ISID);
+		 */
+		map.put(U32.ofRaw(OF_BASIC | (37 << SHIFT_FIELD) | 3 ), MatchUtils.STR_PBB_ISID); /* need to update after Loxi support */
+		map.put(U32.ofRaw(OF_BASIC | (37 << SHIFT_FIELD) | 3 * 2 | MASKED ), MatchUtils.STR_PBB_ISID + STR_MASKED);
+		
+		map.put(U32.ofRaw(OF_BASIC | (38 << SHIFT_FIELD) | U64.ZERO.getLength()), MatchUtils.STR_TUNNEL_ID);
+		map.put(U32.ofRaw(OF_BASIC | (38 << SHIFT_FIELD) | U64.ZERO.getLength() * 2 | MASKED), MatchUtils.STR_TUNNEL_ID + STR_MASKED);
+		
+		/* 
+		 * TODO in MatchUtils
+		 * map.put(U32.ofRaw(OF_BASIC | 39), MatchUtils.STR_IPV6_EXTHDR);
+		 */
+		map.put(U32.ofRaw(OF_BASIC | (39 << SHIFT_FIELD) | 2), "ipv6_exthdr"); /* need to update after Loxi support */
+		map.put(U32.ofRaw(OF_BASIC | (39 << SHIFT_FIELD) | 2 * 2 | MASKED), "ipv6_exthdr" + STR_MASKED);
+		
+		/* note skip of ID 40 here according to spec */
+		
+		/* 
+		 * TODO in MatchUtils
+		 * map.put(U32.ofRaw(OF_BASIC | 41), MatchUtils.STR_PBB_UCA);
+		 */
+		map.put(U32.ofRaw(OF_BASIC | (41 << SHIFT_FIELD) | 1), "pbb_uca");
+		map.put(U32.ofRaw(OF_BASIC | (41 << SHIFT_FIELD) | 1 * 2 | MASKED), "pbb_uca" + STR_MASKED);
+		
+		/*
+		 * NXM_0 Definitions
+		 */
+		map.put(U32.ofRaw(NXM_0 | (0 << SHIFT_FIELD) | 2 /* old ports are len=2 */), STR_NXM + MatchUtils.STR_IN_PORT);
+		map.put(U32.ofRaw(NXM_0 | (0 << SHIFT_FIELD) | 2 * 2 /* old ports are len=2 */ | MASKED), STR_NXM + MatchUtils.STR_IN_PORT + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (1 << SHIFT_FIELD) | MacAddress.NONE.getLength()), STR_NXM + MatchUtils.STR_DL_DST);
+		map.put(U32.ofRaw(NXM_0 | (1 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_DL_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (2 << SHIFT_FIELD) | MacAddress.NONE.getLength()), STR_NXM + MatchUtils.STR_DL_SRC);
+		map.put(U32.ofRaw(NXM_0 | (2 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_DL_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (3 << SHIFT_FIELD) | EthType.NONE.getLength()), STR_NXM + MatchUtils.STR_DL_TYPE);
+		map.put(U32.ofRaw(NXM_0 | (3 << SHIFT_FIELD) | EthType.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_DL_TYPE + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (4 << SHIFT_FIELD) | VlanVid.ZERO.getLength()), STR_NXM + MatchUtils.STR_DL_VLAN);
+		map.put(U32.ofRaw(NXM_0 | (4 << SHIFT_FIELD) | VlanVid.ZERO.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_DL_VLAN + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (5 << SHIFT_FIELD) | 1), STR_NXM + MatchUtils.STR_NW_TOS);
+		map.put(U32.ofRaw(NXM_0 | (5 << SHIFT_FIELD) | 1 * 2 | MASKED), STR_NXM + MatchUtils.STR_NW_TOS + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (6 << SHIFT_FIELD) | IpProtocol.NONE.getLength()), STR_NXM + MatchUtils.STR_NW_PROTO);
+		map.put(U32.ofRaw(NXM_0 | (6 << SHIFT_FIELD) | IpProtocol.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_NW_PROTO + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (7 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), STR_NXM + MatchUtils.STR_NW_SRC);
+		map.put(U32.ofRaw(NXM_0 | (7 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_NW_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (8 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), STR_NXM + MatchUtils.STR_NW_DST);
+		map.put(U32.ofRaw(NXM_0 | (8 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_NW_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (9 << SHIFT_FIELD) | TransportPort.NONE.getLength()), STR_NXM + MatchUtils.STR_TCP_SRC);
+		map.put(U32.ofRaw(NXM_0 | (9 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_TCP_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (10 << SHIFT_FIELD) | TransportPort.NONE.getLength()), STR_NXM + MatchUtils.STR_TCP_DST);
+		map.put(U32.ofRaw(NXM_0 | (10 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_TCP_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (11 << SHIFT_FIELD) | TransportPort.NONE.getLength()), STR_NXM + MatchUtils.STR_UDP_SRC);
+		map.put(U32.ofRaw(NXM_0 | (11 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_UDP_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (12 << SHIFT_FIELD) | TransportPort.NONE.getLength()), STR_NXM + MatchUtils.STR_UDP_DST);
+		map.put(U32.ofRaw(NXM_0 | (12 << SHIFT_FIELD) | TransportPort.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_UDP_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (13 << SHIFT_FIELD) | U8.ZERO.getLength()), STR_NXM + MatchUtils.STR_ICMP_TYPE);
+		map.put(U32.ofRaw(NXM_0 | (13 << SHIFT_FIELD) | U8.ZERO.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ICMP_TYPE + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (14 << SHIFT_FIELD) | U8.ZERO.getLength()), STR_NXM + MatchUtils.STR_ICMP_CODE);
+		map.put(U32.ofRaw(NXM_0 | (14 << SHIFT_FIELD) | U8.ZERO.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ICMP_CODE + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (15 << SHIFT_FIELD) | ArpOpcode.NONE.getLength()), STR_NXM + MatchUtils.STR_ARP_OPCODE);
+		map.put(U32.ofRaw(NXM_0 | (15 << SHIFT_FIELD) | ArpOpcode.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ARP_OPCODE + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (16 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), STR_NXM + MatchUtils.STR_ARP_SPA);
+		map.put(U32.ofRaw(NXM_0 | (16 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ARP_SPA + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_0 | (17 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), STR_NXM + MatchUtils.STR_ARP_DPA);
+		map.put(U32.ofRaw(NXM_0 | (17 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ARP_DPA + STR_MASKED);
+
+		/*
+		 * NXM_1 Definitions
+		 */
+		map.put(U32.ofRaw(NXM_1 | (0 << SHIFT_FIELD) | 4), STR_NXM + "reg_0");
+		map.put(U32.ofRaw(NXM_1 | (0 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "reg_0" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (1 << SHIFT_FIELD) | 4), STR_NXM + "reg_1");
+		map.put(U32.ofRaw(NXM_1 | (1 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "reg_1" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (2 << SHIFT_FIELD) | 4), STR_NXM + "reg_2");
+		map.put(U32.ofRaw(NXM_1 | (2 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "reg_2" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (3 << SHIFT_FIELD) | 4), STR_NXM + "reg_3");
+		map.put(U32.ofRaw(NXM_1 | (3 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "reg_3" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (4 << SHIFT_FIELD) | 4), STR_NXM + "reg_4");
+		map.put(U32.ofRaw(NXM_1 | (4 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "reg_4" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (5 << SHIFT_FIELD) | 4), STR_NXM + "reg_5");
+		map.put(U32.ofRaw(NXM_1 | (5 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "reg_5" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (6 << SHIFT_FIELD) | 4), STR_NXM + "reg_6");
+		map.put(U32.ofRaw(NXM_1 | (6 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "reg_6" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (7 << SHIFT_FIELD) | 4), STR_NXM + "reg_7");
+		map.put(U32.ofRaw(NXM_1 | (7 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "reg_7" + STR_MASKED);
+
+		map.put(U32.ofRaw(NXM_1 | (16 << SHIFT_FIELD) | U64.ZERO.getLength()), STR_NXM + MatchUtils.STR_TUNNEL_ID);
+		map.put(U32.ofRaw(NXM_1 | (16 << SHIFT_FIELD) | U64.ZERO.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_TUNNEL_ID + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (17 << SHIFT_FIELD) | MacAddress.NONE.getLength()), STR_NXM + MatchUtils.STR_ARP_SHA);
+		map.put(U32.ofRaw(NXM_1 | (17 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ARP_SHA + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (18 << SHIFT_FIELD) | MacAddress.NONE.getLength()), STR_NXM + MatchUtils.STR_ARP_DHA);
+		map.put(U32.ofRaw(NXM_1 | (18 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ARP_DHA + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (19 << SHIFT_FIELD) | IPv6Address.NONE.getLength()), STR_NXM + MatchUtils.STR_IPV6_SRC);
+		map.put(U32.ofRaw(NXM_1 | (19 << SHIFT_FIELD) | IPv6Address.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_IPV6_SRC + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (20 << SHIFT_FIELD) | IPv6Address.NONE.getLength()), STR_NXM + MatchUtils.STR_IPV6_DST);
+		map.put(U32.ofRaw(NXM_1 | (20 << SHIFT_FIELD) | IPv6Address.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_IPV6_DST + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (21 << SHIFT_FIELD) | U8.ZERO.getLength()), STR_NXM + MatchUtils.STR_ICMPV6_TYPE);
+		map.put(U32.ofRaw(NXM_1 | (21 << SHIFT_FIELD) | U8.ZERO.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ICMPV6_TYPE + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (22 << SHIFT_FIELD) | U8.ZERO.getLength()), STR_NXM + MatchUtils.STR_ICMPV6_CODE);
+		map.put(U32.ofRaw(NXM_1 | (22 << SHIFT_FIELD) | U8.ZERO.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_ICMPV6_CODE + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (23 << SHIFT_FIELD) | IPv6Address.NONE.getLength()), STR_NXM + MatchUtils.STR_IPV6_ND_TARGET);
+		map.put(U32.ofRaw(NXM_1 | (23 << SHIFT_FIELD) | IPv6Address.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_IPV6_ND_TARGET + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (24 << SHIFT_FIELD) | MacAddress.NONE.getLength()), STR_NXM + MatchUtils.STR_IPV6_ND_SSL);
+		map.put(U32.ofRaw(NXM_1 | (24 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_IPV6_ND_SSL + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (25 << SHIFT_FIELD) | MacAddress.NONE.getLength()), STR_NXM + MatchUtils.STR_IPV6_ND_TTL);
+		map.put(U32.ofRaw(NXM_1 | (25 << SHIFT_FIELD) | MacAddress.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_IPV6_ND_TTL + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (26 << SHIFT_FIELD) | 1), STR_NXM + "ip_frag");
+		map.put(U32.ofRaw(NXM_1 | (26 << SHIFT_FIELD) | 1 * 2 | MASKED), STR_NXM + "ip_frag" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (27 << SHIFT_FIELD) | IPv6FlowLabel.NONE.getLength()), STR_NXM + MatchUtils.STR_IPV6_FLOW_LABEL);	
+		map.put(U32.ofRaw(NXM_1 | (27 << SHIFT_FIELD) | IPv6FlowLabel.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_IPV6_FLOW_LABEL + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (28 << SHIFT_FIELD) | IpEcn.NONE.getLength()), STR_NXM + MatchUtils.STR_NW_ECN);
+		map.put(U32.ofRaw(NXM_1 | (28 << SHIFT_FIELD) | IpEcn.NONE.getLength() * 2 | MASKED), STR_NXM + MatchUtils.STR_NW_ECN + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (29 << SHIFT_FIELD) | 1), STR_NXM + "ip_ttl");
+		map.put(U32.ofRaw(NXM_1 | (29 << SHIFT_FIELD) | 1 * 2 | MASKED), STR_NXM + "ip_ttl" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (30 << SHIFT_FIELD) | 8), STR_NXM + "flow_cookie");
+		map.put(U32.ofRaw(NXM_1 | (30 << SHIFT_FIELD) | 8 * 2 | MASKED), STR_NXM + "flow_cookie" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (31 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), MatchUtils.STR_TUNNEL_IPV4_SRC);
+		map.put(U32.ofRaw(NXM_1 | (31 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_TUNNEL_IPV4_SRC + MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (32 << SHIFT_FIELD) | IPv4Address.NONE.getLength()), MatchUtils.STR_TUNNEL_IPV4_DST);
+		map.put(U32.ofRaw(NXM_1 | (32 << SHIFT_FIELD) | IPv4Address.NONE.getLength() * 2 | MASKED), MatchUtils.STR_TUNNEL_IPV4_DST + MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (33 << SHIFT_FIELD) | 4), STR_NXM + "pkt_mark");
+		map.put(U32.ofRaw(NXM_1 | (33 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "pkt_mark" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (34 << SHIFT_FIELD) | 2), STR_NXM + "tcp_flags");
+		map.put(U32.ofRaw(NXM_1 | (34 << SHIFT_FIELD) | 2 * 2 | MASKED), STR_NXM + "tcp_flags" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (35 << SHIFT_FIELD) | 4), STR_NXM + "internal_dp_hash");
+		map.put(U32.ofRaw(NXM_1 | (35 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "internal_dp_hash" + STR_MASKED);
+		
+		map.put(U32.ofRaw(NXM_1 | (36 << SHIFT_FIELD) | 4), STR_NXM + "internal_recirc_id");
+		map.put(U32.ofRaw(NXM_1 | (36 << SHIFT_FIELD) | 4 * 2 | MASKED), STR_NXM + "internal_recirc_id" + STR_MASKED);
+	}
+	
+	/**
+	 * Converts the string representation of an OXM ID as
+	 * defined in {@link net.floodlightcontroller.util.MatchUtils.java}
+	 * to its corresponding U32 OXM ID.
+	 * 
+	 * Any NXM (not defined in {@link net.floodlightcontroller.util.MatchUtils.java}
+	 * is the same as the OXM string with an "nxm_" prefix.
+	 * 
+	 * Any OXM or NXM that is masked include a "_masked" postfix.
+	 * 
+	 * @param oxmId, the U32 defining the OXM/NXM as [class]+[field]+[has_mask]+[length]
+	 * @return the String representing the OXM/NXM
+	 */
+	public static String oxmIdToString(U32 oxmId) {
+		if (map.containsKey(oxmId)) {
+			return map.get(oxmId);
+		} else {
+			return "Unknown OXM ID: " + oxmId.toString();
+		}
+	}
+	
+	/**
+	 * Converts the string representation of an OXM ID as
+	 * defined in {@link net.floodlightcontroller.util.MatchUtils.java}
+	 * to its corresponding U32 OXM ID.
+	 * 
+	 * Any NXM (not defined in {@link net.floodlightcontroller.util.MatchUtils.java}
+	 * is the same as the OXM string with an "nxm_" prefix.
+	 * 
+	 * Any OXM or NXM that is masked include a "_masked" postfix.
+	 * 
+	 * @param oxmString, the string definging the OXM/NXM
+	 * @return the U32 representing the OXM/NXM as [class]+[field]+[has_mask]+[length]
+	 */
+	public static U32 oxmStringToId(String oxmString) {
+		if (map.inverse().containsKey(oxmString)) {
+			return map.inverse().get(oxmString);
+		} else {
+			return null;
+		}
+	}
+}
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java
index bd728ff80be82b0993fd10385b8dca53c63a0fed..606d42f6baa2a4e3f5923b8ce2c2ed85ed81af00 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java
@@ -80,6 +80,7 @@ import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandDscpRemark;
 import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandExperimenter;
 import org.projectfloodlight.openflow.protocol.ver13.OFFlowModFlagsSerializerVer13;
 import org.projectfloodlight.openflow.protocol.ver13.OFMeterBandTypeSerializerVer13;
+import org.projectfloodlight.openflow.protocol.ver13.OFOxmClassSerializerVer13;
 // Use Loxigen's serializer
 import org.projectfloodlight.openflow.protocol.ver13.OFPortFeaturesSerializerVer13;
 import org.projectfloodlight.openflow.protocol.ver13.OFStatsReplyFlagsSerializerVer13;
@@ -158,7 +159,7 @@ public class StatsReplySerializer extends JsonSerializer<StatsReply> {
 
 		jGen.configure(Feature.WRITE_NUMBERS_AS_STRINGS, true); // IMHO this just looks nicer and is easier to read if everything is quoted
 		jGen.writeStartObject();
-		
+
 		if (reply.getStatType() == null) { // must be an OFFeaturesReply. getValues() was already checked for null above.
 			serializeFeaturesReply((OFFeaturesReply) reply.getValues(), jGen);
 		} else {
@@ -213,7 +214,7 @@ public class StatsReplySerializer extends JsonSerializer<StatsReply> {
 		}
 		jGen.writeEndObject();
 	}
-	
+
 	public static void serializeFeaturesReply(OFFeaturesReply fr, JsonGenerator jGen) throws IOException, JsonProcessingException {
 		/* Common to All OF Versions */			
 		jGen.writeStringField("capabilities", fr.getCapabilities().toString());
@@ -221,7 +222,7 @@ public class StatsReplySerializer extends JsonSerializer<StatsReply> {
 		jGen.writeNumberField("buffers", fr.getNBuffers());
 		jGen.writeNumberField("tables", fr.getNTables());
 		jGen.writeStringField("version", fr.getVersion().toString());
-		
+
 		if (fr.getVersion().compareTo(OFVersion.OF_13) < 0) { // OF1.3+ break this out into port_config
 			serializePortDesc(fr.getPorts(), jGen);
 		}
@@ -509,208 +510,183 @@ public class StatsReplySerializer extends JsonSerializer<StatsReply> {
 	 */
 	public static void serializeTableFeaturesReply(List<OFTableFeaturesStatsReply> tableFeaturesReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{
 
-		OFTableFeaturesStatsReply tableFeaturesReply = tableFeaturesReplies.get(0);
-		jGen.writeStringField("version", tableFeaturesReply.getVersion().toString()); //return the enum name
-
 		jGen.writeFieldName("tableFeatures");
 		jGen.writeStartArray();
-		for(OFTableFeatures tableFeature : tableFeaturesReply.getEntries()) {
-			jGen.writeStartObject();                        
-			jGen.writeNumberField("tableId", tableFeature.getTableId().getValue());
-			jGen.writeStringField("name", tableFeature.getName());
-			jGen.writeNumberField("metadataMatch", tableFeature.getMetadataMatch().getValue());
-			jGen.writeNumberField("metadataWrite", tableFeature.getMetadataWrite().getValue());
-			jGen.writeNumberField("config", tableFeature.getConfig());
-			jGen.writeNumberField("maxEntries", tableFeature.getMaxEntries());
-
-			jGen.writeFieldName("properties");
-			jGen.writeStartArray();
-			for (OFTableFeatureProp properties : tableFeature.getProperties()) {            	
-				jGen.writeStartObject();
-				short type = (short)properties.getType();
-				jGen.writeNumberField("tableFeaturePropType",type);
-
-				switch (type) {
-				case OFTableFeaturePropTypeSerializerVer13.INSTRUCTIONS_VAL:
-					OFTableFeaturePropInstructions propInstruct = (OFTableFeaturePropInstructions) properties;
-					jGen.writeFieldName("instructions");
-					jGen.writeStartArray();
-					for (OFInstructionId id : propInstruct.getInstructionIds()) {
-						jGen.writeStartObject();
-						jGen.writeString(id.getType().toString());              			
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.INSTRUCTIONS_MISS_VAL:
-					OFTableFeaturePropInstructionsMiss propInstructMiss = (OFTableFeaturePropInstructionsMiss) properties;
-					jGen.writeFieldName("instructionsMiss");
-					jGen.writeStartArray();
-					for (OFInstructionId id : propInstructMiss.getInstructionIds()) {
-						jGen.writeStartObject();
-						jGen.writeString(id.getType().toString());              			
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.NEXT_TABLES_VAL:
-					OFTableFeaturePropNextTables propNxtTables = (OFTableFeaturePropNextTables) properties;
-					jGen.writeFieldName("nextTables");
-					jGen.writeStartArray();
-					for (U8 id : propNxtTables.getNextTableIds()) {
-						jGen.writeStartObject();
-						jGen.writeNumber(id.getValue());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.NEXT_TABLES_MISS_VAL:
-					OFTableFeaturePropNextTablesMiss propNxtTablesMiss = (OFTableFeaturePropNextTablesMiss) properties;
-					jGen.writeFieldName("nextTablesMiss");
-					jGen.writeStartArray();
-					for (U8 id : propNxtTablesMiss.getNextTableIds()) {
-						jGen.writeStartObject();
-						jGen.writeNumber(id.getValue());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.WRITE_ACTIONS_VAL:
-					OFTableFeaturePropWriteActions propWrAct = (OFTableFeaturePropWriteActions) properties; 
-					jGen.writeFieldName("writeActions");
-					jGen.writeStartArray();
-					for (OFActionId id : propWrAct.getActionIds()) {
-						jGen.writeStartObject();
-						jGen.writeString(id.getType().toString());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.WRITE_ACTIONS_MISS_VAL:
-					OFTableFeaturePropWriteActionsMiss propWrActMiss = (OFTableFeaturePropWriteActionsMiss) properties;
-					jGen.writeFieldName("writeActionsMiss");
-					jGen.writeStartArray();
-					for (OFActionId id : propWrActMiss.getActionIds()) {
-						jGen.writeStartObject();
-						jGen.writeString(id.getType().toString());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.APPLY_ACTIONS_VAL:
-					OFTableFeaturePropApplyActions propAppAct = (OFTableFeaturePropApplyActions) properties;   
-					jGen.writeFieldName("applyActions");
-					jGen.writeStartArray();
-					for (OFActionId id : propAppAct.getActionIds()) {
-						jGen.writeStartObject();
-						jGen.writeString(id.getType().toString());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;	
-				case OFTableFeaturePropTypeSerializerVer13.APPLY_ACTIONS_MISS_VAL:
-					OFTableFeaturePropApplyActionsMiss propAppActMiss = (OFTableFeaturePropApplyActionsMiss) properties;
-					jGen.writeFieldName("applyActionsMiss");
-					jGen.writeStartArray();
-					for (OFActionId id : propAppActMiss.getActionIds()) {
-						jGen.writeStartObject();
-						jGen.writeString(id.getType().toString());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.MATCH_VAL:                	
-					OFTableFeaturePropMatch propMatch = (OFTableFeaturePropMatch) properties;
-					jGen.writeFieldName("match");
-					jGen.writeStartArray();
-					for (U32 id : propMatch.getOxmIds()) {
-						jGen.writeStartObject();
-						jGen.writeNumber(id.getValue());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.WILDCARDS_VAL:
-					OFTableFeaturePropWildcards propWildcards = (OFTableFeaturePropWildcards) properties;
-					jGen.writeFieldName("wildcards");
-					jGen.writeStartArray();
-					for (U32 id : propWildcards.getOxmIds()) {
-						jGen.writeStartObject();
-						jGen.writeNumber(id.getValue());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.WRITE_SETFIELD_VAL:
-					OFTableFeaturePropWriteSetfield propWrSetfield = (OFTableFeaturePropWriteSetfield) properties;           
-					jGen.writeFieldName("writeSetfield");
-					jGen.writeStartArray();
-					for (U32 id : propWrSetfield.getOxmIds()) {
-						jGen.writeStartObject();
-						jGen.writeNumber(id.getValue());
-						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.WRITE_SETFIELD_MISS_VAL:
-					OFTableFeaturePropWriteSetfieldMiss propWrSetfieldMiss = (OFTableFeaturePropWriteSetfieldMiss) properties; 
-					jGen.writeFieldName("writeSetfieldMiss");
-					jGen.writeStartArray();
-					for (U32 id : propWrSetfieldMiss.getOxmIds()) {
+		for (OFTableFeaturesStatsReply tableFeaturesReply : tableFeaturesReplies) {
+
+			for(OFTableFeatures tableFeature : tableFeaturesReply.getEntries()) {
+				jGen.writeStartObject();    
+				jGen.writeStringField("version", tableFeature.getVersion().toString());
+				jGen.writeNumberField("tableId", tableFeature.getTableId().getValue());
+				jGen.writeStringField("name", tableFeature.getName());
+				jGen.writeNumberField("metadataMatch", tableFeature.getMetadataMatch().getValue());
+				jGen.writeNumberField("metadataWrite", tableFeature.getMetadataWrite().getValue());
+				jGen.writeNumberField("config", tableFeature.getConfig());
+				jGen.writeNumberField("maxEntries", tableFeature.getMaxEntries());
+
+				jGen.writeFieldName("properties");
+				jGen.writeStartArray();
+				for (OFTableFeatureProp properties : tableFeature.getProperties()) {            	
+					jGen.writeStartObject();
+
+					short type = (short)properties.getType();
+					switch (type) {
+					case OFTableFeaturePropTypeSerializerVer13.INSTRUCTIONS_VAL:
+						OFTableFeaturePropInstructions propInstruct = (OFTableFeaturePropInstructions) properties;
+						jGen.writeFieldName("instructions");
+						jGen.writeStartArray();
+						for (OFInstructionId id : propInstruct.getInstructionIds()) {
+							jGen.writeString(id.getType().toString());              			
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.INSTRUCTIONS_MISS_VAL:
+						OFTableFeaturePropInstructionsMiss propInstructMiss = (OFTableFeaturePropInstructionsMiss) properties;
+						jGen.writeFieldName("instructionsMiss");
+						jGen.writeStartArray();
+						for (OFInstructionId id : propInstructMiss.getInstructionIds()) {
+							jGen.writeString(id.getType().toString());              			
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.NEXT_TABLES_VAL:
+						OFTableFeaturePropNextTables propNxtTables = (OFTableFeaturePropNextTables) properties;
+						jGen.writeFieldName("nextTables");
+						jGen.writeStartArray();
+						for (U8 id : propNxtTables.getNextTableIds()) {
+							jGen.writeNumber(id.getValue());
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.NEXT_TABLES_MISS_VAL:
+						OFTableFeaturePropNextTablesMiss propNxtTablesMiss = (OFTableFeaturePropNextTablesMiss) properties;
+						jGen.writeFieldName("nextTablesMiss");
+						jGen.writeStartArray();
+						for (U8 id : propNxtTablesMiss.getNextTableIds()) {
+							jGen.writeNumber(id.getValue());
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.WRITE_ACTIONS_VAL:
+						OFTableFeaturePropWriteActions propWrAct = (OFTableFeaturePropWriteActions) properties; 
+						jGen.writeFieldName("writeActions");
+						jGen.writeStartArray();
+						for (OFActionId id : propWrAct.getActionIds()) {
+							jGen.writeString(id.getType().toString());
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.WRITE_ACTIONS_MISS_VAL:
+						OFTableFeaturePropWriteActionsMiss propWrActMiss = (OFTableFeaturePropWriteActionsMiss) properties;
+						jGen.writeFieldName("writeActionsMiss");
+						jGen.writeStartArray();
+						for (OFActionId id : propWrActMiss.getActionIds()) {
+							jGen.writeString(id.getType().toString());
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.APPLY_ACTIONS_VAL:
+						OFTableFeaturePropApplyActions propAppAct = (OFTableFeaturePropApplyActions) properties;   
+						jGen.writeFieldName("applyActions");
+						jGen.writeStartArray();
+						for (OFActionId id : propAppAct.getActionIds()) {
+							jGen.writeString(id.getType().toString());
+						}
+						jGen.writeEndArray();
+						break;	
+					case OFTableFeaturePropTypeSerializerVer13.APPLY_ACTIONS_MISS_VAL:
+						OFTableFeaturePropApplyActionsMiss propAppActMiss = (OFTableFeaturePropApplyActionsMiss) properties;
+						jGen.writeFieldName("applyActionsMiss");
+						jGen.writeStartArray();
+						for (OFActionId id : propAppActMiss.getActionIds()) {
+							jGen.writeString(id.getType().toString());
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.MATCH_VAL:                	
+						OFTableFeaturePropMatch propMatch = (OFTableFeaturePropMatch) properties;
+						jGen.writeFieldName("match");
+						jGen.writeStartArray();
+						for (U32 id : propMatch.getOxmIds()) {
+							jGen.writeString(OXMSerializer.oxmIdToString(id));
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.WILDCARDS_VAL:
+						OFTableFeaturePropWildcards propWildcards = (OFTableFeaturePropWildcards) properties;
+						jGen.writeFieldName("wildcards");
+						jGen.writeStartArray();
+						for (U32 id : propWildcards.getOxmIds()) {
+							jGen.writeString(OXMSerializer.oxmIdToString(id));
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.WRITE_SETFIELD_VAL:
+						OFTableFeaturePropWriteSetfield propWrSetfield = (OFTableFeaturePropWriteSetfield) properties;           
+						jGen.writeFieldName("writeSetfield");
+						jGen.writeStartArray();
+						for (U32 id : propWrSetfield.getOxmIds()) {
+							jGen.writeString(OXMSerializer.oxmIdToString(id));
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.WRITE_SETFIELD_MISS_VAL:
+						OFTableFeaturePropWriteSetfieldMiss propWrSetfieldMiss = (OFTableFeaturePropWriteSetfieldMiss) properties; 
+						jGen.writeFieldName("writeSetfieldMiss");
+						jGen.writeStartArray();
+						for (U32 id : propWrSetfieldMiss.getOxmIds()) {
+							jGen.writeString(OXMSerializer.oxmIdToString(id));
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.APPLY_SETFIELD_VAL:
+						OFTableFeaturePropApplySetfield propAppSetfield = (OFTableFeaturePropApplySetfield) properties;
+						jGen.writeFieldName("applySetfield");
+						jGen.writeStartArray();
+						for (U32 id : propAppSetfield.getOxmIds()) {
+							jGen.writeString(OXMSerializer.oxmIdToString(id));
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.APPLY_SETFIELD_MISS_VAL:
+						OFTableFeaturePropApplySetfieldMiss propAppSetfieldMiss = (OFTableFeaturePropApplySetfieldMiss) properties;                		
+						jGen.writeFieldName("applySetfieldMiss");
+						jGen.writeStartArray();
+						for (U32 id : propAppSetfieldMiss.getOxmIds()) {
+							jGen.writeString(OXMSerializer.oxmIdToString(id));
+						}
+						jGen.writeEndArray();
+						break;
+					case OFTableFeaturePropTypeSerializerVer13.EXPERIMENTER_VAL:
+						OFTableFeaturePropExperimenter propExp = (OFTableFeaturePropExperimenter) properties; 
+						jGen.writeFieldName("experimenter");
 						jGen.writeStartObject();
-						jGen.writeNumber(id.getValue());
+						jGen.writeNumberField("subType", propExp.getSubtype());
+						jGen.writeNumberField("experimenter", propExp.getExperimenter());
+						jGen.writeStringField("data", propExp.getExperimenterData().toString());
 						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.APPLY_SETFIELD_VAL:
-					OFTableFeaturePropApplySetfield propAppSetfield = (OFTableFeaturePropApplySetfield) properties;
-					jGen.writeFieldName("applySetfield");
-					jGen.writeStartArray();
-					for (U32 id : propAppSetfield.getOxmIds()) {
+						break;	
+					case OFTableFeaturePropTypeSerializerVer13.EXPERIMENTER_MISS_VAL:
+						OFTableFeaturePropExperimenterMiss propExpMiss = (OFTableFeaturePropExperimenterMiss) properties;
+						jGen.writeFieldName("experimenterMiss");
 						jGen.writeStartObject();
-						jGen.writeNumber(id.getValue());
+						jGen.writeNumberField("subType", propExpMiss.getSubtype());
+						jGen.writeNumberField("experimenter", propExpMiss.getExperimenter());
+						jGen.writeStringField("data", propExpMiss.getExperimenterData().toString());
 						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.APPLY_SETFIELD_MISS_VAL:
-					OFTableFeaturePropApplySetfieldMiss propAppSetfieldMiss = (OFTableFeaturePropApplySetfieldMiss) properties;                		
-					jGen.writeFieldName("applySetfieldMiss");
-					jGen.writeStartArray();
-					for (U32 id : propAppSetfieldMiss.getOxmIds()) {
+						break;	
+					default:
+						// shouldn't ever get here
 						jGen.writeStartObject();
-						jGen.writeNumber(id.getValue());
 						jGen.writeEndObject();
-					}
-					jGen.writeEndArray();
-					break;
-				case OFTableFeaturePropTypeSerializerVer13.EXPERIMENTER_VAL:
-					OFTableFeaturePropExperimenter propExp = (OFTableFeaturePropExperimenter) properties; 
-					jGen.writeFieldName("experimenter");
-					jGen.writeStartObject();
-					jGen.writeNumberField("subType", propExp.getSubtype());
-					jGen.writeNumberField("experimenter", propExp.getExperimenter());
-					jGen.writeStringField("subType", propExp.getExperimenterData().toString());
-					jGen.writeEndObject();
-					break;	
-				case OFTableFeaturePropTypeSerializerVer13.EXPERIMENTER_MISS_VAL:
-					OFTableFeaturePropExperimenterMiss propExpMiss = (OFTableFeaturePropExperimenterMiss) properties;
-					jGen.writeFieldName("experimenterMiss");
-					jGen.writeStartObject();
-					jGen.writeNumberField("subType", propExpMiss.getSubtype());
-					jGen.writeNumberField("experimenter", propExpMiss.getExperimenter());
-					jGen.writeStringField("subType", propExpMiss.getExperimenterData().toString());
+						break;            		
+					}//end of Switch Case  
 					jGen.writeEndObject();
-					break;	
-				default:
-					// shouldn't ever get here
-					break;            		
-				}//end of Switch Case  
+				}//end of for loop - properties                                              
+				jGen.writeEndArray();
 				jGen.writeEndObject();
-			}//end of for loop - properties                                              
-			jGen.writeEndObject();
-		}//end of for loop - features
+			}//end of for loop - features
+		} //end of looping through REQ_MORE flagged message loop
 		jGen.writeEndArray();
 	} 
 
@@ -847,7 +823,7 @@ public class StatsReplySerializer extends JsonSerializer<StatsReply> {
 		jGen.writeStringField("version", portDescReply.getVersion().toString()); //return the enum name
 		serializePortDesc(portDescReply.getEntries(), jGen);
 	}
-	
+
 	public static void serializePortDesc(List<OFPortDesc> portDescList, JsonGenerator jGen) throws IOException, JsonProcessingException {
 		jGen.writeFieldName("portDesc");
 		jGen.writeStartArray();
diff --git a/src/main/java/net/floodlightcontroller/util/MatchUtils.java b/src/main/java/net/floodlightcontroller/util/MatchUtils.java
index ea3d77cf26075acbd1c602052c66e25c04b0156c..028614485c1a1d18300241a43d02e4c15398d5e4 100644
--- a/src/main/java/net/floodlightcontroller/util/MatchUtils.java
+++ b/src/main/java/net/floodlightcontroller/util/MatchUtils.java
@@ -11,6 +11,7 @@ import org.projectfloodlight.openflow.types.ArpOpcode;
 import org.projectfloodlight.openflow.types.EthType;
 import org.projectfloodlight.openflow.types.ICMPv4Code;
 import org.projectfloodlight.openflow.types.ICMPv4Type;
+import org.projectfloodlight.openflow.types.IPv4Address;
 import org.projectfloodlight.openflow.types.IPv4AddressWithMask;
 import org.projectfloodlight.openflow.types.IPv6AddressWithMask;
 import org.projectfloodlight.openflow.types.IPv6FlowLabel;
@@ -104,6 +105,8 @@ public class MatchUtils {
 
 	public static final String STR_METADATA = "metadata";
 	public static final String STR_TUNNEL_ID = "tunnel_id";
+	public static final String STR_TUNNEL_IPV4_SRC = "tunnel_ipv4_src";
+	public static final String STR_TUNNEL_IPV4_DST = "tunnel_ipv4_dst";
 
 	public static final String STR_PBB_ISID = "pbb_isid";	
 
@@ -748,6 +751,20 @@ public class MatchUtils {
 							dataMask[1].contains("0x") ? U64.of(Long.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U64.of(Long.valueOf(dataMask[1])));
 				}
 				break;
+			case STR_TUNNEL_IPV4_SRC:
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.TUNNEL_IPV4_SRC, IPv4Address.of(key_value[1]));
+				} else {
+					mb.setMasked(MatchField.TUNNEL_IPV4_SRC, IPv4AddressWithMask.of(key_value[1]));
+				}
+				break;
+			case STR_TUNNEL_IPV4_DST:
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.TUNNEL_IPV4_DST, IPv4Address.of(key_value[1]));
+				} else {
+					mb.setMasked(MatchField.TUNNEL_IPV4_DST, IPv4AddressWithMask.of(key_value[1]));
+				}
+				break;
 			case STR_PBB_ISID:
 				/*TODO no-op. Not implemented.
 				if (key_value[1].startsWith("0x")) {
diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties
index 2a4786bf21b600aa31c233d9f0378eee61d99948..eb354532c36c036904aafe218478c9970d206dba 100644
--- a/src/main/resources/floodlightdefault.properties
+++ b/src/main/resources/floodlightdefault.properties
@@ -30,6 +30,7 @@ net.floodlightcontroller.core.internal.OFSwitchManager.clearTablesOnEachTransiti
 net.floodlightcontroller.core.internal.OFSwitchManager.keyStorePath=/path/to/your/keystore-file.jks
 net.floodlightcontroller.core.internal.OFSwitchManager.keyStorePassword=your-keystore-password
 net.floodlightcontroller.core.internal.OFSwitchManager.useSsl=NO
+net.floodlightcontroller.core.internal.OFSwitchManager.supportedOpenFlowVersions=1.0, 1.1, 1.2, 1.3, 1.4
 net.floodlightcontroller.restserver.RestApiServer.keyStorePath=/path/to/your/keystore-file.jks
 net.floodlightcontroller.restserver.RestApiServer.keyStorePassword=your-keystore-password
 net.floodlightcontroller.restserver.RestApiServer.httpsNeedClientAuthentication=NO
diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer10Test.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer10Test.java
index b724ebcd629d4f7ee868888e6fb81546ce061977..96147b02eb52b4323be4f804ffad6014c552809b 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer10Test.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer10Test.java
@@ -35,12 +35,14 @@ import org.jboss.netty.util.Timer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+
 import net.floodlightcontroller.core.IOFConnectionBackend;
 import net.floodlightcontroller.core.OFConnectionCounters;
 import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandler;
 import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandshakeTimeout;
 import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl;
 import net.floodlightcontroller.debugcounter.IDebugCounterService;
+
 import org.projectfloodlight.openflow.protocol.OFActionType;
 import org.projectfloodlight.openflow.protocol.OFBarrierReply;
 import org.projectfloodlight.openflow.protocol.OFCapabilities;
@@ -63,6 +65,7 @@ import org.projectfloodlight.openflow.protocol.OFType;
 import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.types.DatapathId;
 import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.U32;
 
 import com.google.common.collect.ImmutableList;
 
@@ -137,7 +140,7 @@ public class OFChannelHandlerVer10Test {
         replay(switchManager);
         handler = new OFChannelHandler(switchManager, newConnectionListener,
                                        pipeline, debugCounterService,
-                                       timer);
+                                       timer, Collections.singletonList(U32.of(0)), OFFactories.getFactory(OFVersion.OF_14));
         verify(switchManager);
         reset(switchManager);
 
diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer13Test.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer13Test.java
index bd499214c6a33c624be829a3fa91a71514acd8ba..9b9b6ce897bf00c210326fed7d49e315500e11eb 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer13Test.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer13Test.java
@@ -35,12 +35,14 @@ import org.jboss.netty.util.Timer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+
 import net.floodlightcontroller.core.IOFConnectionBackend;
 import net.floodlightcontroller.core.OFConnectionCounters;
 import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandler;
 import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandshakeTimeout;
 import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl;
 import net.floodlightcontroller.debugcounter.IDebugCounterService;
+
 import org.projectfloodlight.openflow.protocol.OFBarrierReply;
 import org.projectfloodlight.openflow.protocol.OFBsnSetAuxCxnsReply;
 import org.projectfloodlight.openflow.protocol.OFCapabilities;
@@ -64,6 +66,7 @@ import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.types.DatapathId;
 import org.projectfloodlight.openflow.types.OFAuxId;
 import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.U32;
 
 import com.google.common.collect.ImmutableList;
 
@@ -139,7 +142,9 @@ public class OFChannelHandlerVer13Test {
         expect(switchManager.getCounters()).andReturn(counters).anyTimes();
         replay(switchManager);
         handler = new OFChannelHandler(switchManager, newConnectionListener,
-                                       pipeline, debugCounterService, timer);
+                                       pipeline, debugCounterService, /* 62 is OF versions 1.0 thru 1.4 in decimal */
+                                       timer, Collections.singletonList(U32.of(62)), OFFactories.getFactory(OFVersion.OF_14));
+
         verify(switchManager);
         reset(switchManager);