diff --git a/logback.xml b/logback.xml
index a25cc7f639cbb65d64acfca5a5df190e83c674d4..f5163007d4c2af4ea21c0c62b023614e2689ee79 100644
--- a/logback.xml
+++ b/logback.xml
@@ -11,5 +11,5 @@
   <logger name="LogService" level="DEBUG"/> <!-- Restlet access logging -->
   <logger name="net.floodlightcontroller" level="DEBUG"/>
   <logger name="net.floodlightcontroller.logging" level="DEBUG"/>
-  <logger name="org.sdnplatform" level="DEBUG"/>
+  <logger name="org.sdnplatform" level="INFO"/>
 </configuration>
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/MatchSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/MatchSerializer.java
index c242cc6305711654eff318152d0348b6e5e34a89..9bc587ced4742c47e9bfc1f8a7472406ca334605 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/MatchSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/MatchSerializer.java
@@ -31,6 +31,11 @@ public class MatchSerializer extends JsonSerializer<Match> {
 	JsonProcessingException {
 		serializeMatch(jGen, match);
 	}
+	
+	@SuppressWarnings("unchecked") 
+	public static String matchValueToString(Match m, @SuppressWarnings("rawtypes") MatchField mf) {
+		return m.isPartiallyMasked(mf) ? m.getMasked(mf).toString() : m.get(mf).toString();
+	}
 
 	public static void serializeMatch(JsonGenerator jGen, Match match) throws IOException, JsonProcessingException {
 		// list flow matches
@@ -42,115 +47,116 @@ public class MatchSerializer extends JsonSerializer<Match> {
 			MatchField<?> mf = mi.next();
 			switch (mf.id) {
 			case IN_PORT:
-				jGen.writeStringField(MatchUtils.STR_IN_PORT, m.get(MatchField.IN_PORT).toString());
+				jGen.writeStringField(MatchUtils.STR_IN_PORT, matchValueToString(m, mf));
 				break;
 			case IN_PHY_PORT:
-				jGen.writeStringField(MatchUtils.STR_IN_PHYS_PORT, m.get(MatchField.IN_PHY_PORT).toString());
+				jGen.writeStringField(MatchUtils.STR_IN_PHYS_PORT, matchValueToString(m, mf));
 				break;
 			case ARP_OP:
-				jGen.writeNumberField(MatchUtils.STR_ARP_OPCODE, m.get(MatchField.ARP_OP).getOpcode());
+				jGen.writeStringField(MatchUtils.STR_ARP_OPCODE, matchValueToString(m, mf));
 				break;
 			case ARP_SHA:
-				jGen.writeStringField(MatchUtils.STR_ARP_SHA, m.get(MatchField.ARP_SHA).toString());
+				jGen.writeStringField(MatchUtils.STR_ARP_SHA, matchValueToString(m, mf));
 				break;
 			case ARP_SPA:
-				jGen.writeStringField(MatchUtils.STR_ARP_SPA, m.get(MatchField.ARP_SPA).toString());
+				jGen.writeStringField(MatchUtils.STR_ARP_SPA, matchValueToString(m, mf));
 				break;
 			case ARP_THA:
-				jGen.writeStringField(MatchUtils.STR_ARP_DHA, m.get(MatchField.ARP_THA).toString());
+				jGen.writeStringField(MatchUtils.STR_ARP_DHA, matchValueToString(m, mf));
 				break;
 			case ARP_TPA:
-				jGen.writeStringField(MatchUtils.STR_ARP_DPA, m.get(MatchField.ARP_TPA).toString());
+				jGen.writeStringField(MatchUtils.STR_ARP_DPA, matchValueToString(m, mf));
 				break;
-			case ETH_TYPE:
-				jGen.writeNumberField(MatchUtils.STR_DL_TYPE, m.get(MatchField.ETH_TYPE).getValue());
+			case ETH_TYPE: // TODO Remove this "0x" when Loxigen is updated.
+				jGen.writeStringField(MatchUtils.STR_DL_TYPE, m.isPartiallyMasked(mf) ?
+						"0x" + m.getMasked(mf).toString() : "0x" + m.get(mf).toString());
 				break;
 			case ETH_SRC:
-				jGen.writeStringField(MatchUtils.STR_DL_SRC, m.get(MatchField.ETH_SRC).toString());
+				jGen.writeStringField(MatchUtils.STR_DL_SRC, matchValueToString(m, mf));
 				break;
 			case ETH_DST:
-				jGen.writeStringField(MatchUtils.STR_DL_DST, m.get(MatchField.ETH_DST).toString());
+				jGen.writeStringField(MatchUtils.STR_DL_DST, matchValueToString(m, mf));
 				break;
 			case VLAN_VID:
-				jGen.writeNumberField(MatchUtils.STR_DL_VLAN, m.get(MatchField.VLAN_VID).getVlan());
+				jGen.writeStringField(MatchUtils.STR_DL_VLAN, matchValueToString(m, mf));
 				break;
 			case VLAN_PCP:
-				jGen.writeNumberField(MatchUtils.STR_DL_VLAN_PCP, m.get(MatchField.VLAN_PCP).getValue());
+				jGen.writeStringField(MatchUtils.STR_DL_VLAN_PCP, matchValueToString(m, mf));
 				break;
 			case ICMPV4_TYPE:
-				jGen.writeNumberField(MatchUtils.STR_ICMP_TYPE, m.get(MatchField.ICMPV4_TYPE).getType());
+				jGen.writeStringField(MatchUtils.STR_ICMP_TYPE, matchValueToString(m, mf));
 				break;
 			case ICMPV4_CODE:
-				jGen.writeNumberField(MatchUtils.STR_ICMP_CODE, m.get(MatchField.ICMPV4_CODE).getCode());
+				jGen.writeStringField(MatchUtils.STR_ICMP_CODE, matchValueToString(m, mf));
 				break;
 			case ICMPV6_TYPE:
-				jGen.writeNumberField(MatchUtils.STR_ICMPV6_TYPE, m.get(MatchField.ICMPV6_TYPE).getValue());
+				jGen.writeStringField(MatchUtils.STR_ICMPV6_TYPE, matchValueToString(m, mf));
 				break;
 			case ICMPV6_CODE:
-				jGen.writeNumberField(MatchUtils.STR_ICMPV6_CODE, m.get(MatchField.ICMPV6_CODE).getValue());
+				jGen.writeStringField(MatchUtils.STR_ICMPV6_CODE, matchValueToString(m, mf));
 				break;
 			case IP_DSCP:
-				jGen.writeNumberField(MatchUtils.STR_NW_DSCP, m.get(MatchField.IP_DSCP).getDscpValue());
+				jGen.writeStringField(MatchUtils.STR_NW_DSCP, matchValueToString(m, mf));
 				break;
 			case IP_ECN:
-				jGen.writeNumberField(MatchUtils.STR_NW_ECN, m.get(MatchField.IP_ECN).getEcnValue());
+				jGen.writeStringField(MatchUtils.STR_NW_ECN, matchValueToString(m, mf));
 				break;
 			case IP_PROTO:
-				jGen.writeNumberField(MatchUtils.STR_NW_PROTO, m.get(MatchField.IP_PROTO).getIpProtocolNumber());
+				jGen.writeStringField(MatchUtils.STR_NW_PROTO, matchValueToString(m, mf));
 				break;
 			case IPV4_SRC:
-				jGen.writeStringField(MatchUtils.STR_NW_SRC, m.get(MatchField.IPV4_SRC).toString());
+				jGen.writeStringField(MatchUtils.STR_NW_SRC, matchValueToString(m, mf));
 				break;
 			case IPV4_DST:
-				jGen.writeStringField(MatchUtils.STR_NW_DST, m.get(MatchField.IPV4_DST).toString());
+				jGen.writeStringField(MatchUtils.STR_NW_DST, matchValueToString(m, mf));
 				break;
 			case IPV6_SRC:
-				jGen.writeStringField(MatchUtils.STR_IPV6_SRC, m.get(MatchField.IPV6_SRC).toString());
+				jGen.writeStringField(MatchUtils.STR_IPV6_SRC, matchValueToString(m, mf));
 				break;
 			case IPV6_DST:
-				jGen.writeStringField(MatchUtils.STR_IPV6_DST, m.get(MatchField.IPV6_DST).toString());
+				jGen.writeStringField(MatchUtils.STR_IPV6_DST, matchValueToString(m, mf));
 				break;
 			case IPV6_FLABEL:
-				jGen.writeNumberField(MatchUtils.STR_IPV6_FLOW_LABEL, m.get(MatchField.IPV6_FLABEL).getIPv6FlowLabelValue());
+				jGen.writeStringField(MatchUtils.STR_IPV6_FLOW_LABEL, matchValueToString(m, mf));
 				break;
 			case IPV6_ND_SLL:
-				jGen.writeNumberField(MatchUtils.STR_IPV6_ND_SSL, m.get(MatchField.IPV6_ND_SLL).getLong());
+				jGen.writeStringField(MatchUtils.STR_IPV6_ND_SSL, matchValueToString(m, mf));
 				break;
 			case IPV6_ND_TARGET:
-				jGen.writeNumberField(MatchUtils.STR_IPV6_ND_TARGET, m.get(MatchField.IPV6_ND_TARGET).getZeroCompressStart());
+				jGen.writeStringField(MatchUtils.STR_IPV6_ND_TARGET, matchValueToString(m, mf));
 				break;
 			case IPV6_ND_TLL:
-				jGen.writeNumberField(MatchUtils.STR_IPV6_ND_TTL, m.get(MatchField.IPV6_ND_TLL).getLong());
+				jGen.writeStringField(MatchUtils.STR_IPV6_ND_TTL, matchValueToString(m, mf));
 				break;
 			case METADATA:
-				jGen.writeNumberField(MatchUtils.STR_METADATA, m.get(MatchField.METADATA).getValue().getValue());
+				jGen.writeStringField(MatchUtils.STR_METADATA, matchValueToString(m, mf));
 				break;
 			case MPLS_LABEL:
-				jGen.writeNumberField(MatchUtils.STR_MPLS_LABEL, m.get(MatchField.MPLS_LABEL).getValue());
+				jGen.writeStringField(MatchUtils.STR_MPLS_LABEL, matchValueToString(m, mf));
 				break;
 			case MPLS_TC:
-				jGen.writeNumberField(MatchUtils.STR_MPLS_TC, m.get(MatchField.MPLS_TC).getValue());
+				jGen.writeStringField(MatchUtils.STR_MPLS_TC, matchValueToString(m, mf));
 				break;
 			case MPLS_BOS:
-				jGen.writeStringField(MatchUtils.STR_MPLS_BOS, m.get(MatchField.MPLS_BOS).toString());
+				jGen.writeStringField(MatchUtils.STR_MPLS_BOS, matchValueToString(m, mf));
 				break;
 			case SCTP_SRC:
-				jGen.writeNumberField(MatchUtils.STR_SCTP_SRC, m.get(MatchField.SCTP_SRC).getPort());
+				jGen.writeStringField(MatchUtils.STR_SCTP_SRC, matchValueToString(m, mf));
 				break;
 			case SCTP_DST:
-				jGen.writeNumberField(MatchUtils.STR_SCTP_DST, m.get(MatchField.SCTP_DST).getPort());
+				jGen.writeStringField(MatchUtils.STR_SCTP_DST, matchValueToString(m, mf));
 				break;
 			case TCP_SRC:
-				jGen.writeNumberField(MatchUtils.STR_TCP_SRC, m.get(MatchField.TCP_SRC).getPort());
+				jGen.writeStringField(MatchUtils.STR_TCP_SRC, matchValueToString(m, mf));
 				break;
 			case TCP_DST:
-				jGen.writeNumberField(MatchUtils.STR_TCP_DST, m.get(MatchField.TCP_DST).getPort());
+				jGen.writeStringField(MatchUtils.STR_TCP_DST, matchValueToString(m, mf));
 				break;
 			case UDP_SRC:
-				jGen.writeNumberField(MatchUtils.STR_UDP_SRC, m.get(MatchField.UDP_SRC).getPort());
+				jGen.writeStringField(MatchUtils.STR_UDP_SRC, matchValueToString(m, mf));
 				break;
 			case UDP_DST:
-				jGen.writeNumberField(MatchUtils.STR_UDP_DST, m.get(MatchField.UDP_DST).getPort());
+				jGen.writeStringField(MatchUtils.STR_UDP_DST, matchValueToString(m, mf));
 				break;
 			default:
 				// either a BSN or unknown match type
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OFInstructionListSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OFInstructionListSerializer.java
index e16b1854826c709812cb9e79ab5cb638671efb68..a59d38fd3132544e07f8b37dbde600a03c814070 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/OFInstructionListSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OFInstructionListSerializer.java
@@ -45,20 +45,20 @@ public class OFInstructionListSerializer extends JsonSerializer<List<OFInstructi
                     jGen.writeObjectFieldStart(InstructionUtils.STR_CLEAR_ACTIONS);
                     break;
                 case WRITE_METADATA:
-                    jGen.writeStartObject();
+                    jGen.writeObjectFieldStart(InstructionUtils.STR_WRITE_METADATA);
                     jGen.writeNumberField(InstructionUtils.STR_WRITE_METADATA, ((OFInstructionWriteMetadata)i).getMetadata().getValue());
                     jGen.writeNumberField(InstructionUtils.STR_WRITE_METADATA + "_mask", ((OFInstructionWriteMetadata)i).getMetadataMask().getValue());
                     break;
                 case EXPERIMENTER:
-                    jGen.writeStartObject();
+                    jGen.writeObjectFieldStart(InstructionUtils.STR_EXPERIMENTER);
                     jGen.writeNumberField(InstructionUtils.STR_EXPERIMENTER, ((OFInstructionExperimenter)i).getExperimenter());
                     break;
                 case GOTO_TABLE:
-                    jGen.writeStartObject();
+                    jGen.writeObjectFieldStart(InstructionUtils.STR_GOTO_TABLE);
                     jGen.writeNumberField(InstructionUtils.STR_GOTO_TABLE, ((OFInstructionGotoTable)i).getTableId().getValue());
                     break;
                 case METER:
-                    jGen.writeStartObject();
+                    jGen.writeObjectFieldStart(InstructionUtils.STR_GOTO_METER);
                     jGen.writeNumberField(InstructionUtils.STR_GOTO_METER, ((OFInstructionMeter)i).getMeterId());
                     break;
                 case APPLY_ACTIONS:
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java b/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java
index 22b60197be03a9dbd2063552c78b121de6297620..0abf9d2f39ffdd3320ae64e0a1156bacb2cf3b98 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java
@@ -39,7 +39,7 @@ public interface IStaticFlowEntryPusherService extends IFloodlightService {
     public void deleteFlow(String name);
     
     /**
-     * Deletes all static flows for a practicular switch
+     * Deletes all static flows for a particular switch
      * @param dpid The DPID of the switch to delete flows for.
      */
     public void deleteFlowsForSwitch(DatapathId dpid);
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java
index fec72f40add7fcc13d94894453a025f0074a1cfe..94a8686afe655dbfe2ff3ce3eb935c6fc14b24e1 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java
@@ -17,6 +17,7 @@
 package net.floodlightcontroller.staticflowentry;
 
 import java.io.IOException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -37,6 +38,7 @@ import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.databind.MappingJsonFactory;
 
 import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionClearActions;
@@ -90,7 +92,8 @@ public class StaticFlowEntries {
 		.setBufferId(OFBufferId.NO_BUFFER)
 		.setOutPort(OFPort.ANY) 
 		.setCookie(computeEntryCookie(0, entryName))
-		.setPriority(Integer.MAX_VALUE);
+		.setPriority(Integer.MAX_VALUE)
+		.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM));
 		return;
 	}
 
@@ -144,6 +147,8 @@ public class StaticFlowEntries {
 		entry.put(StaticFlowEntryPusher.COLUMN_SWITCH, sw);
 		entry.put(StaticFlowEntryPusher.COLUMN_ACTIVE, Boolean.toString(true));
 		entry.put(StaticFlowEntryPusher.COLUMN_PRIORITY, Integer.toString(fm.getPriority()));
+		entry.put(StaticFlowEntryPusher.COLUMN_IDLE_TIMEOUT, Integer.toString(fm.getIdleTimeout()));
+		entry.put(StaticFlowEntryPusher.COLUMN_HARD_TIMEOUT, Integer.toString(fm.getHardTimeout()));
 
 		switch (fm.getVersion()) {
 		case OF_10:
@@ -367,9 +372,6 @@ public class StaticFlowEntries {
 
 			String n = jp.getCurrentName();
 			jp.nextToken();
-			if (jp.getText().equals("")) {
-				continue;
-			}
 
 			// Java 7 switch-case on strings automatically checks for (deep) string equality.
 			// IMHO, this makes things easier on the eyes than if, else if, else's, and it
@@ -559,6 +561,7 @@ public class StaticFlowEntries {
 				break;
 			default:
 				log.error("Could not decode field from JSON string: {}", n);
+				break;
 			}  
 		} 
 		
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
index ba8a2c5fff06087f1771249d532f5c1b6e8c91e7..3730a095f75b90a6e33c5c4102f54743730a61c6 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
@@ -65,6 +65,11 @@ import org.projectfloodlight.openflow.protocol.OFPortDesc;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFType;
 import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.ver10.OFFlowRemovedReasonSerializerVer10;
+import org.projectfloodlight.openflow.protocol.ver11.OFFlowRemovedReasonSerializerVer11;
+import org.projectfloodlight.openflow.protocol.ver12.OFFlowRemovedReasonSerializerVer12;
+import org.projectfloodlight.openflow.protocol.ver13.OFFlowRemovedReasonSerializerVer13;
+import org.projectfloodlight.openflow.protocol.ver14.OFFlowRemovedReasonSerializerVer14;
 import org.projectfloodlight.openflow.types.DatapathId;
 import org.projectfloodlight.openflow.types.TableId;
 import org.projectfloodlight.openflow.types.U16;
@@ -132,7 +137,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 	public static final String COLUMN_ARP_DHA = MatchUtils.STR_ARP_DHA;
 	public static final String COLUMN_ARP_SPA = MatchUtils.STR_ARP_SPA;
 	public static final String COLUMN_ARP_DPA = MatchUtils.STR_ARP_DPA;
-	
+
 	/* IPv6 related columns */
 	public static final String COLUMN_NW6_SRC = MatchUtils.STR_IPV6_SRC;
 	public static final String COLUMN_NW6_DST = MatchUtils.STR_IPV6_DST;
@@ -154,7 +159,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 	/* end newly added matches */
 
 	public static final String COLUMN_ACTIONS = "actions";
-	
+
 	public static final String COLUMN_INSTR_GOTO_TABLE = InstructionUtils.STR_GOTO_TABLE; // instructions are each getting their own column, due to write and apply actions, which themselves contain a variable list of actions
 	public static final String COLUMN_INSTR_WRITE_METADATA = InstructionUtils.STR_WRITE_METADATA;
 	public static final String COLUMN_INSTR_WRITE_ACTIONS = InstructionUtils.STR_WRITE_ACTIONS;
@@ -175,7 +180,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 		COLUMN_ICMP_TYPE, COLUMN_ICMP_CODE, 
 		COLUMN_ARP_OPCODE, COLUMN_ARP_SHA, COLUMN_ARP_DHA, 
 		COLUMN_ARP_SPA, COLUMN_ARP_DPA,
-		
+
 		/* IPv6 related matches */
 		COLUMN_NW6_SRC, COLUMN_NW6_DST, COLUMN_ICMP6_TYPE, COLUMN_ICMP6_CODE, 
 		COLUMN_IPV6_FLOW_LABEL, COLUMN_ND_SLL, COLUMN_ND_TLL, COLUMN_ND_TARGET,		
@@ -189,7 +194,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 		COLUMN_INSTR_CLEAR_ACTIONS, COLUMN_INSTR_GOTO_METER,
 		COLUMN_INSTR_EXPERIMENTER
 		/* end newly added instructions */
-		};
+	};
 
 	protected IFloodlightProviderService floodlightProviderService;
 	protected IOFSwitchService switchService;
@@ -365,11 +370,11 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 				if (row.get(key) == null) {
 					continue;
 				}
-				
+
 				if (key.equals(COLUMN_SWITCH) || key.equals(COLUMN_NAME) || key.equals("id")) {
 					continue; // already handled
 				}
-				
+
 				if (key.equals(COLUMN_ACTIVE)) {
 					if  (!Boolean.valueOf((String) row.get(COLUMN_ACTIVE))) {
 						log.debug("skipping inactive entry {} for switch {}", entryName, switchName);
@@ -489,17 +494,17 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 				entriesFromStorage.put(dpid, new HashMap<String, OFFlowMod>());
 
 			List<OFMessage> outQueue = new ArrayList<OFMessage>();
-			
+
 			/* For every flow per dpid, decide how to "add" the flow. */
 			for (String entry : entriesToAdd.get(dpid).keySet()) {
 				OFFlowMod newFlowMod = entriesToAdd.get(dpid).get(entry);
 				OFFlowMod oldFlowMod = null;
-				
+
 				String dpidOldFlowMod = entry2dpid.get(entry);
 				if (dpidOldFlowMod != null) {
 					oldFlowMod = entriesFromStorage.get(dpidOldFlowMod).remove(entry);
 				}
-				
+
 				/* Modify, which can be either a Flow MODIFY_STRICT or a Flow DELETE_STRICT with a side of Flow ADD */
 				if (oldFlowMod != null && newFlowMod != null) { 
 					/* MODIFY_STRICT b/c the match is still the same */
@@ -511,7 +516,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 						entry2dpid.put(entry, dpid);
 						newFlowMod = FlowModUtils.toFlowModifyStrict(newFlowMod);
 						outQueue.add(newFlowMod);
-					/* DELETE_STRICT and then ADD b/c the match is now different */
+						/* DELETE_STRICT and then ADD b/c the match is now different */
 					} else {
 						log.debug("DeleteStrict and Add SFP Flow");
 						oldFlowMod = FlowModUtils.toFlowDeleteStrict(oldFlowMod);
@@ -520,7 +525,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 						if (dpidOldFlowMod.equals(dpid)) {
 							outQueue.add(oldFlowMod);
 							outQueue.add(addTmp); 
-						/* Otherwise, go ahead and send the flows now (since queuing them will send to the wrong switch). */
+							/* Otherwise, go ahead and send the flows now (since queuing them will send to the wrong switch). */
 						} else {
 							writeOFMessageToSwitch(DatapathId.of(dpidOldFlowMod), oldFlowMod);
 							writeOFMessageToSwitch(DatapathId.of(dpid), FlowModUtils.toFlowAdd(newFlowMod)); 
@@ -528,14 +533,14 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 						entriesFromStorage.get(dpid).put(entry, addTmp);
 						entry2dpid.put(entry, dpid);			
 					}
-				/* Add a brand-new flow with ADD */
+					/* Add a brand-new flow with ADD */
 				} else if (newFlowMod != null && oldFlowMod == null) {
 					log.debug("Add SFP Flow");
 					OFFlowAdd addTmp = FlowModUtils.toFlowAdd(newFlowMod);
 					entriesFromStorage.get(dpid).put(entry, addTmp);
 					entry2dpid.put(entry, dpid);
 					outQueue.add(addTmp);
-				/* Something strange happened, so remove the flow */
+					/* Something strange happened, so remove the flow */
 				} else if (newFlowMod == null) { 
 					entriesFromStorage.get(dpid).remove(entry);
 					entry2dpid.remove(entry);
@@ -666,7 +671,6 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 		sw.write(flowMod);
 		sw.flush();
 	}
-
 	@Override
 	public String getName() {
 		return StaticFlowName;
@@ -688,13 +692,74 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 		 * never expire.
 		 */
 		if (AppCookie.extractApp(cookie) == STATIC_FLOW_APP_ID) {
-			if (OFFlowRemovedReason.DELETE.equals(msg.getReason()))
-				log.error("Got a FlowRemove message for a infinite " +
-						"timeout flow: {} from switch {}", msg, sw);
-			// Stop the processing chain since we sent the delete.
-			return Command.STOP;
+			OFFlowRemovedReason reason = null;
+			switch (msg.getVersion()) {
+			case OF_10:
+				reason = OFFlowRemovedReasonSerializerVer10.ofWireValue((byte) msg.getReason());
+				break;
+			case OF_11:
+				reason = OFFlowRemovedReasonSerializerVer11.ofWireValue((byte) msg.getReason());
+				break;
+			case OF_12:
+				reason = OFFlowRemovedReasonSerializerVer12.ofWireValue((byte) msg.getReason());
+				break;
+			case OF_13:
+				reason = OFFlowRemovedReasonSerializerVer13.ofWireValue((byte) msg.getReason());
+				break;
+			case OF_14:
+				reason = OFFlowRemovedReasonSerializerVer14.ofWireValue((byte) msg.getReason());
+				break;
+			default:
+				log.debug("OpenFlow version {} unsupported for OFFlowRemovedReasonSerializerVerXX", msg.getVersion());
+				break;
+			}
+			if (reason != null) {
+				if (OFFlowRemovedReason.DELETE == reason) {
+					log.error("Got a FlowRemove message for a infinite " + 
+							"timeout flow: {} from switch {}", msg, sw);
+				} else if (OFFlowRemovedReason.HARD_TIMEOUT == reason || OFFlowRemovedReason.IDLE_TIMEOUT == reason) {
+					/* Remove the Flow from the DB since it timed out */
+					log.debug("Received an IDLE or HARD timeout for an SFP flow. Removing it from the SFP DB.");
+					/* 
+					 * Lookup the flow based on the flow contents. We do not know/care about the name of the 
+					 * flow based on this message, but we can get the table values for this switch and search.
+					 */
+					String flowToRemove = null;
+					Map<String, OFFlowMod> flowsByName = getFlows(sw.getId());
+					for (Map.Entry<String, OFFlowMod> entry : flowsByName.entrySet()) {
+						if (msg.getCookie().equals(entry.getValue().getCookie()) &&
+								msg.getHardTimeout() == entry.getValue().getHardTimeout() &&
+								msg.getIdleTimeout() == entry.getValue().getIdleTimeout() &&
+								msg.getMatch().equals(entry.getValue().getMatch()) &&
+								msg.getPriority() == entry.getValue().getPriority() &&
+								msg.getTableId().equals(entry.getValue().getTableId())
+							) {
+							flowToRemove = entry.getKey();
+							break;
+						}
+					}
+					
+					log.debug("Flow to Remove: {}", flowToRemove);
+					
+					/*
+					 * Remove the flow. This will send the delete message to the switch,
+					 * since we cannot tell the storage listener rowsdeleted() that we
+					 * are only removing our local DB copy of the flow and that it actually
+					 * timed out on the switch and is already gone. The switch will silently
+					 * discard the delete message in this case.
+					 * 
+					 * TODO: We should come up with a way to convey to the storage listener
+					 * the reason for the flow being removed.
+					 */
+					if (flowToRemove != null) {
+						deleteFlow(flowToRemove);
+					}
+				}
+				/* Stop the processing chain since we sent or asked for the delete message. */
+				return Command.STOP;
+			}
 		}
-
+		/* Continue the processing chain, since we did not send the delete. */
 		return Command.CONTINUE;
 	}
 
@@ -787,7 +852,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
 			storageSourceService.insertRowAsync(TABLE_NAME, fmMap);
 		} catch (Exception e) {
 			log.error("Error! Check the fields specified for the flow.Make sure IPv4 fields are not mixed with IPv6 fields or all "
-            		+ "mandatory fields are specified. ");
+					+ "mandatory fields are specified. ");
 		}
 	}
 
diff --git a/src/main/java/net/floodlightcontroller/util/InstructionUtils.java b/src/main/java/net/floodlightcontroller/util/InstructionUtils.java
index 1de33710366a6d2c8057498d5411780165dc92ce..aa89c1b581156c6dbdda3f75107bf2db74dfbe9b 100644
--- a/src/main/java/net/floodlightcontroller/util/InstructionUtils.java
+++ b/src/main/java/net/floodlightcontroller/util/InstructionUtils.java
@@ -278,7 +278,7 @@ public class InstructionUtils {
 			return;
 		}
 
-		if (inst != null && inst.isEmpty()) {
+		if (inst != null && inst.trim().isEmpty()) { /* Allow the empty string, since this is what specifies clear (i.e. key clear does not have any defined values). */
 			OFInstructionClearActions i = OFFactories.getFactory(fmb.getVersion()).instructions().clearActions();
 			log.debug("Appending ClearActions instruction: {}", i);
 			appendInstruction(fmb, i);
diff --git a/src/main/java/net/floodlightcontroller/util/MatchUtils.java b/src/main/java/net/floodlightcontroller/util/MatchUtils.java
index 9b16fa7a8ebaa4f1deb8301049e47b605755f15f..9693561690f146aa6e9d7280fc8aadca2eacfb83 100644
--- a/src/main/java/net/floodlightcontroller/util/MatchUtils.java
+++ b/src/main/java/net/floodlightcontroller/util/MatchUtils.java
@@ -11,9 +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.IPv6Address;
 import org.projectfloodlight.openflow.types.IPv6AddressWithMask;
 import org.projectfloodlight.openflow.types.IPv6FlowLabel;
 import org.projectfloodlight.openflow.types.IpDscp;
@@ -388,19 +386,33 @@ public class MatchUtils {
 
 			switch (key_value[0]) {
 			case STR_IN_PORT:
-				mb.setExact(MatchField.IN_PORT, OFPort.of(Integer.valueOf(key_value[1])));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.IN_PORT, OFPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+				} else {
+					mb.setMasked(MatchField.IN_PORT, OFPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+					OFPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+				}
 				break;
-			case STR_DL_DST:
-				mb.setExact(MatchField.ETH_DST, MacAddress.of(key_value[1]));
+			case STR_DL_DST: /* Only accept hex-string for MAC addresses */
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ETH_DST, MacAddress.of(dataMask[0]));
+				} else {
+					mb.setMasked(MatchField.ETH_DST, MacAddress.of(dataMask[0]), MacAddress.of(dataMask[1]));
+				}
 				break;
 			case STR_DL_SRC:
-				mb.setExact(MatchField.ETH_SRC, MacAddress.of(key_value[1]));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ETH_SRC, MacAddress.of(dataMask[0]));
+				} else {
+					mb.setMasked(MatchField.ETH_SRC, MacAddress.of(dataMask[0]), MacAddress.of(dataMask[1]));
+				}
 				break;
 			case STR_DL_TYPE:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.ETH_TYPE, EthType.of(Integer.valueOf(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ETH_TYPE, EthType.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.ETH_TYPE, EthType.of(Integer.valueOf(key_value[1])));
+					mb.setMasked(MatchField.ETH_TYPE, EthType.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+					EthType.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_DL_VLAN:
@@ -413,19 +425,20 @@ public class MatchUtils {
 				}
 				break;
 			case STR_DL_VLAN_PCP:
-				if (key_value[1].startsWith("0x")) { 
-					mb.setExact(MatchField.VLAN_PCP, VlanPcp.of(U8.t(Short.valueOf(key_value[1].replaceFirst("0x", ""), 16))));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.VLAN_PCP, VlanPcp.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))));
 				} else {
-					mb.setExact(MatchField.VLAN_PCP, VlanPcp.of(U8.t(Short.valueOf(key_value[1]))));
+					mb.setMasked(MatchField.VLAN_PCP, VlanPcp.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))), 
+					VlanPcp.of(dataMask[1].contains("0x") ? U8.t(Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[1]))));
 				}
 				break;
