Complete the work toward Issue #215 and Issue #216:

 * Added back-end support for matching conditions and actions for flows.
 * Fixed a bug in setting the inPort matching condition.

NOTE: to match IP Source or Destination address, we must
add "matchEthernetFrameType 2048" to the set of matching conditions. E.g:

web/add_flow.py 1 FOOBAR 00:00:00:00:00:00:00:01 0 00:00:00:00:00:00:00:02 0 matchDstMac 00:11:22:33:44:55 matchDstIPv4Net 10.0.0.0/8 matchEthernetFrameType 2048
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java b/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
index 8788aa7..c70ab16 100644
--- a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
+++ b/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
@@ -193,18 +193,6 @@
 		@Property("switch_dpid")
 		public void setSwitchDpid(String switchDpid);
 
-		@Property("in_port")
-		public Short getInPort();
-
-		@Property("in_port")
-		public void setInPort(Short inPort);
-
-		@Property("out_port")
-		public Short getOutPort();
-
-		@Property("out_port")
-		public void setOutPort(Short outPort);
-
 		@Property("user_state")
 		public String getUserState();
 
@@ -228,5 +216,47 @@
 
 		@Property("error_state_code")
 		public void setErrorStateCode(String errorStateCode);
+
+		@Property("matchInPort")
+		public Short getMatchInPort();
+
+		@Property("matchInPort")
+		public void setMatchInPort(Short matchInPort);
+
+		@Property("matchEthernetFrameType")
+		public Short getMatchEthernetFrameType();
+
+		@Property("matchEthernetFrameType")
+		public void setMatchEthernetFrameType(Short matchEthernetFrameType);
+
+		@Property("matchSrcMac")
+		public String getMatchSrcMac();
+
+		@Property("matchSrcMac")
+		public void setMatchSrcMac(String matchSrcMac);
+
+		@Property("matchDstMac")
+		public String getMatchDstMac();
+
+		@Property("matchDstMac")
+		public void setMatchDstMac(String matchDstMac);
+
+		@Property("matchSrcIPv4Net")
+		public String getMatchSrcIPv4Net();
+
+		@Property("matchSrcIPv4Net")
+		public void setMatchSrcIPv4Net(String matchSrcIPv4Net);
+
+		@Property("matchDstIPv4Net")
+		public String getMatchDstIPv4Net();
+
+		@Property("matchDstIPv4Net")
+		public void setMatchDstIPv4Net(String matchDstIPv4Net);
+
+		@Property("actionOutput")
+		public Short getActionOutput();
+
+		@Property("actionOutput")
+		public void setActionOutput(Short actionOutput);
 	}
 }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 8cf1982..838c3ed 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -29,11 +29,15 @@
 import net.floodlightcontroller.util.Dpid;
 import net.floodlightcontroller.util.DataPathEndpoints;
 import net.floodlightcontroller.util.FlowEntry;
+import net.floodlightcontroller.util.FlowEntryAction;
 import net.floodlightcontroller.util.FlowEntryId;
+import net.floodlightcontroller.util.FlowEntryMatch;
 import net.floodlightcontroller.util.FlowEntrySwitchState;
 import net.floodlightcontroller.util.FlowEntryUserState;
 import net.floodlightcontroller.util.FlowId;
 import net.floodlightcontroller.util.FlowPath;
+import net.floodlightcontroller.util.IPv4Net;
+import net.floodlightcontroller.util.MACAddress;
 import net.floodlightcontroller.util.OFMessageDamper;
 import net.floodlightcontroller.util.Port;
 import net.onrc.onos.util.GraphDBConnection;
@@ -123,14 +127,54 @@
 			continue;
 		    }
 
+		    //
+		    // Fetch the match conditions
+		    //
 		    OFMatch match = new OFMatch();
