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/device/src/test/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProviderTest.java b/providers/openflow/device/src/test/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProviderTest.java
index e92d1be..c83da17 100644
--- a/providers/openflow/device/src/test/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProviderTest.java
+++ b/providers/openflow/device/src/test/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProviderTest.java
@@ -49,6 +49,7 @@
 import org.onosproject.openflow.controller.OpenFlowSwitchListener;
 import org.onosproject.openflow.controller.PacketListener;
 import org.onosproject.openflow.controller.RoleState;
+import org.onosproject.openflow.controller.OpenFlowSwitch.TableType;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
@@ -56,6 +57,7 @@
 import org.projectfloodlight.openflow.protocol.OFPortStatus;
 import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
 import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TableId;
 
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Lists;
@@ -310,10 +312,6 @@
         }
 
         @Override
-        public void sendMsg(OFMessage msg, TableType tableType) {
-        }
-
-        @Override
         public void handleMessage(OFMessage fromSwitch) {
         }
 
@@ -395,6 +393,17 @@
             return "1.2.3.4:1";
         }
 
+        @Override
+        public TableType getTableType(TableId tid) {
+            return TableType.NONE;
+        }
+
+        @Override
+        public void transformAndSendMsg(OFMessage msg, TableType tableType) {
+            // TODO Auto-generated method stub
+        }
+
+
     }
 
 }
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;
-        }
-
     }
 
     /**
diff --git a/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java b/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
index 402e0ac..2cd2e55 100644
--- a/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
+++ b/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
@@ -1,6 +1,7 @@
 package org.onosproject.provider.of.group.impl;
 
 import com.google.common.collect.Lists;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -41,6 +42,7 @@
 import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.protocol.errormsg.OFGroupModFailedErrorMsg;
 import org.projectfloodlight.openflow.types.OFGroup;
+import org.projectfloodlight.openflow.types.TableId;
 
 import java.util.Collection;
 import java.util.List;
@@ -310,11 +312,6 @@
         }
 
         @Override
-        public void sendMsg(OFMessage msg, TableType tableType) {
-
-        }
-
-        @Override
         public void handleMessage(OFMessage fromSwitch) {
 
         }
@@ -398,5 +395,15 @@
         public String channelId() {
             return null;
         }
+
+        @Override
+        public TableType getTableType(TableId tid) {
+            return TableType.NONE;
+        }
+
+        @Override
+        public void transformAndSendMsg(OFMessage msg, TableType tableType) {
+            // TODO Auto-generated method stub
+        }
     }
 }
\ No newline at end of file
diff --git a/providers/openflow/link/src/test/java/org/onosproject/provider/of/link/impl/OpenFlowLinkProviderTest.java b/providers/openflow/link/src/test/java/org/onosproject/provider/of/link/impl/OpenFlowLinkProviderTest.java
index 311a728..27138e1 100644
--- a/providers/openflow/link/src/test/java/org/onosproject/provider/of/link/impl/OpenFlowLinkProviderTest.java
+++ b/providers/openflow/link/src/test/java/org/onosproject/provider/of/link/impl/OpenFlowLinkProviderTest.java
@@ -46,6 +46,7 @@
 import org.onosproject.openflow.controller.OpenflowControllerAdapter;
 import org.onosproject.openflow.controller.PacketListener;
 import org.onosproject.openflow.controller.RoleState;
+import org.onosproject.openflow.controller.OpenFlowSwitch.TableType;
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.ONLabLddp;
 import org.projectfloodlight.openflow.protocol.OFFactory;
@@ -56,6 +57,7 @@
 import org.projectfloodlight.openflow.protocol.OFPortStatus;
 import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
 import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TableId;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -414,10 +416,6 @@
         }
 
         @Override
-        public void sendMsg(OFMessage msg, TableType tableType) {
-        }
-
-        @Override
         public void handleMessage(OFMessage fromSwitch) {
         }
 
@@ -499,6 +497,15 @@
             return "1.2.3.4:1";
         }
 
+        @Override
+        public TableType getTableType(TableId tid) {
+            return TableType.NONE;
+        }
+
+        @Override
+        public void transformAndSendMsg(OFMessage msg, TableType tableType) {
+            // TODO Auto-generated method stub
+        }
 
     }
 }
diff --git a/providers/openflow/packet/src/test/java/org/onosproject/provider/of/packet/impl/OpenFlowPacketProviderTest.java b/providers/openflow/packet/src/test/java/org/onosproject/provider/of/packet/impl/OpenFlowPacketProviderTest.java
index 9f03527..02e604d 100644
--- a/providers/openflow/packet/src/test/java/org/onosproject/provider/of/packet/impl/OpenFlowPacketProviderTest.java
+++ b/providers/openflow/packet/src/test/java/org/onosproject/provider/of/packet/impl/OpenFlowPacketProviderTest.java
@@ -49,6 +49,7 @@
 import org.onosproject.openflow.controller.OpenFlowSwitchListener;
 import org.onosproject.openflow.controller.PacketListener;
 import org.onosproject.openflow.controller.RoleState;
+import org.onosproject.openflow.controller.OpenFlowSwitch.TableType;
 import org.onlab.packet.ARP;
 import org.onlab.packet.Ethernet;
 import org.projectfloodlight.openflow.protocol.OFFactory;
@@ -60,6 +61,7 @@
 import org.projectfloodlight.openflow.types.MacAddress;
 import org.projectfloodlight.openflow.types.OFBufferId;
 import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TableId;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -347,10 +349,6 @@
         }
 
         @Override
-        public void sendMsg(OFMessage msg, TableType tableType) {
-        }
-
-        @Override
         public void handleMessage(OFMessage fromSwitch) {
         }
 
@@ -432,6 +430,17 @@
             return "1.2.3.4:1";
         }
 
+        @Override
+        public TableType getTableType(TableId tid) {
+            return TableType.NONE;
+        }
+
+        @Override
+        public void transformAndSendMsg(OFMessage msg, TableType tableType) {
+            // TODO Auto-generated method stub
+
+        }
+
     }
 
 }