-			case STR_NW_DST:
+			case STR_NW_DST: /* Only accept dotted-decimal for IPv4 addresses */
 				mb.setMasked(MatchField.IPV4_DST, IPv4AddressWithMask.of(key_value[1]));
 				break;
 			case STR_NW_SRC:
 				mb.setMasked(MatchField.IPV4_SRC, IPv4AddressWithMask.of(key_value[1]));
 				break;
-			case STR_IPV6_DST:
+			case STR_IPV6_DST: /* Only accept hex-string for IPv6 addresses */
 				if (ver10 == true) {
 					throw new IllegalArgumentException("OF Version incompatible");
 				}
@@ -441,207 +454,297 @@ public class MatchUtils {
 				if (ver10 == true) {
 					throw new IllegalArgumentException("OF Version incompatible");
 				}
-				if (key_value[1].startsWith("0x")) { 
-					mb.setExact(MatchField.IPV6_FLABEL, IPv6FlowLabel.of(Integer.parseInt(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.IPV6_FLABEL, IPv6FlowLabel.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.IPV6_FLABEL, IPv6FlowLabel.of(Integer.parseInt(key_value[1])));
+					mb.setMasked(MatchField.IPV6_FLABEL, IPv6FlowLabel.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+					IPv6FlowLabel.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_NW_PROTO:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.IP_PROTO, IpProtocol.of(Short.valueOf(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.IP_PROTO, IpProtocol.of(dataMask[0].contains("0x") ? Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.IP_PROTO, IpProtocol.of(Short.valueOf(key_value[1])));
+					mb.setMasked(MatchField.IP_PROTO, IpProtocol.of(dataMask[0].contains("0x") ? Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[0])), 
+					IpProtocol.of(dataMask[1].contains("0x") ? Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_NW_TOS:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.IP_ECN, IpEcn.of(U8.t(Short.valueOf(key_value[1].replaceFirst("0x", ""), 16))));
-					mb.setExact(MatchField.IP_DSCP, IpDscp.of(U8.t(Short.valueOf(key_value[1].replaceFirst("0x", ""), 16))));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.IP_ECN, IpEcn.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))));
+					mb.setExact(MatchField.IP_DSCP, IpDscp.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))));
 				} else {
-					mb.setExact(MatchField.IP_ECN, IpEcn.of(U8.t(Short.valueOf(key_value[1]))));
-					mb.setExact(MatchField.IP_DSCP, IpDscp.of(U8.t(Short.valueOf(key_value[1]))));
+					mb.setMasked(MatchField.IP_ECN, IpEcn.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))), 
+							IpEcn.of(dataMask[1].contains("0x") ? U8.t(Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[1]))));
+					mb.setMasked(MatchField.IP_DSCP, IpDscp.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))), 
+							IpDscp.of(dataMask[1].contains("0x") ? U8.t(Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[1]))));
 				}
 				break;
 			case STR_NW_ECN:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.IP_ECN, IpEcn.of(U8.t(Short.valueOf(key_value[1].replaceFirst("0x", ""), 16))));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.IP_ECN, IpEcn.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))));
 				} else {
-					mb.setExact(MatchField.IP_ECN, IpEcn.of(U8.t(Short.valueOf(key_value[1]))));
+					mb.setMasked(MatchField.IP_ECN, IpEcn.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))), 
+							IpEcn.of(dataMask[1].contains("0x") ? U8.t(Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[1]))));
 				}
 				break;
 			case STR_NW_DSCP:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.IP_DSCP, IpDscp.of(U8.t(Short.valueOf(key_value[1].replaceFirst("0x", ""), 16))));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.IP_DSCP, IpDscp.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))));
 				} else {
-					mb.setExact(MatchField.IP_DSCP, IpDscp.of(U8.t(Short.valueOf(key_value[1]))));
+					mb.setMasked(MatchField.IP_DSCP, IpDscp.of(dataMask[0].contains("0x") ? U8.t(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[0]))), 
+							IpDscp.of(dataMask[1].contains("0x") ? U8.t(Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U8.t(Short.valueOf(dataMask[1]))));
 				}
 				break;
 			case STR_SCTP_DST: // for transport ports, if we don't know the transport protocol yet, postpone parsing this [key, value] pair until we know. Put it at the back of the queue.
 				if (mb.get(MatchField.IP_PROTO) == null) {
 					llValues.add(key_value); // place it back if we can't proceed yet
 				} else {
-					mb.setExact(MatchField.SCTP_DST, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.SCTP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.SCTP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				}
 				break;
 			case STR_SCTP_SRC:
 				if (mb.get(MatchField.IP_PROTO) == null) {
 					llValues.add(key_value); // place it back if we can't proceed yet
 				} else {
-					mb.setExact(MatchField.SCTP_SRC, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.SCTP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.SCTP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				}
 				break;
 			case STR_UDP_DST:
 				if (mb.get(MatchField.IP_PROTO) == null) {
 					llValues.add(key_value); // place it back if we can't proceed yet
 				} else {
-					mb.setExact(MatchField.UDP_DST, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.UDP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.UDP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				}
 				break;
 			case STR_UDP_SRC:
 				if (mb.get(MatchField.IP_PROTO) == null) {
 					llValues.add(key_value); // place it back if we can't proceed yet
 				} else {
-					mb.setExact(MatchField.UDP_SRC, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.UDP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.UDP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				}
 				break;
 			case STR_TCP_DST:
 				if (mb.get(MatchField.IP_PROTO) == null) {
 					llValues.add(key_value); // place it back if we can't proceed yet
 				} else {
-					mb.setExact(MatchField.TCP_DST, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.TCP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.TCP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				}
 				break;
 			case STR_TCP_SRC:
 				if (mb.get(MatchField.IP_PROTO) == null) {
 					llValues.add(key_value); // place it back if we can't proceed yet
 				} else {
-					mb.setExact(MatchField.TCP_SRC, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.TCP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.TCP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				}
 				break;
 			case STR_TP_DST: // support for OF1.0 generic transport ports
 				if ((ipProto = mb.get(MatchField.IP_PROTO)) == null) {
 					llValues.add(key_value); // place it back if we can't proceed yet
 				} else if (ipProto == IpProtocol.TCP){
-					mb.setExact(MatchField.TCP_DST, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.TCP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.TCP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				} else if (ipProto == IpProtocol.UDP){
-					mb.setExact(MatchField.UDP_DST, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.UDP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.UDP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				} else if (ipProto == IpProtocol.SCTP){
-					mb.setExact(MatchField.SCTP_DST, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.SCTP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.SCTP_DST, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				}
 				break;
 			case STR_TP_SRC:
 				if ((ipProto = mb.get(MatchField.IP_PROTO)) == null) {
 					llValues.add(key_value); // place it back if we can't proceed yet
 				}  else if (ipProto == IpProtocol.TCP){
-					mb.setExact(MatchField.TCP_SRC, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.TCP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.TCP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				} else if (ipProto == IpProtocol.UDP){
-					mb.setExact(MatchField.UDP_SRC, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.UDP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.UDP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				} else if (ipProto == IpProtocol.SCTP){
-					mb.setExact(MatchField.SCTP_SRC, TransportPort.of(Integer.valueOf(key_value[1])));
+					if (dataMask.length == 1) {
+						mb.setExact(MatchField.SCTP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])));
+					} else {
+						mb.setMasked(MatchField.SCTP_SRC, TransportPort.of(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), 
+								TransportPort.of(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])));
+					}
 				}
 				break;
 			case STR_ICMP_TYPE:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.ICMPV4_TYPE, ICMPv4Type.of(Short.parseShort(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ICMPV4_TYPE, ICMPv4Type.of(dataMask[0].contains("0x") ? Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.ICMPV4_TYPE, ICMPv4Type.of(Short.parseShort(key_value[1])));
+					mb.setMasked(MatchField.ICMPV4_TYPE, ICMPv4Type.of(dataMask[0].contains("0x") ? Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[0])), 
+							ICMPv4Type.of(dataMask[1].contains("0x") ? Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_ICMP_CODE:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.ICMPV4_CODE, ICMPv4Code.of(Short.parseShort(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ICMPV4_CODE, ICMPv4Code.of(dataMask[0].contains("0x") ? Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.ICMPV4_CODE, ICMPv4Code.of(Short.parseShort(key_value[1])));
+					mb.setMasked(MatchField.ICMPV4_CODE, ICMPv4Code.of(dataMask[0].contains("0x") ? Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[0])), 
+							ICMPv4Code.of(dataMask[1].contains("0x") ? Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Short.valueOf(dataMask[1])));
 				}
 				break;
-
-				//sanjivini
 			case STR_ICMPV6_TYPE:
 				if (ver10 == true) {
 					throw new IllegalArgumentException("OF Version incompatible");
-					//throw new Exception("OF Version incompatible");
 				}
-				mb.setExact(MatchField.ICMPV6_TYPE, U8.of(Short.parseShort(key_value[1])));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ICMPV6_TYPE, dataMask[0].contains("0x") ? U8.of(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[0])));
+				} else {
+					mb.setMasked(MatchField.ICMPV6_TYPE, dataMask[0].contains("0x") ? U8.of(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[0])), 
+							dataMask[1].contains("0x") ? U8.of(Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[1])));
+				}
 				break;
 			case STR_ICMPV6_CODE:
 				if (ver10 == true) {
 					throw new IllegalArgumentException("OF Version incompatible");
-					//throw new Exception("OF Version incompatible");
 				}
-				mb.setExact(MatchField.ICMPV6_CODE, U8.of(Short.parseShort(key_value[1])));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ICMPV6_CODE, dataMask[0].contains("0x") ? U8.of(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[0])));
+				} else {
+					mb.setMasked(MatchField.ICMPV6_CODE, dataMask[0].contains("0x") ? U8.of(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[0])), 
+							dataMask[1].contains("0x") ? U8.of(Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[1])));
+				}
 				break;
 			case STR_IPV6_ND_SSL:
 				if (ver10 == true) {
 					throw new IllegalArgumentException("OF Version incompatible");
-					//throw new Exception("OF Version incompatible");
 				}
