A set of fixes to ensure that the FlowRuleManager can correctly account for flows
from the dataplane in a multi-table pipeline scenario
Change-Id: I9ca3ef9a77781f126a13538647c824b27f77101c
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
index 0b9b0cd..f0e4f84 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -34,6 +34,7 @@
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowEntry.FlowEntryState;
import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRule.Type;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.openflow.controller.Dpid;
@@ -87,6 +88,7 @@
public enum FlowType { STAT, REMOVED, MOD }
private final FlowType type;
+ private Type tableType = FlowRule.Type.DEFAULT;
public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
@@ -99,6 +101,17 @@
this.type = FlowType.STAT;
}
+ public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry, Type tableType) {
+ this.stat = entry;
+ this.match = entry.getMatch();
+ this.actions = getActions(entry);
+ this.dpid = dpid;
+ this.removed = null;
+ this.flowMod = null;
+ this.type = FlowType.STAT;
+ this.tableType = tableType;
+ }
+
public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
this.match = removed.getMatch();
this.removed = removed;
@@ -127,7 +140,8 @@
case STAT:
rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
buildSelector(), buildTreatment(), stat.getPriority(),
- stat.getCookie().getValue(), stat.getIdleTimeout(), false);
+ stat.getCookie().getValue(), stat.getIdleTimeout(), false,
+ tableType);
return new DefaultFlowEntry(rule, FlowEntryState.ADDED,
stat.getDurationSec(), stat.getPacketCount().getValue(),
stat.getByteCount().getValue());
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
index 00bb197..4c2dc93 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -266,6 +266,8 @@
return OpenFlowSwitch.TableType.ETHER;
case COS:
return OpenFlowSwitch.TableType.COS;
+ case FIRST:
+ return OpenFlowSwitch.TableType.FIRST;
default:
return OpenFlowSwitch.TableType.NONE;
}
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
index 928f7b0..bf4c73f 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -45,26 +45,17 @@
import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.onosproject.openflow.controller.OpenFlowSwitchListener;
import org.onosproject.openflow.controller.RoleState;
-import org.projectfloodlight.openflow.protocol.OFActionType;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFErrorType;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
-import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
-import org.projectfloodlight.openflow.protocol.OFInstructionType;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsType;
-import org.projectfloodlight.openflow.protocol.OFVersion;
-import org.projectfloodlight.openflow.protocol.action.OFAction;
-import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
-import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
-import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
-import org.projectfloodlight.openflow.types.OFPort;
import org.slf4j.Logger;
import java.util.Collections;
@@ -85,8 +76,6 @@
@Component(immediate = true)
public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
- private static final int LOWEST_PRIORITY = 0;
-
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -160,7 +149,7 @@
Optional.empty()).buildFlowAdd());
} else {
OpenFlowSwitch.TableType type = getTableType(flowRule.type());
- sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
+ sw.transformAndSendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
Optional.empty()).buildFlowAdd(),
type);
}
@@ -181,7 +170,7 @@
sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
Optional.empty()).buildFlowDel());
} else {
- sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
+ sw.transformAndSendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
Optional.empty()).buildFlowDel(), getTableType(flowRule.type()));
}
}
@@ -225,7 +214,7 @@
if (fbe.target().type() == FlowRule.Type.DEFAULT) {
sw.sendMsg(mod);
} else {
- sw.sendMsg(mod, getTableType(fbe.target().type()));
+ sw.transformAndSendMsg(mod, getTableType(fbe.target().type()));
}
}
OFBarrierRequest.Builder builder = sw.factory()
@@ -253,12 +242,38 @@
return OpenFlowSwitch.TableType.ETHER;
case COS:
return OpenFlowSwitch.TableType.COS;
+ case FIRST:
+ return OpenFlowSwitch.TableType.FIRST;
default:
return OpenFlowSwitch.TableType.NONE;
}
}
+ private FlowRule.Type getType(OpenFlowSwitch.TableType tableType) {
+ switch (tableType) {
+ case NONE:
+ return FlowRule.Type.DEFAULT;
+ case IP:
+ return FlowRule.Type.IP;
+ case MPLS:
+ return FlowRule.Type.MPLS;
+ case ACL:
+ return FlowRule.Type.ACL;
+ case VLAN_MPLS:
+ return FlowRule.Type.VLAN_MPLS;
+ case VLAN:
+ return FlowRule.Type.VLAN;
+ case ETHER:
+ return FlowRule.Type.ETHER;
+ case COS:
+ return FlowRule.Type.COS;
+ case FIRST:
+ return FlowRule.Type.FIRST;
+ default:
+ return FlowRule.Type.DEFAULT;
+ }
+ }
private class InternalFlowProvider
@@ -354,41 +369,18 @@
private void pushFlowMetrics(Dpid dpid, OFFlowStatsReply replies) {
DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
List<FlowEntry> flowEntries = replies.getEntries().stream()
- .filter(entry -> !tableMissRule(dpid, entry))
- .map(entry -> new FlowEntryBuilder(dpid, entry).build())
+ .map(entry -> new FlowEntryBuilder(dpid, entry,
+ getType(sw.getTableType(entry.getTableId())))
+ .build())
.collect(Collectors.toList());
providerService.pushFlowMetrics(did, flowEntries);
}
- private boolean tableMissRule(Dpid dpid, OFFlowStatsEntry reply) {
- if (reply.getMatch().getMatchFields().iterator().hasNext()) {
- return false;
- }
- if (reply.getVersion().equals(OFVersion.OF_10)) {
- return reply.getPriority() == LOWEST_PRIORITY
- && reply.getActions().isEmpty();
- }
- for (OFInstruction ins : reply.getInstructions()) {
- if (ins.getType() == OFInstructionType.APPLY_ACTIONS) {
- OFInstructionApplyActions apply = (OFInstructionApplyActions) ins;
- List<OFAction> acts = apply.getActions();
- for (OFAction act : acts) {
- if (act.getType() == OFActionType.OUTPUT) {
- OFActionOutput out = (OFActionOutput) act;
- if (out.getPort() == OFPort.CONTROLLER) {
- return true;
- }
- }
- }
- }
- }
- return false;
- }
-
}
/**