Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/RoleManager.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/RoleManager.java
index b47bada..992270f 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/RoleManager.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/RoleManager.java
@@ -122,7 +122,7 @@
                 //FIXME fix below when we actually use generation ids
                 .setGenerationId(U64.ZERO)
                 .build();
-        sw.sendMsg(rrm);
+        sw.write(rrm);
         return xid;
     }
 
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/OFSwitchImplOVS13.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/OFSwitchImplOVS13.java
index 05ffdd1..6bb4586 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/OFSwitchImplOVS13.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/OFSwitchImplOVS13.java
@@ -138,7 +138,7 @@
                 .buildBarrierRequest()
                 .setXid(xid)
                 .build();
-        sendMsg(br);
+        write(br);
     }
 
     @Override
@@ -227,7 +227,7 @@
                 .setHardTimeout(0)
                 .setXid(getNextTransactionId())
                 .build();
-        sendMsg(tableMissEntry);
+        write(tableMissEntry);
     }
 
 }
diff --git a/openflow/openflowj/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFType.java b/openflow/openflowj/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFType.java
index aef779f..51de582 100644
--- a/openflow/openflowj/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFType.java
+++ b/openflow/openflowj/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFType.java
@@ -40,15 +40,15 @@
      PORT_STATUS,
      PACKET_OUT,
      FLOW_MOD,
+     GROUP_MOD,
      PORT_MOD,
+     TABLE_MOD,
      STATS_REQUEST,
      STATS_REPLY,
      BARRIER_REQUEST,
      BARRIER_REPLY,
      QUEUE_GET_CONFIG_REQUEST,
      QUEUE_GET_CONFIG_REPLY,
-     GROUP_MOD,
-     TABLE_MOD,
      ROLE_REQUEST,
      ROLE_REPLY,
      GET_ASYNC_REQUEST,
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
index 82fcede..876bc27 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
@@ -20,6 +20,7 @@
 import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
 import org.projectfloodlight.openflow.protocol.OFFlowRemovedReason;
 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFInstructionType;
 import org.projectfloodlight.openflow.protocol.action.OFAction;
 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
@@ -28,11 +29,15 @@
 import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
 import org.projectfloodlight.openflow.protocol.match.Match;
 import org.projectfloodlight.openflow.protocol.match.MatchField;
 import org.projectfloodlight.openflow.types.IPv4Address;
 import org.slf4j.Logger;
 
+import com.google.common.collect.Lists;
+
 public class FlowRuleBuilder {
     private final Logger log = getLogger(getClass());
 
@@ -44,15 +49,16 @@
 
     private final Dpid dpid;
 
-
+    private final boolean addedRule;
 
 
     public FlowRuleBuilder(Dpid dpid, OFFlowStatsEntry entry) {
         this.stat = entry;
         this.match = entry.getMatch();
-        this.actions = entry.getActions();
+        this.actions = getActions(entry);
         this.dpid = dpid;
         this.removed = null;
+        this.addedRule = true;
     }
 
     public FlowRuleBuilder(Dpid dpid, OFFlowRemoved removed) {
@@ -62,11 +68,12 @@
         this.dpid = dpid;
         this.actions = null;
         this.stat = null;
+        this.addedRule = false;
 
     }
 
     public FlowRule build() {
-        if (stat != null) {
+        if (addedRule) {
             return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
                     buildSelector(), buildTreatment(), stat.getPriority(),
                     FlowRuleState.ADDED, stat.getDurationNsec() / 1000000,
@@ -84,6 +91,26 @@
         }
     }
 
+    private List<OFAction> getActions(OFFlowStatsEntry entry) {
+        switch (entry.getVersion()) {
+            case OF_10:
+                return entry.getActions();
+            case OF_11:
+            case OF_12:
+            case OF_13:
+                List<OFInstruction> ins = entry.getInstructions();
+                for (OFInstruction in : ins) {
+                    if (in.getType().equals(OFInstructionType.APPLY_ACTIONS)) {
+                        OFInstructionApplyActions apply = (OFInstructionApplyActions) in;
+                        return apply.getActions();
+                    }
+                }
+                return Lists.newLinkedList();
+            default:
+                log.warn("Unknown OF version {}", entry.getVersion());
+        }
+        return Lists.newLinkedList();
+    }
 
     private TrafficTreatment buildTreatment() {
         TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
index 24a7ea8..c4507b4 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -2,6 +2,7 @@
 
 import static org.slf4j.LoggerFactory.getLogger;
 
+import java.util.List;
 import java.util.Map;
 
 import org.apache.felix.scr.annotations.Activate;
@@ -24,14 +25,22 @@
 import org.onlab.onos.openflow.controller.OpenFlowSwitch;
 import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
 import org.onlab.onos.openflow.controller.RoleState;
+import org.projectfloodlight.openflow.protocol.OFActionType;
 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.OFStatsReplyFlags;
 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.instruction.OFInstruction;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
+import org.projectfloodlight.openflow.types.OFPort;
 import org.slf4j.Logger;
 
 import com.google.common.collect.ArrayListMultimap;
@@ -178,8 +187,9 @@
             //final List<FlowRule> entries = Lists.newLinkedList();
 
             for (OFFlowStatsEntry reply : replies.getEntries()) {
-                completeEntries.put(did, new FlowRuleBuilder(dpid, reply).build());
-                //entries.add(new FlowRuleBuilder(dpid, reply).build());
+                if (!tableMissRule(dpid, reply)) {
+                    completeEntries.put(did, new FlowRuleBuilder(dpid, reply).build());
+                }
             }
 
             if (!stats.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
@@ -189,6 +199,29 @@
             }
         }
 
+        private boolean tableMissRule(Dpid dpid, OFFlowStatsEntry reply) {
+            // TODO NEED TO FIND A BETTER WAY TO AVOID DOING THIS
+            if (reply.getVersion().equals(OFVersion.OF_10) ||
+                    reply.getMatch().getMatchFields().iterator().hasNext()) {
+                return false;
+            }
+            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;
+        }
+
     }