-				mb.setExact(MatchField.IPV6_ND_SLL, MacAddress.of(key_value[1]));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.IPV6_ND_SLL, MacAddress.of(dataMask[0]));
+				} else {
+					mb.setMasked(MatchField.IPV6_ND_SLL, MacAddress.of(dataMask[0]), MacAddress.of(dataMask[1]));
+				}
 				break;
 			case STR_IPV6_ND_TTL:
 				if (ver10 == true) {
 					throw new IllegalArgumentException("OF Version incompatible");
-					//throw new Exception("OF Version incompatible");
 				}
-				mb.setExact(MatchField.IPV6_ND_TLL, MacAddress.of(key_value[1]));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.IPV6_ND_TLL, MacAddress.of(dataMask[0]));
+				} else {
+					mb.setMasked(MatchField.IPV6_ND_TLL, MacAddress.of(dataMask[0]), MacAddress.of(dataMask[1]));
+				}
 				break;
 			case STR_IPV6_ND_TARGET:
 				if (ver10 == true) {
 					throw new IllegalArgumentException("OF Version incompatible");
-					//throw new Exception("OF Version incompatible");
 				}
-				mb.setExact(MatchField.IPV6_ND_TARGET, IPv6Address.of(key_value[1]));
+				mb.setMasked(MatchField.IPV6_ND_TARGET, IPv6AddressWithMask.of(key_value[1]));
 				break;
