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