-		    match.setInputPort(flowEntryObj.getInPort());
+		    match.setWildcards(OFMatch.OFPFW_ALL);
+		    Short matchInPort = flowEntryObj.getMatchInPort();
+		    if (matchInPort != null) {
+			match.setInputPort(matchInPort);
+			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
+		    }
+		    Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+		    if (matchEthernetFrameType != null) {
+			match.setDataLayerType(matchEthernetFrameType);
+			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+		    }
+		    String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+		    if (matchSrcIPv4Net != null) {
+			match.setFromCIDR(matchSrcIPv4Net, OFMatch.STR_NW_SRC);
+		    }
+		    String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+		    if (matchDstIPv4Net != null) {
+			match.setFromCIDR(matchDstIPv4Net, OFMatch.STR_NW_DST);
+		    }
+		    String matchSrcMac = flowEntryObj.getMatchSrcMac();
+		    if (matchSrcMac != null) {
+			match.setDataLayerSource(matchSrcMac);
+			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
+		    }
+		    String matchDstMac = flowEntryObj.getMatchDstMac();
+		    if (matchDstMac != null) {
+			match.setDataLayerDestination(matchDstMac);
+			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
+		    }
+		    log.debug("PAVPAV {}:", match.toString());
 
-		    OFActionOutput action = new OFActionOutput();
-		    action.setMaxLength((short)0xffff);
-		    action.setPort(flowEntryObj.getOutPort());
+
+		    //
+		    // Fetch the actions
+		    //
 		    List<OFAction> actions = new ArrayList<OFAction>();
-		    actions.add(action);
+		    Short actionOutputPort = flowEntryObj.getActionOutput();
+		    if (actionOutputPort != null) {
+			OFActionOutput action = new OFActionOutput();
+			// XXX: The max length is hard-coded for now
+			action.setMaxLength((short)0xffff);
+			action.setPort(actionOutputPort);
+			actions.add(action);
+		    }
 
 		    fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
 			.setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
@@ -351,15 +395,35 @@
 	    // - flowEntry.flowEntryMatch()
 	    // - flowEntry.flowEntryActions()
 	    // - flowEntry.dpid()
-	    // - flowEntry.inPort()
-	    // - flowEntry.outPort()
 	    // - flowEntry.flowEntryUserState()
 	    // - flowEntry.flowEntrySwitchState()
 	    // - flowEntry.flowEntryErrorState()
+	    // - flowEntry.matchInPort()
+	    // - flowEntry.matchEthernetFrameType()
+	    // - flowEntry.matchSrcIPv4Net()
+	    // - flowEntry.matchDstIPv4Net()
+	    // - flowEntry.matchSrcMac()
+	    // - flowEntry.matchDstMac()
+	    // - flowEntry.actionOutput()
 	    //
 	    flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
-	    flowEntryObj.setInPort(flowEntry.inPort().value());
-	    flowEntryObj.setOutPort(flowEntry.outPort().value());
+	    if (flowEntry.flowEntryMatch().matchInPort())
+		flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
+	    if (flowEntry.flowEntryMatch().matchEthernetFrameType())
+		flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
+	    if (flowEntry.flowEntryMatch().matchSrcIPv4Net())
+		flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
+	    if (flowEntry.flowEntryMatch().matchDstIPv4Net())
+		flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
+	    if (flowEntry.flowEntryMatch().matchSrcMac())
+		flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
+	    if (flowEntry.flowEntryMatch().matchDstMac())
+		flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
+
+	    for (FlowEntryAction fa : flowEntry.flowEntryActions()) {
+		if (fa.actionOutput() != null)
+		    flowEntryObj.setActionOutput(fa.actionOutput().port().value());
+	    }
 	    // TODO: Hacks with hard-coded state names!
 	    if (found)
 		flowEntryObj.setUserState("FE_USER_MODIFY");
@@ -640,8 +704,43 @@
 	    FlowEntry flowEntry = new FlowEntry();
 	    flowEntry.setFlowEntryId(new FlowEntryId(flowEntryObj.getFlowEntryId()));
 	    flowEntry.setDpid(new Dpid(flowEntryObj.getSwitchDpid()));
