ONOS-7077 Openflow 1.5 OXS and stat trigger support

Change-Id: I006bcd3d8eac451a780c7e5c69a12298ead14281
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java
index bf0af04..9bd2146 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java
@@ -70,14 +70,24 @@
         if (isBuilt.getAndSet(true)) {
             return;
         }
-        OFPacketOut.Builder builder = sw.factory().buildPacketOut();
         OFAction act = buildOutput(outPort.getPortNumber());
-        pktout = builder.setXid(pktin.getXid())
-                .setInPort(pktinInPort())
-                .setBufferId(OFBufferId.NO_BUFFER)
-                .setData(pktin.getData())
+        pktout = createOFPacketOut(pktin.getData(), act, pktin.getXid());
+    }
+
+    private OFPacketOut createOFPacketOut(byte[] data, OFAction act, long xid) {
+        OFPacketOut.Builder builder = sw.factory().buildPacketOut();
+        if (sw.factory().getVersion().getWireVersion() <= OFVersion.OF_14.getWireVersion()) {
+            return builder.setXid(xid)
+                    .setInPort(pktinInPort())
+                    .setBufferId(OFBufferId.NO_BUFFER)
+                    .setData(data)
 //                .setBufferId(pktin.getBufferId())
+                    .setActions(Collections.singletonList(act)).build();
+        }
+        return builder.setXid(xid)
+                .setBufferId(OFBufferId.NO_BUFFER)
                 .setActions(Collections.singletonList(act))
+                .setData(data)
                 .build();
     }
 
@@ -86,14 +96,8 @@
         if (isBuilt.getAndSet(true)) {
             return;
         }
-        OFPacketOut.Builder builder = sw.factory().buildPacketOut();
         OFAction act = buildOutput(outPort.getPortNumber());
-        pktout = builder.setXid(pktin.getXid())
-                .setBufferId(OFBufferId.NO_BUFFER)
-                .setInPort(pktinInPort())
-                .setActions(Collections.singletonList(act))
-                .setData(ethFrame.serialize())
-                .build();
+        pktout = createOFPacketOut(ethFrame.serialize(), act, pktin.getXid());
     }
 
     @Override
diff --git a/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java b/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
index b50bdbc..05b68a4 100644
--- a/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
+++ b/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
@@ -49,6 +49,8 @@
 import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
 import org.projectfloodlight.openflow.protocol.OFExperimenter;
 import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFlowLightweightStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFFlowLightweightStatsReply;
 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
 import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
 import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
@@ -60,6 +62,8 @@
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
 import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
 import org.projectfloodlight.openflow.protocol.OFPortStatus;
+import org.projectfloodlight.openflow.protocol.OFQueueStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFQueueStatsReply;
 import org.projectfloodlight.openflow.protocol.OFStatsReply;
 import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
 import org.projectfloodlight.openflow.protocol.OFTableStatsEntry;
@@ -88,8 +92,6 @@
 import static org.onosproject.net.Device.Type.CONTROLLER;
 import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
 import static org.onosproject.openflow.controller.Dpid.dpid;
-import org.projectfloodlight.openflow.protocol.OFQueueStatsEntry;
-import org.projectfloodlight.openflow.protocol.OFQueueStatsReply;
 
 
 @Component(immediate = true)
@@ -161,6 +163,9 @@
     protected Multimap<Dpid, OFFlowStatsEntry> fullFlowStats =
             ArrayListMultimap.create();
 
+    protected Multimap<Dpid, OFFlowLightweightStatsEntry> fullFlowLightweightStats =
+            ArrayListMultimap.create();
+
     protected Multimap<Dpid, OFTableStatsEntry> fullTableStats =
             ArrayListMultimap.create();
 
@@ -422,7 +427,17 @@
                     executorMsgs.execute(new OFMessageHandler(dpid, rep.build()));
                 }
                 break;
-
+            case FLOW_LIGHTWEIGHT:
+                Collection<OFFlowLightweightStatsEntry> flowLightweightStats =
+                        publishFlowStatsLightweight(dpid, (OFFlowLightweightStatsReply) reply);
+                if (flowLightweightStats != null) {
+                    OFFlowLightweightStatsReply.Builder rep =
+                            OFFactories.getFactory(reply.getVersion()).buildFlowLightweightStatsReply();
+                    rep.setEntries(ImmutableList.copyOf(flowLightweightStats));
+                    rep.setXid(reply.getXid());
+                    executorMsgs.execute(new OFMessageHandler(dpid, rep.build()));
+                }
+                break;
             case TABLE:
                 Collection<OFTableStatsEntry> tableStats = publishTableStats(dpid, (OFTableStatsReply) reply);
                 if (tableStats != null) {
@@ -529,6 +544,17 @@
         return null;
     }
 
+    private synchronized Collection<OFFlowLightweightStatsEntry> publishFlowStatsLightweight(
+            Dpid dpid,
+            OFFlowLightweightStatsReply reply) {
+        //TODO: Get rid of synchronized
+        fullFlowLightweightStats.putAll(dpid, reply.getEntries());
+        if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
+            return fullFlowLightweightStats.removeAll(dpid);
+        }
+        return null;
+    }
+
     private synchronized Collection<OFTableStatsEntry> publishTableStats(Dpid dpid,
                                                                        OFTableStatsReply reply) {
         //TODO: Get rid of synchronized