Expose cookie information in packet context

Change-Id: I7f2cb331a19aeca1a578aade6488a6480d15496c
diff --git a/core/api/src/main/java/org/onosproject/net/packet/DefaultInboundPacket.java b/core/api/src/main/java/org/onosproject/net/packet/DefaultInboundPacket.java
index 96f872f..3f5f138 100644
--- a/core/api/src/main/java/org/onosproject/net/packet/DefaultInboundPacket.java
+++ b/core/api/src/main/java/org/onosproject/net/packet/DefaultInboundPacket.java
@@ -20,6 +20,7 @@
 
 import java.nio.ByteBuffer;
 import java.util.Objects;
+import java.util.Optional;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
 
@@ -31,6 +32,7 @@
     private final ConnectPoint receivedFrom;
     private final Ethernet parsed;
     private final ByteBuffer unparsed;
+    private final Optional<Long> cookie;
 
     /**
      * Creates an immutable inbound packet.
@@ -39,11 +41,25 @@
      * @param parsed       parsed ethernet frame
      * @param unparsed     unparsed raw bytes
      */
-    public  DefaultInboundPacket(ConnectPoint receivedFrom, Ethernet parsed,
+    public DefaultInboundPacket(ConnectPoint receivedFrom, Ethernet parsed,
                                 ByteBuffer unparsed) {
+        this(receivedFrom, parsed, unparsed, Optional.empty());
+    }
+
+    /**
+     * Creates an immutable inbound packet with cookie.
+     *
+     * @param receivedFrom connection point where received
+     * @param parsed       parsed ethernet frame
+     * @param unparsed     unparsed raw bytes
+     * @param cookie       cookie
+     */
+    public DefaultInboundPacket(ConnectPoint receivedFrom, Ethernet parsed,
+            ByteBuffer unparsed, Optional<Long> cookie) {
         this.receivedFrom = receivedFrom;
         this.parsed = parsed;
         this.unparsed = unparsed;
+        this.cookie = cookie;
     }
 
     @Override
@@ -63,6 +79,11 @@
     }
 
     @Override
+    public Optional<Long> cookie() {
+        return cookie;
+    }
+
+    @Override
     public int hashCode() {
         return Objects.hash(receivedFrom, parsed, unparsed);
     }
diff --git a/core/api/src/main/java/org/onosproject/net/packet/InboundPacket.java b/core/api/src/main/java/org/onosproject/net/packet/InboundPacket.java
index 3fd5814..48fdb20 100644
--- a/core/api/src/main/java/org/onosproject/net/packet/InboundPacket.java
+++ b/core/api/src/main/java/org/onosproject/net/packet/InboundPacket.java
@@ -19,6 +19,7 @@
 import org.onlab.packet.Ethernet;
 
 import java.nio.ByteBuffer;
+import java.util.Optional;
 
 /**
  * Represents a data packet intercepted from an infrastructure device.
@@ -47,4 +48,10 @@
      */
     ByteBuffer unparsed();
 
+    /**
+     * Returns the cookie in the packet in message.
+     *
+     * @return optional flow cookie
+     */
+    Optional<Long> cookie();
 }
diff --git a/core/api/src/test/java/org/onosproject/net/packet/DefaultInboundPacketTest.java b/core/api/src/test/java/org/onosproject/net/packet/DefaultInboundPacketTest.java
index eda6824..b051ad4 100644
--- a/core/api/src/test/java/org/onosproject/net/packet/DefaultInboundPacketTest.java
+++ b/core/api/src/test/java/org/onosproject/net/packet/DefaultInboundPacketTest.java
@@ -16,6 +16,7 @@
 package org.onosproject.net.packet;
 
 import java.nio.ByteBuffer;
+import java.util.Optional;
 
 import org.junit.Test;
 import org.onlab.packet.Ethernet;
@@ -41,15 +42,22 @@
     final DefaultInboundPacket packet1 =
             new DefaultInboundPacket(connectPoint("d1", 1),
                     eth,
-                    byteBuffer);
+                    byteBuffer,
+                    Optional.of(1L));
     final DefaultInboundPacket sameAsPacket1 =
             new DefaultInboundPacket(connectPoint("d1", 1),
                     eth,
-                    byteBuffer);
+                    byteBuffer,
+                    Optional.of(1L));
     final DefaultInboundPacket packet2 =
             new DefaultInboundPacket(connectPoint("d2", 1),
                     eth,
                     byteBuffer);