-				//sanjivini	
-
 			case STR_ARP_OPCODE:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.ARP_OP, ArpOpcode.of(Integer.parseInt(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ARP_OP, dataMask[0].contains("0x") ? ArpOpcode.of(Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : ArpOpcode.of(Integer.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.ARP_OP, ArpOpcode.of(Integer.parseInt(key_value[1])));
+					mb.setMasked(MatchField.ARP_OP, dataMask[0].contains("0x") ? ArpOpcode.of(Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : ArpOpcode.of(Integer.valueOf(dataMask[0])), 
+							dataMask[1].contains("0x") ? ArpOpcode.of(Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : ArpOpcode.of(Integer.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_ARP_SHA:
-				mb.setExact(MatchField.ARP_SHA, MacAddress.of(key_value[1]));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ARP_SHA, MacAddress.of(dataMask[0]));
+				} else {
+					mb.setMasked(MatchField.ARP_SHA, MacAddress.of(dataMask[0]), MacAddress.of(dataMask[1]));
+				}
 				break;
 			case STR_ARP_DHA:
-				mb.setExact(MatchField.ARP_THA, MacAddress.of(key_value[1]));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.ARP_THA, MacAddress.of(dataMask[0]));
+				} else {
+					mb.setMasked(MatchField.ARP_THA, MacAddress.of(dataMask[0]), MacAddress.of(dataMask[1]));
+				}
 				break;
 			case STR_ARP_SPA:
-				mb.setExact(MatchField.ARP_SPA, IPv4Address.of(key_value[1]));
+				mb.setMasked(MatchField.ARP_SPA, IPv4AddressWithMask.of(key_value[1]));
 				break;
 			case STR_ARP_DPA:
-				mb.setExact(MatchField.ARP_TPA, IPv4Address.of(key_value[1]));
+				mb.setMasked(MatchField.ARP_TPA, IPv4AddressWithMask.of(key_value[1]));
 				break;
 			case STR_MPLS_LABEL:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.MPLS_LABEL, U32.of(Long.parseLong(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.MPLS_LABEL, dataMask[0].contains("0x") ? U32.of(Long.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U32.of(Long.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.MPLS_LABEL, U32.of(Long.parseLong(key_value[1])));
+					mb.setMasked(MatchField.MPLS_LABEL, dataMask[0].contains("0x") ? U32.of(Long.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U32.of(Long.valueOf(dataMask[0])), 
+							dataMask[1].contains("0x") ? U32.of(Long.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U32.of(Long.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_MPLS_TC:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.MPLS_TC, U8.of(Short.parseShort(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.MPLS_TC, dataMask[0].contains("0x") ? U8.of(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.MPLS_TC, U8.of(Short.parseShort(key_value[1])));
+					mb.setMasked(MatchField.MPLS_TC, dataMask[0].contains("0x") ? U8.of(Short.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[0])), 
+							dataMask[1].contains("0x") ? U8.of(Short.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U8.of(Short.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_MPLS_BOS:
 				mb.setExact(MatchField.MPLS_BOS, key_value[1].equalsIgnoreCase("true") ? OFBooleanValue.TRUE : OFBooleanValue.FALSE);
 				break;
 			case STR_METADATA:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.METADATA, OFMetadata.ofRaw(Long.parseLong(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.METADATA, dataMask[0].contains("0x") ? OFMetadata.ofRaw(Long.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : OFMetadata.ofRaw(Long.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.METADATA, OFMetadata.ofRaw(Long.parseLong(key_value[1])));
+					mb.setMasked(MatchField.METADATA, dataMask[0].contains("0x") ? OFMetadata.ofRaw(Long.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : OFMetadata.ofRaw(Long.valueOf(dataMask[0])), 
+							dataMask[1].contains("0x") ? OFMetadata.ofRaw(Long.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : OFMetadata.ofRaw(Long.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_TUNNEL_ID:
-				if (key_value[1].startsWith("0x")) {
-					mb.setExact(MatchField.TUNNEL_ID, U64.of(Long.parseLong(key_value[1].replaceFirst("0x", ""), 16)));
+				if (dataMask.length == 1) {
+					mb.setExact(MatchField.TUNNEL_ID, dataMask[0].contains("0x") ? U64.of(Long.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U64.of(Long.valueOf(dataMask[0])));
 				} else {
-					mb.setExact(MatchField.TUNNEL_ID, U64.of(Long.parseLong(key_value[1])));
+					mb.setMasked(MatchField.TUNNEL_ID, dataMask[0].contains("0x") ? U64.of(Long.valueOf(dataMask[0].replaceFirst("0x", ""), 16)) : U64.of(Long.valueOf(dataMask[0])), 
+							dataMask[1].contains("0x") ? U64.of(Long.valueOf(dataMask[1].replaceFirst("0x", ""), 16)) : U64.of(Long.valueOf(dataMask[1])));
 				}
 				break;
 			case STR_PBB_ISID: