Netflow support for ONOS

Change-Id: I6c55168229f63d70c97fc6e19169d120a39de3fe
diff --git a/apps/netflow/api/BUILD b/apps/netflow/api/BUILD
new file mode 100644
index 0000000..f72e3bc
--- /dev/null
+++ b/apps/netflow/api/BUILD
@@ -0,0 +1,3 @@
+osgi_jar_with_tests(
+    deps = CORE_DEPS,
+)
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/DataDeserializer.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/DataDeserializer.java
new file mode 100644
index 0000000..5821361
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/DataDeserializer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023-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.netflow;
+
+import org.onlab.packet.IPacket;
+import org.onlab.packet.DeserializationException;
+@FunctionalInterface
+public interface DataDeserializer<U extends IPacket> {
+
+    /**
+     * Deserialize a netflow data flowset packet object from a byte array.
+     *
+     * @param data     input array to take packet bytes from
+     * @param offset   index where this packet header begins in the byte array
+     * @param length   length of the packet header
+     * @param template data template
+     * @return a deserialized packet object
+     * @throws DeserializationException if the packet cannot be deserialized
+     *         from the input
+     */
+    U deserialize(byte[] data, int offset, int length, FlowRecord template) throws DeserializationException;
+}
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/DataRecord.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/DataRecord.java
new file mode 100644
index 0000000..c584044
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/DataRecord.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023-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.netflow;
+
+import org.onlab.packet.BasePacket;
+
+/**
+ * A Flow Data Record is a data record that contains values of the Flow
+ * parameters corresponding to a Template Record.
+ */
+public abstract class DataRecord extends BasePacket implements FlowRecord {
+
+    @Override
+    public byte[] serialize() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+}
+
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/Flow.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/Flow.java
new file mode 100644
index 0000000..2c09e71
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/Flow.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2023-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.netflow;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Flow is a collection of Flow Data Record(s).
+ * each containing a set of field values.  The Type and
+ * Length of the fields have been previously defined in the
+ * Template Record referenced by the FlowSet ID or Template ID.
+ * Ref: https://www.ietf.org/rfc/rfc3954.txt
+ */
+public final class Flow {
+
+    /*
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |   Record 1 - Field Value 1    |   Record 1 - Field Value 2    |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     */
+
+    private FlowField field;
+
+    private Object value;
+
+    private Flow(Builder builder) {
+        this.field = builder.field;
+        this.value = builder.value;
+    }
+
+    /**
+     * The getter for flow fields.
+     *
+     * @return flow field
+     */
+    public FlowField getField() {
+        return field;
+    }
+
+    /**
+     * Returns flow value.
+     *
+     * @return flow value
+     */
+    public Object getValue() {
+        return value;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public int hashCode() {
+        int hash = 5;
+        hash = 23 * hash + Objects.hashCode(this.field);
+        hash = 23 * hash + Objects.hashCode(this.value);
+        return hash;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final Flow other = (Flow) obj;
+        if (this.field != other.field) {
+            return false;
+        }
+        return Objects.equals(this.value, other.value);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("field", field)
+                .add("value", value)
+                .toString();
+    }
+
+    /**
+     * Flow data value builder.
+     */
+    public static class Builder {
+
+        private FlowField field;
+
+        private Object value;
+
+        /**
+         * Setter for flow fields.
+         *
+         * @param field flow field.
+         * @return this class builder.
+         */
+        public Builder field(FlowField field) {
+            this.field = field;
+            return this;
+        }
+
+        /**
+         * Setter for flow data value.
+         *
+         * @param value flow data value.
+         * @return this class builder.
+         */
+        public Builder value(Object value) {
+            this.value = value;
+            return this;
+        }
+
+        /**
+         * Checks arguments for flow data value.
+         */
+        private void checkArguments() {
+            checkNotNull(field, "flow field cannot be null");
+            checkNotNull(value, "value cannot be null");
+        }
+
+        /**
+         * Builds data flow.
+         *
+         * @return data flow object.
+         */
+        public Flow build() {
+            checkArguments();
+            return new Flow(this);
+        }
+
+    }
+
+}
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowField.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowField.java
new file mode 100644
index 0000000..207903c
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowField.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2023-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.netflow;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiFunction;
+
+import static org.onosproject.netflow.NetflowUtils.VAR_INT_LONG;
+import static org.onosproject.netflow.NetflowUtils.VAR_BYTE;
+import static org.onosproject.netflow.NetflowUtils.NULL;
+import static org.onosproject.netflow.NetflowUtils.VAR_SHORT;
+import static org.onosproject.netflow.NetflowUtils.VAR_IP_ADDRESS;
+import static org.onosproject.netflow.NetflowUtils.VAR_SHORT_INT;
+import static org.onosproject.netflow.NetflowUtils.VAR_INT;
+import static org.onosproject.netflow.NetflowUtils.VAR_MAC;
+
+/**
+ * The flow fields are a selection of Packet Header
+ * fields, lookup results (for example, the autonomous system numbers or
+ * the subnet masks), and properties of the packet such as length.
+ */
+public enum FlowField {
+
+    /**
+     * Flow field type definition reference.
+     * RFC reference :- rfc3954
+     * https://www.ietf.org/rfc/rfc3954.txt
+     * Section :- Field Type Definitions.
+     */
+    IN_BYTES(1, VAR_INT_LONG),
+    IN_PKTS(2, VAR_INT_LONG),
+    FLOWS(3, VAR_INT_LONG),
+    PROTOCOL(4, VAR_BYTE),
+    SRC_TOS(5, VAR_BYTE),
+    TCP_FLAGS(6, VAR_BYTE),
+    L4_SRC_PORT(7, VAR_SHORT),
+    IPV4_SRC_ADDR(8, VAR_IP_ADDRESS),
+    SRC_MASK(9, VAR_BYTE),
+    INPUT_SNMP(10, VAR_SHORT_INT),
+    L4_DST_PORT(11, VAR_SHORT),
+    IPV4_DST_ADDR(12, VAR_IP_ADDRESS),
+    DST_MASK(13, VAR_BYTE),
+    OUTPUT_SNMP(14, VAR_SHORT_INT),
+    IPV4_NEXT_HOP(15, VAR_IP_ADDRESS),
+    SRC_AS(16, VAR_SHORT_INT),
+    DST_AST(17, VAR_SHORT_INT),
+    BGP_IPV4_NEXT_HOP(18, VAR_IP_ADDRESS),
+    MUL_DST_PKTS(19, VAR_INT_LONG),
+    MUL_DST_BYTES(20, VAR_INT_LONG),
+    LAST_SWITCHED(21, VAR_INT),
+    FIRST_SWITCHED(22, VAR_INT),
+    OUT_BYTES(23, VAR_INT_LONG),
+    OUT_PKTS(24, VAR_INT_LONG),
+    MIN_PKT_LNGTH(25, NULL),
+    MAX_PKT_LNGTH(26, NULL),
+    IPV6_SRC_ADDR(27, VAR_IP_ADDRESS),
+    IPV6_DST_ADDR(28, VAR_IP_ADDRESS),
+    IPV6_SRC_MASK(29, VAR_BYTE),
+    IPV6_DST_MASK(30, VAR_BYTE),
+    IPV6_FLOW_LABEL(31, NULL),
+    ICMP_TYPE(32, VAR_SHORT),
+    MUL_IGMP_TYPE(33, VAR_BYTE),
+    SAMPLING_INTERVAL(34, VAR_INT),
+    SAMPLING_ALGORITHM(35, VAR_BYTE),
+    FLOW_ACTIVE_TIMEOUT(36, VAR_SHORT),
+    FLOW_INACTIVE_TIMEOUT(37, VAR_SHORT),
+    ENGINE_TYPE(38, VAR_BYTE),
+    ENGINE_ID(39, VAR_BYTE),
+    TOTAL_BYTES_EXP(40, VAR_INT_LONG),
+    TOTAL_PKTS_EXP(41, VAR_INT_LONG),
+    TOTAL_FLOWS_EXP(42, VAR_INT_LONG),
+    IPV4_SRC_PREFIX(44, NULL),
+    IPV4_DST_PREFIX(45, NULL),
+    MPLS_TOP_LABEL_TYPE(46, VAR_BYTE),
+    MPLS_TOP_LABEL_IP_ADDR(47, VAR_IP_ADDRESS),
+    FLOW_SAMPLER_ID(48, VAR_BYTE),
+    FLOW_SAMPLER_MODE(49, VAR_BYTE),
+    FLOW_SAMPLER_RANDOM_INTERVAL(50, NULL),
+    MIN_TTL(52, NULL),
+    MAX_TTL(53, NULL),
+    IPV4_IDENT(54, NULL),
+    DST_TOS(55, VAR_BYTE),
+    IN_SRC_MAC(56, VAR_MAC),
+    OUT_DST_MAC(57, VAR_MAC),
+    SRC_VLAN(58, VAR_SHORT),
+    DST_VLAN(59, VAR_SHORT),
+    IP_PROTOCOL_VERSION(60, VAR_BYTE),
+    DIRECTION(61, VAR_BYTE),
+    IPV6_NEXT_HOP(62, VAR_IP_ADDRESS),
+    BPG_IPV6_NEXT_HOP(63, VAR_IP_ADDRESS),
+    IPV6_OPTION_HEADERS(64, VAR_INT),
+    MPLS_LABEL_1(70, NULL),
+    MPLS_LABEL_2(71, NULL),
+    MPLS_LABEL_3(72, NULL),
+    MPLS_LABEL_4(73, NULL),
+    MPLS_LABEL_5(74, NULL),
+    MPLS_LABEL_6(75, NULL),
+    MPLS_LABEL_7(76, NULL),
+    MPLS_LABEL_8(77, NULL),
+    MPLS_LABEL_9(78, NULL),
+    MPLS_LABEL_10(79, NULL),
+    IN_DST_MAC(80, VAR_MAC),
+    OUT_SRC_MAC(81, VAR_MAC),
+    IF_NAME(82, NULL),
+    IF_DESC(83, NULL),
+    SAMPLER_NAME(84, NULL),
+    IN_PERMANENT_BYTES(85, NULL),
+    IN_PERMANENT_PKTS(86, NULL),
+    FRAGMENT_OFFSET(88, NULL),
+    FORWARDING_STATUS(89, NULL),
+    MPLS_PAL_RD(90, NULL),
+    MPLS_PREFIX_LEN(91, NULL),
+    SRC_TRAFFIC_INDEX(92, NULL),
+    DST_TRAFFIC_INDEX(93, NULL),
+    APPLICATION_DESCRIPTION(94, NULL),
+    APPLICATION_TAG(95, NULL),
+    APPLICATION_NAME(96, NULL),
+    POST_IP_DIFF_SERV_CODE_POINT(98, NULL),
+    REPLICATION_FACTOR(99, NULL),
+    DEPRECATED(100, NULL),
+    LAYER2_PACKET_SECTION_OFFSET(102, NULL),
+    LAYER2_PACKET_SECTION_SIZE(103, NULL),
+    LAYER2_PACKET_SECTION_DATA(104, NULL);
+
+    final int fieldID;
+    final BiFunction<ByteBuffer, Integer, Object> parser;
+    private static Map<Integer, FlowField> fields = new ConcurrentHashMap<>();
+
+    private FlowField(int fieldID, BiFunction<ByteBuffer, Integer, Object> parser) {
+        this.fieldID = fieldID;
+        this.parser = parser;
+    }
+
+    static {
+        Arrays.stream(FlowField.values()).forEach(f -> fields.put(f.fieldID, f));
+    }
+
+    public static Optional<FlowField> getField(int fieldId) {
+        return Optional.of(fieldId)
+                .filter(id -> fields.containsKey(id))
+                .map(id -> fields.get(id));
+    }
+
+    public BiFunction<ByteBuffer, Integer, Object> getParser() {
+        return this.parser;
+    }
+
+}
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowRecord.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowRecord.java
new file mode 100644
index 0000000..a19a162
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowRecord.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2023-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.netflow;
+
+/**
+ * A Flow Record is a data record that contains values of the Flow
+ * parameters corresponding to a Template Record.
+ */
+public interface FlowRecord {
+    TemplateId getTemplateId();
+}
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowTemplateField.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowTemplateField.java
new file mode 100644
index 0000000..b274409
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/FlowTemplateField.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2023-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.netflow;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Flow template fields.
+ * Ref: https://www.ietf.org/rfc/rfc3954.txt
+ */
+public final class FlowTemplateField {
+
+    /*
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |        Field Type 1           |         Field Length 1        |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |        Field Type 2           |         Field Length 2        |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     */
+
+    private FlowField flowField;
+
+    private int length;
+
+    private FlowTemplateField(Builder builder) {
+        this.flowField = builder.flowField;
+        this.length = builder.length;
+    }
+
+    /**
+     * Returns a numeric value that represents the type of the field.
+     *
+     * @return flow field
+     */
+    public FlowField getFlowField() {
+        return flowField;
+    }
+
+    /**
+     * Returns length of the corresponding Field Type, in bytes.
+     *
+     * @return flow value length
+     */
+    public int getLength() {
+        return length;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        hash = 97 * hash + Objects.hashCode(this.flowField);
+        hash = 97 * hash + this.length;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final FlowTemplateField other = (FlowTemplateField) obj;
+        if (this.length != other.length) {
+            return false;
+        }
+        return this.flowField == other.flowField;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("flowField", flowField)
+                .add("length", length)
+                .toString();
+    }
+
+
+    public static class Builder {
+        private FlowField flowField;
+
+        private int length;
+
+        /**
+         * Setter for flowfield.
+         *
+         * @param fieldId flow field.
+         * @return this class builder.
+         */
+        public Builder flowField(int fieldId) {
+            this.flowField = FlowField.getField(fieldId)
+                    .orElseThrow(() -> new RuntimeException("Unsupported flow field"));
+            return this;
+        }
+
+        /**
+         * Setter for flow template length.
+         *
+         * @param length flow template length.
+         * @return this class builder.
+         */
+        public Builder length(int length) {
+            this.length = length;
+            return this;
+        }
+
+        /**
+         * Checks arguments for flow template field.
+         */
+        private void checkArguments() {
+            checkState(length != 0, "Flow length can be zero.");
+            checkNotNull(flowField, "Flow field can not be null.");
+        }
+
+        /**
+         * Builds flow template field.
+         *
+         * @return flow template field.
+         */
+        public FlowTemplateField build() {
+            checkArguments();
+            return new FlowTemplateField(this);
+        }
+    }
+}
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/NetflowUtils.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/NetflowUtils.java
new file mode 100644
index 0000000..7e75dc7
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/NetflowUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2023-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.netflow;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.function.BiFunction;
+
+
+/**
+ * Netflow utility.
+ */
+public final class NetflowUtils {
+    private NetflowUtils() {
+    }
+
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_BYTE = (bb, len) -> {
+        return bb.get();
+    };
+
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_SHORT = (bb, len) -> {
+        return bb.getShort();
+    };
+
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_INT = (bb, len) -> {
+        return bb.getInt();
+    };
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_FLOAT = (bb, len) -> {
+        return bb.getFloat();
+    };
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_LONG = (bb, len) -> {
+        return bb.getLong();
+    };
+
+    public static final BiFunction<ByteBuffer, Integer, Object> NULL = (bb, len) -> {
+        byte[] address = new byte[len];
+        bb.get(address);
+        return null;
+    };
+
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_INT_LONG = (bb, len) -> {
+        if (len == 4) {
+            return bb.getInt();
+        }
+        return bb.getLong();
+    };
+
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_SHORT_INT = (bb, len) -> {
+        if (len == 2) {
+            return bb.getShort();
+        }
+        return bb.getInt();
+    };
+
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_IP_ADDRESS = (bb, len) -> {
+        return toInetAddress(bb, len);
+    };
+
+    public static final BiFunction<ByteBuffer, Integer, Object> VAR_MAC = (bb, len) -> {
+        byte[] mac = new byte[len];
+        bb.get(mac);
+        //return MacAddress.valueOf(mac);;
+        return null;
+    };
+
+    public static InetAddress toInetAddress(ByteBuffer bb, int length) {
+        byte[] address = new byte[length];
+        bb.get(address);
+
+        InetAddress ipAddress = null;
+        try {
+            ipAddress = InetAddress.getByAddress(address);
+        } catch (UnknownHostException e) {
+            throw new IllegalArgumentException("Invalid host buffer");
+        }
+
+        return ipAddress;
+    }
+
+}
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/SourceId.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/SourceId.java
new file mode 100644
index 0000000..1b7731f
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/SourceId.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2023-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.netflow;
+
+import java.util.Objects;
+import com.google.common.base.MoreObjects;
+
+/**
+ * SourceId is that identifies the Exporter Observation Domain.
+ * NetFlow Collectors SHOULD use the combination of the source IP
+ * address and the Source ID field to separate different export
+ * streams originating from the same Exporter.
+ * Ref: https://www.ietf.org/rfc/rfc3954.txt
+ */
+public class SourceId {
+
+    private String sourceIp;
+
+    private int id;
+
+    public SourceId(int id, String sourceIp) {
+        this.sourceIp = sourceIp;
+        this.id = id;
+    }
+
+    public SourceId(int id) {
+        this.id = id;
+    }
+
+    /**
+     * Returns exporter ip address.
+     *
+     * @return exporter ip address.
+     */
+    public String getSourceIp() {
+        return sourceIp;
+    }
+
+    /**
+     * Returns exporter unique id.
+     *
+     * @return exporter unique id.
+     */
+    public int getId() {
+        return id;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        hash = 23 * hash + Objects.hashCode(this.sourceIp);
+        hash = 23 * hash + this.id;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final SourceId other = (SourceId) obj;
+        if (this.id != other.id) {
+            return false;
+        }
+        return Objects.equals(this.sourceIp, other.sourceIp);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("sourceIp", sourceIp)
+                .add("id", id)
+                .toString();
+    }
+
+}
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/TemplateId.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/TemplateId.java
new file mode 100644
index 0000000..bf6f4a2
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/TemplateId.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023-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.netflow;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Template Records is given a unique Template ID.
+ * This uniqueness is local to the Observation
+ * Domain that generated the Template ID.  Template IDs 0-255 are
+ * reserved for Template FlowSets, Options FlowSets, and other
+ * reserved FlowSets yet to be created.  Template IDs of Data
+ * FlowSets are numbered from 256 to 65535.
+ * Ref: https://www.ietf.org/rfc/rfc3954.txt
+ */
+public class TemplateId {
+
+    private int id;
+
+    public TemplateId(int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("id", id)
+                .toString();
+    }
+
+}
diff --git a/apps/netflow/api/src/main/java/org/onosproject/netflow/package-info.java b/apps/netflow/api/src/main/java/org/onosproject/netflow/package-info.java
new file mode 100644
index 0000000..4ae967a
--- /dev/null
+++ b/apps/netflow/api/src/main/java/org/onosproject/netflow/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2023-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.
+ */
+
+/**
+ * Sample application that assigns and manages netflow collector.
+ */
+package org.onosproject.netflow;
\ No newline at end of file