-	    flowEntry.setInPort(new Port(flowEntryObj.getInPort()));
-	    flowEntry.setOutPort(new Port(flowEntryObj.getOutPort()));
+
+	    //
+	    // Extract the match conditions
+	    //
+	    FlowEntryMatch match = new FlowEntryMatch();
+	    Short matchInPort = flowEntryObj.getMatchInPort();
+	    if (matchInPort != null)
+		match.enableInPort(new Port(matchInPort));
+	    Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+	    if (matchEthernetFrameType != null)
+		match.enableEthernetFrameType(matchEthernetFrameType);
+	    String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+	    if (matchSrcIPv4Net != null)
+		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+	    String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+	    if (matchDstIPv4Net != null)
+		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+	    String matchSrcMac = flowEntryObj.getMatchSrcMac();
+	    if (matchSrcMac != null)
+		match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
+	    String matchDstMac = flowEntryObj.getMatchDstMac();
+	    if (matchDstMac != null)
+		match.enableDstMac(MACAddress.valueOf(matchDstMac));
+	    flowEntry.setFlowEntryMatch(match);
+
+	    //
+	    // Extract the actions
+	    //
+	    ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
+	    Short actionOutputPort = flowEntryObj.getActionOutput();
+	    if (actionOutputPort != null) {
+		FlowEntryAction action = new FlowEntryAction();
+		action.setActionOutput(new Port(actionOutputPort));
+		actions.add(action);
+	    }
+	    flowEntry.setFlowEntryActions(actions);
+
 	    String userState = flowEntryObj.getUserState();
 	    flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
 	    String switchState = flowEntryObj.getSwitchState();
diff --git a/src/main/java/org/openflow/protocol/OFMatch.java b/src/main/java/org/openflow/protocol/OFMatch.java
index 0336d7d..397263d 100644
--- a/src/main/java/org/openflow/protocol/OFMatch.java
+++ b/src/main/java/org/openflow/protocol/OFMatch.java
@@ -911,7 +911,7 @@
      *            one of STR_NW_DST or STR_NW_SRC
      * @throws IllegalArgumentException
      */
-    private void setFromCIDR(String cidr, String which)
+    public void setFromCIDR(String cidr, String which)
             throws IllegalArgumentException {
         String values[] = cidr.split("/");
         String[] ip_str = values[0].split("\\.");
diff --git a/web/add_flow.py b/web/add_flow.py
index 30de975..d8788ee 100755
--- a/web/add_flow.py
+++ b/web/add_flow.py
@@ -92,11 +92,11 @@
   usage_msg = usage_msg + "        matchDstMac <destination MAC address>\n"
   usage_msg = usage_msg + "        matchSrcIPv4Net <source IPv4 network address>\n"
   usage_msg = usage_msg + "        matchDstIPv4Net <destination IPv4 network address>\n"
+  usage_msg = usage_msg + "        matchEthernetFrameType <Ethernet frame type>\n"
 
   usage_msg = usage_msg + "    Match Conditions (not implemented yet):\n"
   usage_msg = usage_msg + "        matchVlanId <VLAN ID>\n"
   usage_msg = usage_msg + "        matchVlanPriority <VLAN priority>\n"
-  usage_msg = usage_msg + "        matchEthernetFrametype <Ethernet frame type>\n"
   usage_msg = usage_msg + "        matchIpToS <IP ToS (DSCP field, 6 bits)>\n"
   usage_msg = usage_msg + "        matchIpProto <IP protocol>\n"
   usage_msg = usage_msg + "        matchSrcTcpUdpPort <source TCP/UDP port>\n"
diff --git a/web/get_flow.py b/web/get_flow.py
index 99e4f3a..eaf50d3 100755
--- a/web/get_flow.py
+++ b/web/get_flow.py
@@ -44,14 +44,12 @@
   print "FlowPath: (flowId = %s installerId = %s src = %s/%s dst = %s/%s)" % (flowId, installerId, srcSwitch, srcPort, dstSwitch, dstPort)
 
   for f in parsedResult['dataPath']['flowEntries']:
-    inPort = f['inPort']['value']
-    outPort = f['outPort']['value']
     dpid = f['dpid']['value']
     userState = f['flowEntryUserState']
     switchState = f['flowEntrySwitchState']
     match = f['flowEntryMatch'];
     actions = f['flowEntryActions']
-    print "  FlowEntry: (%s, %s, %s, %s, %s)" % (inPort, dpid, outPort, userState, switchState)
+    print "  FlowEntry: (%s, %s, %s)" % (dpid, userState, switchState)
 
     #
     # Print the match conditions