+    final DefaultInboundPacket sameAsPacket2 =
+            new DefaultInboundPacket(connectPoint("d2", 1),
+                    eth,
+                    byteBuffer,
+                    Optional.empty());
     /**
      * Checks that the DefaultInboundPacket class is immutable.
      */
@@ -65,7 +73,7 @@
     public void testEquals() {
         new EqualsTester()
                 .addEqualityGroup(packet1, sameAsPacket1)
-                .addEqualityGroup(packet2)
+                .addEqualityGroup(packet2, sameAsPacket2)
                 .testEquals();
     }
 
@@ -77,5 +85,6 @@
         assertThat(packet1.receivedFrom(), equalTo(connectPoint("d1", 1)));
         assertThat(packet1.parsed(), equalTo(eth));
         assertThat(packet1.unparsed(), notNullValue());
+        assertThat(packet1.cookie(), equalTo(Optional.of(1L)));
     }
 }
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 af92a1d..52e23b3 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
@@ -30,6 +30,7 @@
 
 import java.nio.BufferUnderflowException;
 import java.util.Collections;
+import java.util.Optional;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static org.onosproject.security.AppGuard.checkPermission;
@@ -179,4 +180,14 @@
         return isBuffered;
     }
 
+    @Override
+    public Optional<Long> cookie() {
+        checkPermission(PACKET_READ);
+        if (pktin.getVersion() != OFVersion.OF_10) {
+            return Optional.of(pktin.getCookie().getValue());
+        } else {
+            return Optional.empty();
+        }
+    }
+
 }
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java
index 740d89d..bb10866 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java
@@ -18,6 +18,8 @@
 import org.onlab.packet.Ethernet;
 import org.projectfloodlight.openflow.types.OFPort;
 
+import java.util.Optional;
+
 /**
  * A representation of a packet context which allows any provider
  * to view a packet in event, but may block the response to the
@@ -29,12 +31,14 @@
     /**
      * Blocks further responses (ie. send() calls) on this
      * packet in event.
+     *
      * @return true if blocks
      */
     boolean block();
 
     /**
      * Checks whether the packet has been handled.
+     *
      * @return true if handled, false otherwise.
      */
     boolean isHandled();
@@ -47,12 +51,14 @@
 
     /**
      * Build the packet out in response to this packet in event.
+     *
      * @param outPort the out port to send to packet out of.
      */
     void build(OFPort outPort);
 
     /**
      * Build the packet out in response to this packet in event.
+     *
      * @param ethFrame the actual packet to send out.
      * @param outPort the out port to send to packet out of.
      */
@@ -60,31 +66,43 @@
 
     /**
      * Provided a handle onto the parsed payload.
+     *
      * @return the parsed form of the payload.
      */
     Ethernet parsed();
 
     /**
      * Provide an unparsed copy of the data.
+     *
      * @return the unparsed form of the payload.
      */
     byte[] unparsed();
 
     /**
      * Provide the dpid of the switch where the packet in arrived.
+     *
      * @return the dpid of the switch.
      */
     Dpid dpid();
 
     /**
      * Provide the port on which the packet arrived.
+     *
      * @return the port
      */
     Integer inPort();
 
     /**
      * Indicates that this packet is buffered at the switch.
+     *
      * @return buffer indication
      */
     boolean isBuffered();
+
+    /**
+     * Provide the cookie in the packet in message.
+     *
+     * @return optional flow cookie
+     */
+    Optional<Long> cookie();
 }
diff --git a/providers/openflow/packet/src/main/java/org/onosproject/provider/of/packet/impl/OpenFlowPacketProvider.java b/providers/openflow/packet/src/main/java/org/onosproject/provider/of/packet/impl/OpenFlowPacketProvider.java
index dc79fef..31770e1 100644
--- a/providers/openflow/packet/src/main/java/org/onosproject/provider/of/packet/impl/OpenFlowPacketProvider.java
+++ b/providers/openflow/packet/src/main/java/org/onosproject/provider/of/packet/impl/OpenFlowPacketProvider.java
@@ -156,7 +156,8 @@
 
             DefaultInboundPacket inPkt = new DefaultInboundPacket(
                     new ConnectPoint(id, PortNumber.portNumber(pktCtx.inPort())),
-                    pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()));
+                    pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()),
+                    pktCtx.cookie());
 
             DefaultOutboundPacket outPkt = null;
             if (!pktCtx.isBuffered()) {