[ONOS-7602]Implement support for P4Data in PI framework and P4Runtime southbound

Change-Id: I9c0c76fb29b8c3aa36f39bde62e825f0f0094253
diff --git a/core/api/src/main/java/org/onosproject/net/pi/model/PiData.java b/core/api/src/main/java/org/onosproject/net/pi/model/PiData.java
new file mode 100644
index 0000000..97d5290
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/model/PiData.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.model;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Representation of data that can be used for runtime operations of a protocol-independent pipeline.
+ */
+@Beta
+public interface PiData {
+    /**
+     * Types of data in a protocol-independent pipeline.
+     */
+    enum Type {
+        /**
+         * Bit String.
+         */
+        BITSTRING,
+
+        /**
+         * Bool.
+         */
+        BOOL,
+
+        /**
+         * Tuple.
+         */
+        TUPLE,
+
+        /**
+         * Struct.
+         */
+        STRUCT,
+
+        /**
+         * Header.
+         */
+        HEADER,
+
+        /**
+         * Header Stack.
+         */
+        HEADERSTACK,
+
+        /**
+         * Header Union.
+         */
+        HEADERUNION,
+
+        /**
+         * Header Union Stack.
+         */
+        HEADERUNIONSTACK,
+
+        /**
+         * Enum String.
+         */
+        ENUMSTRING,
+
+        /**
+         * Error String.
+         */
+        ERRORSTRING
+    }
+
+    /**
+     * Returns the type of this protocol-independent data.
+     * @return the type of this instance
+     */
+    Type type();
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiBitString.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiBitString.java
new file mode 100644
index 0000000..544f5df
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiBitString.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.net.pi.model.PiData;
+
+/**
+ * BitString entity in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiBitString implements PiData {
+    private final ImmutableByteSequence bitString;
+
+    /**
+     * Creates a new protocol-independent bit string instance.
+     *
+     * @param bitString bitString
+     */
+    private PiBitString(ImmutableByteSequence bitString) {
+        this.bitString = bitString;
+    }
+
+    /**
+     * Returns a new protocol-independent BitString.
+     * @param bitString bitString
+     * @return BitString
+     */
+    public static PiBitString of(ImmutableByteSequence bitString) {
+        return new PiBitString(bitString);
+    }
+
+    /**
+     * Return protocol-independent bitString instance.
+     *
+     * @return bitString
+     */
+    public ImmutableByteSequence bitString() {
+        return this.bitString;
+    }
+
+    @Override
+    public Type type() {
+        return Type.BITSTRING;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiBitString bitStr = (PiBitString) o;
+        return Objects.equal(bitString, bitStr.bitString);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(bitString);
+    }
+
+    @Override
+    public String toString() {
+        return bitString.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiBool.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiBool.java
new file mode 100644
index 0000000..e100f03
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiBool.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.onosproject.net.pi.model.PiData;
+
+/**
+ * Boolean entity in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiBool implements PiData {
+    private final Boolean bool;
+
+    /**
+     * Creates a new protocol-independent Bool instance.
+     *
+     * @param bool boolean
+     */
+    private PiBool(Boolean bool) {
+        this.bool = bool;
+    }
+
+    /**
+     * Returns a new protocol-independent Bool.
+     * @param bool boolean
+     * @return protocol-independent Bool
+     */
+    public static PiBool of(Boolean bool) {
+        return new PiBool(bool);
+    }
+
+    /**
+     * Return protocol-independent Boolean instance.
+     *
+     * @return bool
+     */
+    public Boolean bool() {
+        return this.bool;
+    }
+
+    @Override
+    public Type type() {
+        return Type.BOOL;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiBool boolValue = (PiBool) o;
+        return Objects.equal(bool, boolValue.bool);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(bool);
+    }
+
+    @Override
+    public String toString() {
+        return bool.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiEnumString.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiEnumString.java
new file mode 100644
index 0000000..74481ea
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiEnumString.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.onosproject.net.pi.model.PiData;
+
+/**
+ * EnumString entity in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiEnumString implements PiData {
+    private final String enumString;
+
+    /**
+     * Creates a new protocol-independent enum string instance.
+     *
+     * @param enumString enum string
+     */
+    private PiEnumString(String enumString) {
+        this.enumString = enumString;
+    }
+
+    /**
+     * Returns a new protocol-independent enum string.
+     * @param enumString enum string
+     * @return enum string
+     */
+    public static PiEnumString of(String enumString) {
+        return new PiEnumString(enumString);
+    }
+
+    /**
+     * Return protocol-independent enum string instance.
+     *
+     * @return enum string
+     */
+    public String enumString() {
+        return this.enumString;
+    }
+
+    @Override
+    public Type type() {
+        return Type.ENUMSTRING;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiEnumString enumStr = (PiEnumString) o;
+        return Objects.equal(enumString, enumStr.enumString);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(enumString);
+    }
+
+    @Override
+    public String toString() {
+        return enumString;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiErrorString.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiErrorString.java
new file mode 100644
index 0000000..ff4e172
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiErrorString.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.onosproject.net.pi.model.PiData;
+
+/**
+ * ErrorString entity in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiErrorString implements PiData {
+    private final String errorString;
+
+    /**
+     * Creates a new protocol-independent error string instance.
+     *
+     * @param errorString error string
+     */
+    private PiErrorString(String errorString) {
+        this.errorString = errorString;
+    }
+
+    /**
+     * Returns a new protocol-independent error string.
+     * @param errorString error string
+     * @return error string
+     */
+    public static PiErrorString of(String errorString) {
+        return new PiErrorString(errorString);
+    }
+
+    /**
+     * Return protocol-independent error string instance.
+     *
+     * @return error string
+     */
+    public String errorString() {
+        return this.errorString;
+    }
+
+    @Override
+    public Type type() {
+        return Type.ERRORSTRING;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiErrorString errorStr = (PiErrorString) o;
+        return Objects.equal(errorString, errorStr.errorString);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(errorString);
+    }
+
+    @Override
+    public String toString() {
+        return errorString;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeader.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeader.java
new file mode 100644
index 0000000..bbc0f8e
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeader.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.net.pi.model.PiData;
+
+import java.util.List;
+import java.util.StringJoiner;
+
+/**
+ * Instance of a PiHeader in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiHeader implements PiData {
+    private final Boolean isValid;
+    private final ImmutableList<ImmutableByteSequence> bitStrings;
+
+    /**
+     * Creates a new protocol-independent header instance.
+     *
+     * @param isValid whether the header is valid
+     * @param bitStrings bitstrings
+     */
+    private PiHeader(Boolean isValid, List<ImmutableByteSequence> bitStrings) {
+        this.isValid = isValid;
+        this.bitStrings = ImmutableList.copyOf(bitStrings);
+    }
+
+    /**
+     * Returns a new protocol-independent header.
+     * @param isValid whether the header is valid
+     * @param bitStrings bitstrings
+     * @return header
+     */
+    public static PiHeader of(Boolean isValid, List<ImmutableByteSequence> bitStrings) {
+        return new PiHeader(isValid, bitStrings);
+    }
+
+    /**
+     * Return whether the header is valid.
+     *
+     * @return bool
+     */
+    public Boolean isValid() {
+        return this.isValid;
+    }
+
+    /**
+     * Return the header bit strings.
+     *
+     * @return the list of bit string
+     */
+    public List<ImmutableByteSequence> bitStrings() {
+        return this.bitStrings;
+    }
+
+    @Override
+    public Type type() {
+        return Type.HEADER;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiHeader header = (PiHeader) o;
+        return Objects.equal(isValid, header.isValid) &&
+                Objects.equal(bitStrings, header.bitStrings);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(isValid, bitStrings);
+    }
+
+    @Override
+    public String toString() {
+        StringJoiner stringParams = new StringJoiner(", ", "(", ")");
+        this.bitStrings().forEach(p -> stringParams.add(p.toString()));
+        return MoreObjects.toStringHelper(getClass())
+                .add("bitString", stringParams)
+                .add("isValid", isValid)
+                .toString();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderStack.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderStack.java
new file mode 100644
index 0000000..ccf8af8
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderStack.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.pi.model.PiData;
+
+import java.util.List;
+import java.util.StringJoiner;
+
+/**
+ * Instance of a PiHeaderStack in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiHeaderStack implements PiData {
+    private final ImmutableList<PiHeader> headers;
+
+    /**
+     * Creates a new protocol-independent header stack instance for the given collection of Header.
+     *
+     * @param headers the collection of header
+     */
+    private PiHeaderStack(List<PiHeader> headers) {
+        this.headers = ImmutableList.copyOf(headers);
+    }
+
+    /**
+     * Returns a new protocol-independent header stack.
+     * @param headers the list of header
+     * @return header stack
+     */
+    public static PiHeaderStack of(List<PiHeader> headers) {
+        return new PiHeaderStack(headers);
+    }
+
+    /**
+     * Return the list of header.
+     *
+     * @return the list of header
+     */
+    public List<PiHeader> headers() {
+        return this.headers;
+    }
+
+    @Override
+    public Type type() {
+        return Type.HEADERSTACK;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiHeaderStack stack = (PiHeaderStack) o;
+        return Objects.equal(headers, stack.headers);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(headers);
+    }
+
+    @Override
+    public String toString() {
+        StringJoiner stringParams = new StringJoiner(", ", "(", ")");
+        this.headers().forEach(p -> stringParams.add(p.toString()));
+        return stringParams.toString();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderUnion.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderUnion.java
new file mode 100644
index 0000000..189318c
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderUnion.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.onosproject.net.pi.model.PiData;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * PiHeaderUnion entity in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiHeaderUnion implements PiData {
+    private final String validHeaderName;
+    private final PiHeader header;
+    private final boolean isValid;
+
+    /**
+     * Creates a new protocol-independent header union instance for the given header name and header.
+     *
+     * @param isValid indicates whether this header union is valid
+     * @param validHeaderName header name
+     * @param header the header
+     */
+    private PiHeaderUnion(boolean isValid, String validHeaderName, PiHeader header) {
+        this.isValid = isValid;
+        this.validHeaderName = validHeaderName;
+        this.header = header;
+    }
+
+    /**
+     * Returns a new invalid protocol-independent header union.
+     *
+     * @return header union
+     */
+    public static PiHeaderUnion ofInvalid() {
+        return new PiHeaderUnion(false, null, null);
+    }
+
+    /**
+     * Returns a new valid protocol-independent header union.
+     * @param validHeaderName header name
+     * @param header the header
+     * @return header union
+     */
+    public static PiHeaderUnion of(String validHeaderName, PiHeader header) {
+        checkNotNull(validHeaderName);
+        checkArgument(!validHeaderName.isEmpty(), "The header name must not be empty");
+        checkNotNull(header);
+        return new PiHeaderUnion(true, validHeaderName, header);
+    }
+
+    /**
+     * Returns true if this header is valid, false otherwise.
+     *
+     * @return a boolean value
+     */
+    public boolean isValid() {
+        return this.isValid;
+    }
+
+    /**
+     * Return the header name.
+     *
+     * @return header name, return null if the header union invalid
+     */
+    public String headerName() {
+        return this.validHeaderName;
+    }
+
+    /**
+     * Return the header.
+     *
+     * @return header, return null if the header union invalid
+     */
+    public PiHeader header() {
+        return this.header;
+    }
+
+    @Override
+    public Type type() {
+        return Type.HEADERUNION;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiHeaderUnion headerUnion = (PiHeaderUnion) o;
+        return Objects.equal(validHeaderName, headerUnion.validHeaderName) &&
+                Objects.equal(header, headerUnion.header);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(validHeaderName, header);
+    }
+
+    @Override
+    public String toString() {
+        return !isValid ? "INVALID" : validHeaderName + ":" + header.toString();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderUnionStack.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderUnionStack.java
new file mode 100644
index 0000000..a1e39b8
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiHeaderUnionStack.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.pi.model.PiData;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.StringJoiner;
+
+/**
+ * PiHeaderUnionStack entity in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiHeaderUnionStack implements PiData {
+    private final ImmutableList<PiHeaderUnion> headerUnions;
+
+    /**
+     * Creates a new protocol-independent header union stack instance for the given collection of HeaderUnion.
+     *
+     * @param headerUnions the collection of headerUnion
+     */
+    private PiHeaderUnionStack(List<PiHeaderUnion> headerUnions) {
+        this.headerUnions = ImmutableList.copyOf(headerUnions);
+    }
+
+    /**
+     * Returns a new protocol-independent header union stack.
+     * @param headerUnions the list of headerUnion
+     * @return header union stack
+     */
+    public static PiHeaderUnionStack of(List<PiHeaderUnion> headerUnions) {
+        return new PiHeaderUnionStack(headerUnions);
+    }
+
+    /**
+     * Return the collection of header union.
+     *
+     * @return the collection header union
+     */
+    public Collection<PiHeaderUnion> headerUnions() {
+        return this.headerUnions;
+    }
+
+    @Override
+    public Type type() {
+        return Type.HEADERUNIONSTACK;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiHeaderUnionStack headerUnionStack = (PiHeaderUnionStack) o;
+        return Objects.equal(headerUnions, headerUnionStack.headerUnions);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(headerUnions);
+    }
+
+    @Override
+    public String toString() {
+        StringJoiner stringParams = new StringJoiner(", ", "(", ")");
+        this.headerUnions().forEach(p -> stringParams.add(p.toString()));
+        return stringParams.toString();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiStruct.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiStruct.java
new file mode 100644
index 0000000..7c60c16
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiStruct.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.pi.model.PiData;
+
+import java.util.List;
+import java.util.StringJoiner;
+
+/**
+ * Struct entity in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiStruct implements PiData {
+    private final ImmutableList<PiData> struct;
+
+    /**
+     * Creates a new protocol-independent struct instance for the given collection of PiData.
+     *
+     * @param struct the collection of PiData
+     */
+    private PiStruct(List<PiData> struct) {
+        this.struct = ImmutableList.copyOf(struct);
+    }
+
+    /**
+     * Returns a new protocol-independent struct.
+     * @param struct the list of PiData
+     * @return struct
+     */
+    public static PiStruct of(List<PiData> struct) {
+        return new PiStruct(struct);
+    }
+
+    /**
+     * Return protocol-independent struct instance.
+     *
+     * @return the list of PiData
+     */
+    public List<PiData> struct() {
+        return this.struct;
+    }
+
+    @Override
+    public Type type() {
+        return Type.STRUCT;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiStruct st = (PiStruct) o;
+        return Objects.equal(struct, st.struct);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(struct);
+    }
+
+    @Override
+    public String toString() {
+        StringJoiner stringParams = new StringJoiner(", ", "(", ")");
+        this.struct().forEach(p -> stringParams.add(p.toString()));
+        return stringParams.toString();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiTuple.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiTuple.java
new file mode 100644
index 0000000..e88fede
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/PiTuple.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.pi.model.PiData;
+
+import java.util.List;
+import java.util.StringJoiner;
+
+/**
+ * Tuple entity in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiTuple implements PiData {
+    private final ImmutableList<PiData> tuple;
+
+    /**
+     * Creates a new protocol-independent tuple instance for the given collection of PiData.
+     *
+     * @param tuple the collection of PiData
+     */
+    private PiTuple(List<PiData> tuple) {
+        this.tuple = ImmutableList.copyOf(tuple);
+    }
+
+    /**
+     * Returns a new protocol-independent tuple.
+     * @param tuple the list of PiData
+     * @return tuple
+     */
+    public static PiTuple of(List<PiData> tuple) {
+        return new PiTuple(tuple);
+    }
+
+    /**
+     * Return protocol-independent tuple instance.
+     *
+     * @return the list of PiData
+     */
+    public List<PiData> tuple() {
+        return this.tuple;
+    }
+
+    @Override
+    public Type type() {
+        return Type.TUPLE;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PiTuple tp = (PiTuple) o;
+        return Objects.equal(tuple, tp.tuple);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(tuple);
+    }
+
+    @Override
+    public String toString() {
+        StringJoiner stringParams = new StringJoiner(", ", "(", ")");
+        this.tuple().forEach(p -> stringParams.add(p.toString()));
+        return stringParams.toString();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/data/package-info.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/package-info.java
new file mode 100644
index 0000000..86fa76b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/data/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Classes abstracting data that can be used for runtime operations of a protocol-independent pipeline.
+ */
+
+package org.onosproject.net.pi.runtime.data;
\ No newline at end of file