aboutsummaryrefslogtreecommitdiff
path: root/helper
diff options
context:
space:
mode:
authorAnders Roxell <anders.roxell@linaro.org>2014-09-02 20:38:00 +0200
committerMaxim Uvarov <maxim.uvarov@linaro.org>2014-09-02 22:56:11 +0400
commit8deea2005ad3f42eb5987171e0b3b1a428aac057 (patch)
tree43a49b97376396ff77ce13b486607c98ca4565cf /helper
parent8e1bf298be449b8f91f25b96870732c433f4ddc0 (diff)
move helper functions and rename to prefix to odph_
Signed-off-by: Anders Roxell <anders.roxell@linaro.org> Acked-by: Petri Savolainen <petri.savolainen@linaro.org> Reviewed-by: Stuart Haslam <stuart.haslam@arm.com> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'helper')
-rw-r--r--helper/include/odph_chksum.h53
-rw-r--r--helper/include/odph_eth.h87
-rw-r--r--helper/include/odph_icmp.h99
-rw-r--r--helper/include/odph_ip.h156
-rw-r--r--helper/include/odph_linux.h68
-rw-r--r--helper/include/odph_packet.h97
-rw-r--r--helper/include/odph_ring.h577
-rw-r--r--helper/include/odph_udp.h102
8 files changed, 1239 insertions, 0 deletions
diff --git a/helper/include/odph_chksum.h b/helper/include/odph_chksum.h
new file mode 100644
index 0000000..710711a
--- /dev/null
+++ b/helper/include/odph_chksum.h
@@ -0,0 +1,53 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP Checksum
+ */
+#ifndef ODP_CHKSUM_H_
+#define ODP_CHKSUM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_std_types.h>
+
+/**
+ * Checksum
+ *
+ * @param buffer calculate chksum for buffer
+ * @param len buffer length
+ *
+ * @return checksum value in host cpu order
+ */
+static inline uint16sum_t odp_chksum(void *buffer, int len)
+{
+ uint16_t *buf = buffer;
+ uint32_t sum = 0;
+ uint16_t result;
+
+ for (sum = 0; len > 1; len -= 2)
+ sum += *buf++;
+
+ if (len == 1)
+ sum += *(unsigned char *)buf;
+
+ sum = (sum >> 16) + (sum & 0xFFFF);
+ sum += (sum >> 16);
+ result = ~sum;
+
+ return (__odp_force uint16sum_t) result;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/helper/include/odph_eth.h b/helper/include/odph_eth.h
new file mode 100644
index 0000000..55a2b1e
--- /dev/null
+++ b/helper/include/odph_eth.h
@@ -0,0 +1,87 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP ethernet header
+ */
+
+#ifndef ODPH_ETH_H_
+#define ODPH_ETH_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_std_types.h>
+#include <odp_byteorder.h>
+#include <odp_align.h>
+#include <odp_debug.h>
+
+#define ODPH_ETHADDR_LEN 6 /**< Ethernet address length */
+#define ODPH_ETHHDR_LEN 14 /**< Ethernet header length */
+#define ODPH_VLANHDR_LEN 4 /**< VLAN header length */
+#define ODPH_ETH_LEN_MIN 60 /**< Min frame length (excl. CRC 4 bytes) */
+#define ODPH_ETH_LEN_MIN_CRC 64 /**< Min frame length (incl. CRC 4 bytes) */
+#define ODPH_ETH_LEN_MAX 1514 /**< Max frame length (excl. CRC 4 bytes) */
+#define ODPH_ETH_LEN_MAX_CRC 1518 /**< Max frame length (incl. CRC 4 bytes) */
+
+/**
+ * Ethernet MAC address
+ */
+typedef struct ODPH_PACKED {
+ uint8_t addr[ODPH_ETHADDR_LEN]; /**< @private Address */
+} odph_ethaddr_t;
+
+/** @internal Compile time assert */
+ODP_STATIC_ASSERT(sizeof(odph_ethaddr_t) == ODPH_ETHADDR_LEN, "ODPH_ETHADDR_T__SIZE_ERROR");
+
+/**
+ * Ethernet header
+ */
+typedef struct ODPH_PACKED {
+ odph_ethaddr_t dst; /**< Destination address */
+ odph_ethaddr_t src; /**< Source address */
+ uint16be_t type; /**< Type */
+} odph_ethhdr_t;
+
+/** @internal Compile time assert */
+ODP_STATIC_ASSERT(sizeof(odph_ethhdr_t) == ODPH_ETHHDR_LEN, "ODPH_ETHHDR_T__SIZE_ERROR");
+
+/**
+ * VLAN header
+ *
+ * @todo Check usage of tpid vs ethertype. Check outer VLAN TPID.
+ */
+typedef struct ODPH_PACKED {
+ uint16be_t tpid; /**< Tag protocol ID (located after ethhdr.src) */
+ uint16be_t tci; /**< Priority / CFI / VLAN ID */
+} odph_vlanhdr_t;
+
+/** @internal Compile time assert */
+ODP_STATIC_ASSERT(sizeof(odph_vlanhdr_t) == ODPH_VLANHDR_LEN, "ODPH_VLANHDR_T__SIZE_ERROR");
+
+
+/* Ethernet header Ether Type ('type') values, a selected few */
+#define ODPH_ETHTYPE_IPV4 0x0800 /**< Internet Protocol version 4 */
+#define ODPH_ETHTYPE_ARP 0x0806 /**< Address Resolution Protocol */
+#define ODPH_ETHTYPE_RARP 0x8035 /**< Reverse Address Resolution Protocol*/
+#define ODPH_ETHTYPE_VLAN 0x8100 /**< VLAN-tagged frame IEEE 802.1Q */
+#define ODPH_ETHTYPE_VLAN_OUTER 0x88A8 /**< Stacked VLANs/QinQ, outer-tag/S-TAG*/
+#define ODPH_ETHTYPE_IPV6 0x86dd /**< Internet Protocol version 6 */
+#define ODPH_ETHTYPE_FLOW_CTRL 0x8808 /**< Ethernet flow control */
+#define ODPH_ETHTYPE_MPLS 0x8847 /**< MPLS unicast */
+#define ODPH_ETHTYPE_MPLS_MCAST 0x8848 /**< MPLS multicast */
+#define ODPH_ETHTYPE_MACSEC 0x88E5 /**< MAC security IEEE 802.1AE */
+#define ODPH_ETHTYPE_1588 0x88F7 /**< Precision Time Protocol IEEE 1588 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/helper/include/odph_icmp.h b/helper/include/odph_icmp.h
new file mode 100644
index 0000000..8414d7e
--- /dev/null
+++ b/helper/include/odph_icmp.h
@@ -0,0 +1,99 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP ICMP header
+ */
+
+#ifndef ODPH_ICMP_H_
+#define ODPH_ICMP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_align.h>
+#include <odp_debug.h>
+#include <odp_byteorder.h>
+
+/** ICMP header length */
+#define ODPH_ICMPHDR_LEN 8
+
+/** ICMP header */
+typedef struct ODPH_PACKED {
+ uint8_t type; /**< message type */
+ uint8_t code; /**< type sub-code */
+ uint16sum_t chksum; /**< checksum of icmp header */
+ union {
+ struct {
+ uint16be_t id;
+ uint16be_t sequence;
+ } echo; /**< echo datagram */
+ uint32be_t gateway; /**< gateway address */
+ struct {
+ uint16be_t __unused;
+ uint16be_t mtu;
+ } frag; /**< path mtu discovery */
+ } un; /**< icmp sub header */
+} odph_icmphdr_t;
+
+#define ICMP_ECHOREPLY 0 /**< Echo Reply */
+#define ICMP_DEST_UNREACH 3 /**< Destination Unreachable */
+#define ICMP_SOURCE_QUENCH 4 /**< Source Quench */
+#define ICMP_REDIRECT 5 /**< Redirect (change route) */
+#define ICMP_ECHO 8 /**< Echo Request */
+#define ICMP_TIME_EXCEEDED 11 /**< Time Exceeded */
+#define ICMP_PARAMETERPROB 12 /**< Parameter Problem */
+#define ICMP_TIMESTAMP 13 /**< Timestamp Request */
+#define ICMP_TIMESTAMPREPLY 14 /**< Timestamp Reply */
+#define ICMP_INFO_REQUEST 15 /**< Information Request */
+#define ICMP_INFO_REPLY 16 /**< Information Reply */
+#define ICMP_ADDRESS 17 /**< Address Mask Request */
+#define ICMP_ADDRESSREPLY 18 /**< Address Mask Reply */
+#define NR_ICMP_TYPES 18 /**< Number of icmp types */
+
+/** Codes for UNREACH. */
+#define ICMP_NET_UNREACH 0 /**< Network Unreachable */
+#define ICMP_HOST_UNREACH 1 /**< Host Unreachable */
+#define ICMP_PROT_UNREACH 2 /**< Protocol Unreachable */
+#define ICMP_PORT_UNREACH 3 /**< Port Unreachable */
+#define ICMP_FRAG_NEEDED 4 /**< Fragmentation Needed/DF set*/
+#define ICMP_SR_FAILED 5 /**< Source Route failed */
+#define ICMP_NET_UNKNOWN 6 /**< Network Unknown */
+#define ICMP_HOST_UNKNOWN 7 /**< Host Unknown */
+#define ICMP_HOST_ISOLATED 8 /**< Host Isolated */
+#define ICMP_NET_ANO 9 /**< ICMP_NET_ANO */
+#define ICMP_HOST_ANO 10 /**< ICMP_HOST_ANO */
+#define ICMP_NET_UNR_TOS 11 /**< ICMP_NET_UNR_TOS */
+#define ICMP_HOST_UNR_TOS 12 /**< ICMP_HOST_UNR_TOS */
+#define ICMP_PKT_FILTERED 13 /**< Packet filtered */
+#define ICMP_PREC_VIOLATION 14 /**< Precedence violation */
+#define ICMP_PREC_CUTOFF 15 /**< Precedence cut off */
+#define NR_ICMP_UNREACH 15 /**< instead of hardcoding
+ immediate value */
+
+/** Codes for REDIRECT. */
+#define ICMP_REDIR_NET 0 /**< Redirect Net */
+#define ICMP_REDIR_HOST 1 /**< Redirect Host */
+#define ICMP_REDIR_NETTOS 2 /**< Redirect Net for TOS */
+#define ICMP_REDIR_HOSTTOS 3 /**< Redirect Host for TOS */
+
+/** Codes for TIME_EXCEEDED. */
+#define ICMP_EXC_TTL 0 /**< TTL count exceeded */
+#define ICMP_EXC_FRAGTIME 1 /**< Fragment Reass time
+ exceeded*/
+
+/** @internal Compile time assert */
+ODP_STATIC_ASSERT(sizeof(odph_icmphdr_t) == ODPH_ICMPHDR_LEN, "ODPH_ICMPHDR_T__SIZE_ERROR");
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/helper/include/odph_ip.h b/helper/include/odph_ip.h
new file mode 100644
index 0000000..ca71c44
--- /dev/null
+++ b/helper/include/odph_ip.h
@@ -0,0 +1,156 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP IP header
+ */
+
+#ifndef ODPH_IP_H_
+#define ODPH_IP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_align.h>
+#include <odp_debug.h>
+#include <odp_byteorder.h>
+#include <odph_chksum.h>
+
+#include <string.h>
+
+#define ODPH_IPV4 4 /**< IP version 4 */
+#define ODPH_IPV4HDR_LEN 20 /**< Min length of IP header (no options) */
+#define ODPH_IPV4HDR_IHL_MIN 5 /**< Minimum IHL value*/
+
+/** @internal Returns IPv4 version */
+#define ODPH_IPV4HDR_VER(ver_ihl) (((ver_ihl) & 0xf0) >> 4)
+
+/** @internal Returns IPv4 header length */
+#define ODPH_IPV4HDR_IHL(ver_ihl) ((ver_ihl) & 0x0f)
+
+/** @internal Returns IPv4 Don't fragment */
+#define ODPH_IPV4HDR_FLAGS_DONT_FRAG(frag_offset) ((frag_offset) & 0x4000)
+
+/** @internal Returns IPv4 more fragments */
+#define ODPH_IPV4HDR_FLAGS_MORE_FRAGS(frag_offset) ((frag_offset) & 0x2000)
+
+/** @internal Returns IPv4 fragment offset */
+#define ODPH_IPV4HDR_FRAG_OFFSET(frag_offset) ((frag_offset) & 0x1fff)
+
+/** @internal Returns true if IPv4 packet is a fragment */
+#define ODPH_IPV4HDR_IS_FRAGMENT(frag_offset) ((frag_offset) & 0x3fff)
+
+/** IPv4 header */
+typedef struct ODPH_PACKED {
+ uint8_t ver_ihl; /**< Version / Header length */
+ uint8_t tos; /**< Type of service */
+ uint16be_t tot_len; /**< Total length */
+ uint16be_t id; /**< ID */
+ uint16be_t frag_offset; /**< Fragmentation offset */
+ uint8_t ttl; /**< Time to live */
+ uint8_t proto; /**< Protocol */
+ uint16sum_t chksum; /**< Checksum */
+ uint32be_t src_addr; /**< Source address */
+ uint32be_t dst_addr; /**< Destination address */
+} odph_ipv4hdr_t;
+
+/** @internal Compile time assert */
+ODP_STATIC_ASSERT(sizeof(odph_ipv4hdr_t) == ODPH_IPV4HDR_LEN, "ODPH_IPV4HDR_T__SIZE_ERROR");
+
+/**
+ * Check if IPv4 checksum is valid
+ *
+ * @param pkt ODP packet
+ *
+ * @return 1 if checksum is valid, otherwise 0
+ */
+static inline int odph_ipv4_csum_valid(odp_packet_t pkt)
+{
+ uint16be_t res = 0;
+ uint16_t *w;
+ int nleft = sizeof(odph_ipv4hdr_t);
+ odph_ipv4hdr_t ip;
+ uint16be_t chksum;
+
+ if (!odp_packet_l3_offset(pkt))
+ return 0;
+
+ memcpy(&ip, odp_packet_l3(pkt), sizeof(odph_ipv4hdr_t));
+ w = (uint16_t *)(void *)&ip;
+ chksum = ip.chksum;
+ ip.chksum = 0x0;
+
+ res = odp_chksum(w, nleft);
+ return (res == chksum) ? 1 : 0;
+}
+
+/**
+ * Calculate and fill in IPv4 checksum
+ *
+ * @note when using this api to populate data destined for the wire
+ * odp_cpu_to_be_16() can be used to remove sparse warnings
+ *
+ * @param pkt ODP packet
+ *
+ * @return IPv4 checksum in host cpu order, or 0 on failure
+ */
+static inline uint16sum_t odph_ipv4_csum_update(odp_packet_t pkt)
+{
+ uint16_t *w;
+ odph_ipv4hdr_t *ip;
+ int nleft = sizeof(odph_ipv4hdr_t);
+
+ if (!odp_packet_l3_offset(pkt))
+ return 0;
+
+ ip = (odph_ipv4hdr_t *)odp_packet_l3(pkt);
+ w = (uint16_t *)(void *)ip;
+ ip->chksum = odp_chksum(w, nleft);
+ return ip->chksum;
+}
+
+/** IPv6 version */
+#define ODPH_IPV6 6
+
+/** IPv6 header length */
+#define ODPH_IPV6HDR_LEN 40
+
+/**
+ * IPv6 header
+ */
+typedef struct ODPH_PACKED {
+ uint32be_t ver_tc_flow; /**< Version / Traffic class / Flow label */
+ uint16be_t payload_len; /**< Payload length */
+ uint8_t next_hdr; /**< Next header */
+ uint8_t hop_limit; /**< Hop limit */
+ uint8_t src_addr[16]; /**< Source address */
+ uint8_t dst_addr[16]; /**< Destination address */
+} odph_ipv6hdr_t;
+
+/** @internal Compile time assert */
+ODP_STATIC_ASSERT(sizeof(odph_ipv6hdr_t) == ODPH_IPV6HDR_LEN, "ODPH_IPV6HDR_T__SIZE_ERROR");
+
+/** @name
+ * IP protocol values (IPv4:'proto' or IPv6:'next_hdr')
+ * @{*/
+#define ODPH_IPPROTO_ICMP 0x01 /**< Internet Control Message Protocol (1) */
+#define ODPH_IPPROTO_TCP 0x06 /**< Transmission Control Protocol (6) */
+#define ODPH_IPPROTO_UDP 0x11 /**< User Datagram Protocol (17) */
+#define ODPH_IPPROTO_SCTP 0x84 /**< Stream Control Transmission Protocol (132) */
+#define ODPH_IPPROTO_FRAG 0x2C /**< Fragment (44) */
+#define ODPH_IPPROTO_AH 0x33 /**< Authentication Header (51) */
+#define ODPH_IPPROTO_ESP 0x32 /**< Encapsulating Security Payload (50) */
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/helper/include/odph_linux.h b/helper/include/odph_linux.h
new file mode 100644
index 0000000..1ea349a
--- /dev/null
+++ b/helper/include/odph_linux.h
@@ -0,0 +1,68 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP Linux helper API
+ *
+ * This file is an optional helper to odp.h APIs. Application can manage
+ * pthreads also by other means.
+ */
+
+#ifndef ODP_LINUX_H_
+#define ODP_LINUX_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <pthread.h>
+
+/** Pthread status data */
+typedef struct {
+ pthread_t thread; /**< @private Pthread */
+ pthread_attr_t attr; /**< @private Pthread attributes */
+
+} odph_linux_pthread_t;
+
+
+/**
+ * Creates and launches pthreads
+ *
+ * Creates, pins and launches num threads to separate cores starting from
+ * first_core.
+ *
+ * @param thread_tbl Thread table
+ * @param num Number of threads to create
+ * @param first_core First physical core
+ * @param start_routine Thread start function
+ * @param arg Thread argument
+ */
+void odph_linux_pthread_create(odph_linux_pthread_t *thread_tbl,
+ int num, int first_core,
+ void *(*start_routine) (void *), void *arg);
+
+
+/**
+ * Waits pthreads to exit
+ *
+ * Returns when all threads have been exit.
+ *
+ * @param thread_tbl Thread table
+ * @param num Number of threads to create
+ *
+ */
+void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/helper/include/odph_packet.h b/helper/include/odph_packet.h
new file mode 100644
index 0000000..c18f48d
--- /dev/null
+++ b/helper/include/odph_packet.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * Optional ODP packet helper functions
+ */
+
+#ifndef ODPH_PACKET_HELPER_H_
+#define ODPH_PACKET_HELPER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp.h>
+
+/**
+ * Helper: Tests if packet is valid
+ *
+ * Allows for more thorough checking than "if (pkt == ODP_PACKET_INVALID)"
+ *
+ * @param pkt Packet handle
+ *
+ * @return 1 if valid, otherwise 0
+ */
+static inline int odph_packet_is_valid(odp_packet_t pkt)
+{
+ odp_buffer_t buf = odp_buffer_from_packet(pkt);
+
+ return odp_buffer_is_valid(buf);
+}
+
+/**
+ * Helper: Allocate and initialize a packet buffer from a packet pool
+ *
+ * @param pool_id Pool handle
+ *
+ * @note The pool must have been created with 'buf_type=ODP_BUFFER_TYPE_PACKET'
+ *
+ * @return Packet handle or ODP_PACKET_INVALID
+ */
+static inline odp_packet_t odph_packet_alloc(odp_buffer_pool_t pool_id)
+{
+ odp_packet_t pkt;
+ odp_buffer_t buf;
+
+ buf = odp_buffer_alloc(pool_id);
+ if (odp_unlikely(!odp_buffer_is_valid(buf)))
+ return ODP_PACKET_INVALID;
+
+ pkt = odp_packet_from_buffer(buf);
+ odp_packet_init(pkt);
+
+ return pkt;
+}
+
+/**
+ * Helper: Free a packet buffer back into the packet pool
+ *
+ * @param pkt Packet handle
+ */
+static inline void odph_packet_free(odp_packet_t pkt)
+{
+ odp_buffer_t buf = odp_buffer_from_packet(pkt);
+
+ odp_buffer_free(buf);
+}
+
+/**
+ * Helper: Packet buffer maximum data size
+ *
+ * @note odp_packet_buf_size(pkt) != odp_packet_get_len(pkt), the former returns
+ * the max length of the buffer, the latter the size of a received packet.
+ *
+ * @param pkt Packet handle
+ *
+ * @return Packet buffer maximum data size
+ */
+static inline size_t odph_packet_buf_size(odp_packet_t pkt)
+{
+ odp_buffer_t buf = odp_buffer_from_packet(pkt);
+
+ return odp_buffer_size(buf);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/helper/include/odph_ring.h b/helper/include/odph_ring.h
new file mode 100644
index 0000000..76c1db8
--- /dev/null
+++ b/helper/include/odph_ring.h
@@ -0,0 +1,577 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Derived from FreeBSD's bufring.c
+ *
+ **************************************************************************
+ *
+ * Copyright (c) 2007,2008 Kip Macy kmacy@freebsd.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. The name of Kip Macy nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ***************************************************************************/
+
+/**
+ * ODP Ring
+ *
+ * The Ring Manager is a fixed-size queue, implemented as a table of
+ * pointers. Head and tail pointers are modified atomically, allowing
+ * concurrent access to it. It has the following features:
+ *
+ * - FIFO (First In First Out)
+ * - Maximum size is fixed; the pointers are stored in a table.
+ * - Lockless implementation.
+ * - Multi- or single-consumer dequeue.
+ * - Multi- or single-producer enqueue.
+ * - Bulk dequeue.
+ * - Bulk enqueue.
+ *
+ * Note: the ring implementation is not preemptable. A lcore must not
+ * be interrupted by another task that uses the same ring.
+ *
+ */
+
+#ifndef ODPH_RING_H_
+#define ODPH_RING_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <odp_std_types.h>
+#include <odp_hints.h>
+#include <odp_atomic.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+enum odph_ring_queue_behavior {
+ ODPH_RING_QUEUE_FIXED = 0, /**< Enq/Deq a fixed number
+ of items from a ring */
+ ODPH_RING_QUEUE_VARIABLE /**< Enq/Deq as many items
+ a possible from ring */
+};
+
+
+#define ODPH_RING_NAMESIZE 32 /**< The maximum length of a ring name. */
+
+/**
+ * An ODP ring structure.
+ *
+ * The producer and the consumer have a head and a tail index. The particularity
+ * of these index is that they are not between 0 and size(ring). These indexes
+ * are between 0 and 2^32, and we mask their value when we access the ring[]
+ * field. Thanks to this assumption, we can do subtractions between 2 index
+ * values in a modulo-32bit base: that's why the overflow of the indexes is not
+ * a problem.
+ */
+typedef struct odph_ring {
+ /** @private Next in list. */
+ TAILQ_ENTRY(odph_ring) next;
+
+ /** @private Name of the ring. */
+ char name[ODPH_RING_NAMESIZE];
+ /** @private Flags supplied at creation. */
+ int flags;
+
+ /** @private Producer */
+ struct prod {
+ uint32_t watermark; /* Maximum items */
+ uint32_t sp_enqueue; /* True, if single producer. */
+ uint32_t size; /* Size of ring. */
+ uint32_t mask; /* Mask (size-1) of ring. */
+ uint32_t head; /* Producer head. */
+ uint32_t tail; /* Producer tail. */
+ } prod ODP_ALIGNED_CACHE;
+
+ /** @private Consumer */
+ struct cons {
+ uint32_t sc_dequeue; /* True, if single consumer. */
+ uint32_t size; /* Size of the ring. */
+ uint32_t mask; /* Mask (size-1) of ring. */
+ uint32_t head; /* Consumer head. */
+ uint32_t tail; /* Consumer tail. */
+ } cons ODP_ALIGNED_CACHE;
+
+ /** @private Memory space of ring starts here. */
+ void *ring[0] ODP_ALIGNED_CACHE;
+} odph_ring_t;
+
+
+#define ODPH_RING_F_SP_ENQ 0x0001 /* The default enqueue is "single-producer".*/
+#define ODPH_RING_F_SC_DEQ 0x0002 /* The default dequeue is "single-consumer".*/
+#define ODPH_RING_QUOT_EXCEED (1 << 31) /* Quota exceed for burst ops */
+#define ODPH_RING_SZ_MASK (unsigned)(0x0fffffff) /* Ring size mask */
+
+
+/**
+ * Create a new ring named *name* in memory.
+ *
+ * This function uses odp_shm_reserve() to allocate memory. Its size is
+ * set to *count*, which must be a power of two. Water marking is
+ * disabled by default. Note that the real usable ring size is count-1
+ * instead of count.
+ *
+ * @param name
+ * The name of the ring.
+ * @param count
+ * The size of the ring (must be a power of 2).
+ * @param socket_id (dummy, not included : todo)
+ * @param flags
+ * An OR of the following:
+ * - RING_F_SP_ENQ: If this flag is set, the default behavior when
+ * using ``odp_ring_enqueue()`` or ``odp_ring_enqueue_bulk()``
+ * is "single-producer". Otherwise, it is "multi-producers".
+ * - RING_F_SC_DEQ: If this flag is set, the default behavior when
+ * using ``odp_ring_dequeue()`` or ``odp_ring_dequeue_bulk()``
+ * is "single-consumer". Otherwise, it is "multi-consumers".
+ * @return
+ * On success, the pointer to the new allocated ring. NULL on error with
+ * odp_errno set appropriately. Possible errno values include:
+ * - EINVAL - count provided is not a power of 2
+ * - ENOSPC - the maximum number of memzones has already been allocated
+ * - EEXIST - a memzone with the same name already exists
+ * - ENOMEM - no appropriate memory area found in which to create memzone
+ */
+odph_ring_t *odph_ring_create(const char *name, unsigned count,
+ unsigned flags);
+
+
+/**
+ * Change the high water mark.
+ *
+ * If *count* is 0, water marking is disabled. Otherwise, it is set to the
+ * *count* value. The *count* value must be greater than 0 and less
+ * than the ring size.
+ *
+ * This function can be called at any time (not necessarily at
+ * initialization).
+ *
+ * @param r Pointer to the ring structure.
+ * @param count New water mark value.
+ * @return 0: Success; water mark changed.
+ * -EINVAL: Invalid water mark value.
+ */
+int odph_ring_set_water_mark(odph_ring_t *r, unsigned count);
+
+/**
+ * Dump the status of the ring to the console.
+ *
+ * @param r A pointer to the ring structure.
+ */
+void odph_ring_dump(const odph_ring_t *r);
+
+/**
+ * Enqueue several objects on the ring (multi-producers safe).
+ *
+ * This function uses a "compare and set" instruction to move the
+ * producer index atomically.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects).
+ * @param n
+ * The number of objects to add in the ring from the obj_table.
+ * @param behavior
+ * ODP_RING_QUEUE_FIXED: Enqueue a fixed number of items from a ring
+ * ODP_RING_QUEUE_VARIABLE: Enqueue as many items a possible from ring
+ * @return
+ * Depend on the behavior value
+ * if behavior = ODP_RING_QUEUE_FIXED
+ * - 0: Success; objects enqueue.
+ * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
+ * high water mark is exceeded.
+ * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
+ * if behavior = ODP_RING_QUEUE_VARIABLE
+ * - n: Actual number of objects enqueued.
+ */
+int __odph_ring_mp_do_enqueue(odph_ring_t *r, void * const *obj_table,
+ unsigned n,
+ enum odph_ring_queue_behavior behavior);
+
+/**
+ * Enqueue several objects on a ring (NOT multi-producers safe).
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects).
+ * @param n
+ * The number of objects to add in the ring from the obj_table.
+ * @param behavior
+ * ODP_RING_QUEUE_FIXED: Enqueue a fixed number of items from a ring
+ * ODP_RING_QUEUE_VARIABLE: Enqueue as many items a possible from ring
+ * @return
+ * Depend on the behavior value
+ * if behavior = ODP_RING_QUEUE_FIXED
+ * - 0: Success; objects enqueue.
+ * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
+ * high water mark is exceeded.
+ * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
+ * if behavior = ODP_RING_QUEUE_VARIABLE
+ * - n: Actual number of objects enqueued.
+ */
+int __odph_ring_sp_do_enqueue(odph_ring_t *r, void * const *obj_table,
+ unsigned n,
+ enum odph_ring_queue_behavior behavior);
+
+/**
+ * Dequeue several objects from a ring (multi-consumers safe). When
+ * the request objects are more than the available objects, only dequeue the
+ * actual number of objects
+ *
+ * This function uses a "compare and set" instruction to move the
+ * consumer index atomically.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ * The number of objects to dequeue from the ring to the obj_table.
+ * @param behavior
+ * ODP_RING_QUEUE_FIXED: Dequeue a fixed number of items from a ring
+ * ODP_RING_QUEUE_VARIABLE: Dequeue as many items a possible from ring
+ * @return
+ * Depend on the behavior value
+ * if behavior = ODP_RING_QUEUE_FIXED
+ * - 0: Success; objects dequeued.
+ * - -ENOENT: Not enough entries in the ring to dequeue; no object is
+ * dequeued.
+ * if behavior = ODP_RING_QUEUE_VARIABLE
+ * - n: Actual number of objects dequeued.
+ */
+
+int __odph_ring_mc_do_dequeue(odph_ring_t *r, void **obj_table,
+ unsigned n,
+ enum odph_ring_queue_behavior behavior);
+
+/**
+ * Dequeue several objects from a ring (NOT multi-consumers safe).
+ * When the request objects are more than the available objects, only dequeue
+ * the actual number of objects
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ * The number of objects to dequeue from the ring to the obj_table.
+ * @param behavior
+ * ODP_RING_QUEUE_FIXED: Dequeue a fixed number of items from a ring
+ * ODP_RING_QUEUE_VARIABLE: Dequeue as many items a possible from ring
+ * @return
+ * Depend on the behavior value
+ * if behavior = ODP_RING_QUEUE_FIXED
+ * - 0: Success; objects dequeued.
+ * - -ENOENT: Not enough entries in the ring to dequeue; no object is
+ * dequeued.
+ * if behavior = ODP_RING_QUEUE_VARIABLE
+ * - n: Actual number of objects dequeued.
+ */
+int __odph_ring_sc_do_dequeue(odph_ring_t *r, void **obj_table,
+ unsigned n,
+ enum odph_ring_queue_behavior behavior);
+
+/**
+ * Enqueue several objects on the ring (multi-producers safe).
+ *
+ * This function uses a "compare and set" instruction to move the
+ * producer index atomically.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects).
+ * @param n
+ * The number of objects to add in the ring from the obj_table.
+ * @return
+ * - 0: Success; objects enqueue.
+ * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
+ * high water mark is exceeded.
+ * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
+ */
+int odph_ring_mp_enqueue_bulk(odph_ring_t *r, void * const *obj_table,
+ unsigned n);
+
+/**
+ * Enqueue several objects on a ring (NOT multi-producers safe).
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects).
+ * @param n
+ * The number of objects to add in the ring from the obj_table.
+ * @return
+ * - 0: Success; objects enqueued.
+ * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
+ * high water mark is exceeded.
+ * - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
+ */
+int odph_ring_sp_enqueue_bulk(odph_ring_t *r, void * const *obj_table,
+ unsigned n);
+
+/**
+ * Dequeue several objects from a ring (multi-consumers safe).
+ *
+ * This function uses a "compare and set" instruction to move the
+ * consumer index atomically.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ * The number of objects to dequeue from the ring to the obj_table.
+ * @return
+ * - 0: Success; objects dequeued.
+ * - -ENOENT: Not enough entries in the ring to dequeue; no object is
+ * dequeued.
+ */
+int odph_ring_mc_dequeue_bulk(odph_ring_t *r, void **obj_table, unsigned n);
+
+/**
+ * Dequeue several objects from a ring (NOT multi-consumers safe).
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ * The number of objects to dequeue from the ring to the obj_table,
+ * must be strictly positive.
+ * @return
+ * - 0: Success; objects dequeued.
+ * - -ENOENT: Not enough entries in the ring to dequeue; no object is
+ * dequeued.
+ */
+int odph_ring_sc_dequeue_bulk(odph_ring_t *r, void **obj_table, unsigned n);
+
+/**
+ * Test if a ring is full.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @return
+ * - 1: The ring is full.
+ * - 0: The ring is not full.
+ */
+int odph_ring_full(const odph_ring_t *r);
+
+/**
+ * Test if a ring is empty.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @return
+ * - 1: The ring is empty.
+ * - 0: The ring is not empty.
+ */
+int odph_ring_empty(const odph_ring_t *r);
+
+/**
+ * Return the number of entries in a ring.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @return
+ * The number of entries in the ring.
+ */
+unsigned odph_ring_count(const odph_ring_t *r);
+
+/**
+ * Return the number of free entries in a ring.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @return
+ * The number of free entries in the ring.
+ */
+unsigned odph_ring_free_count(const odph_ring_t *r);
+
+/**
+ * search ring by name
+ * @param name ring name to search
+ * @return pointer to ring otherwise NULL
+ */
+odph_ring_t *odph_ring_lookup(const char *name);
+
+/**
+ * Enqueue several objects on the ring (multi-producers safe).
+ *
+ * This function uses a "compare and set" instruction to move the
+ * producer index atomically.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects).
+ * @param n
+ * The number of objects to add in the ring from the obj_table.
+ * @return
+ * - n: Actual number of objects enqueued.
+ */
+int odph_ring_mp_enqueue_burst(odph_ring_t *r, void * const *obj_table,
+ unsigned n);
+
+/**
+ * Enqueue several objects on a ring (NOT multi-producers safe).
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects).
+ * @param n
+ * The number of objects to add in the ring from the obj_table.
+ * @return
+ * - n: Actual number of objects enqueued.
+ */
+int odph_ring_sp_enqueue_burst(odph_ring_t *r, void * const *obj_table,
+ unsigned n);
+/**
+ * Enqueue several objects on a ring.
+ *
+ * This function calls the multi-producer or the single-producer
+ * version depending on the default behavior that was specified at
+ * ring creation time (see flags).
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects).
+ * @param n
+ * The number of objects to add in the ring from the obj_table.
+ * @return
+ * - n: Actual number of objects enqueued.
+ */
+int odph_ring_enqueue_burst(odph_ring_t *r, void * const *obj_table,
+ unsigned n);
+
+/**
+ * Dequeue several objects from a ring (multi-consumers safe). When the request
+ * objects are more than the available objects, only dequeue the actual number
+ * of objects
+ *
+ * This function uses a "compare and set" instruction to move the
+ * consumer index atomically.
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ * The number of objects to dequeue from the ring to the obj_table.
+ * @return
+ * - n: Actual number of objects dequeued, 0 if ring is empty
+ */
+int odph_ring_mc_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n);
+
+/**
+ * Dequeue several objects from a ring (NOT multi-consumers safe).When the
+ * request objects are more than the available objects, only dequeue the
+ * actual number of objects
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ * The number of objects to dequeue from the ring to the obj_table.
+ * @return
+ * - n: Actual number of objects dequeued, 0 if ring is empty
+ */
+int odph_ring_sc_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n);
+
+/**
+ * Dequeue multiple objects from a ring up to a maximum number.
+ *
+ * This function calls the multi-consumers or the single-consumer
+ * version, depending on the default behaviour that was specified at
+ * ring creation time (see flags).
+ *
+ * @param r
+ * A pointer to the ring structure.
+ * @param obj_table
+ * A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ * The number of objects to dequeue from the ring to the obj_table.
+ * @return
+ * - Number of objects dequeued, or a negative error code on error
+ */
+int odph_ring_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n);
+
+/**
+ * dump the status of all rings on the console
+ */
+void odph_ring_list_dump(void);
+
+/**
+ * initialise ring tailq
+ */
+void odph_ring_tailq_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/helper/include/odph_udp.h b/helper/include/odph_udp.h
new file mode 100644
index 0000000..3970f00
--- /dev/null
+++ b/helper/include/odph_udp.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP UDP header
+ */
+
+#ifndef ODPH_UDP_H_
+#define ODPH_UDP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_align.h>
+#include <odp_debug.h>
+#include <odp_byteorder.h>
+
+/** UDP header length */
+#define ODPH_UDPHDR_LEN 8
+
+/** UDP header */
+typedef struct ODPH_PACKED {
+ uint16be_t src_port; /**< Source port */
+ uint16be_t dst_port; /**< Destination port */
+ uint16be_t length; /**< UDP datagram length in bytes (header+data) */
+ uint16be_t chksum; /**< UDP header and data checksum (0 if not used)*/
+} odph_udphdr_t;
+
+/** UDP pseudo header */
+typedef struct ODPH_PACKET {
+ uint32be_t src_addr; /**< Source addr */
+ uint32be_t dst_addr; /**< Destination addr */
+ uint8_t pad; /**< pad byte */
+ uint8_t proto; /**< UDP protocol */
+ uint16be_t length; /**< data length */
+} odph_udpphdr_t;
+
+/**
+ * UDP checksum
+ *
+ * This function uses odp packet to calc checksum
+ *
+ * @param pkt calculate chksum for pkt
+ * @return checksum value
+ */
+static inline uint16_t odph_ipv4_udp_chksum(odp_packet_t pkt)
+{
+ uint32_t sum = 0;
+ odph_udpphdr_t phdr;
+ odph_udphdr_t *udph;
+ odph_ipv4hdr_t *iph;
+ uint16_t udplen;
+
+ if (!odp_packet_l3_offset(pkt))
+ return 0;
+
+ if (!odp_packet_l4_offset(pkt))
+ return 0;
+
+ iph = (odph_ipv4hdr_t *)odp_packet_l3(pkt);
+ udph = (odph_udphdr_t *)odp_packet_l4(pkt);
+ udplen = odp_be_to_cpu_16(udph->length);
+
+ /* the source ip */
+ phdr.src_addr = iph->src_addr;
+ /* the dest ip */
+ phdr.dst_addr = iph->dst_addr;
+ /* proto */
+ phdr.pad = 0;
+ phdr.proto = ODPH_IPPROTO_UDP;
+ /* the length */
+ phdr.length = udph->length;
+
+ /* calc UDP pseudo header chksum */
+ sum = (__odp_force uint32_t) odp_chksum(&phdr, sizeof(odph_udpphdr_t));
+ /* calc udp header and data chksum */
+ sum += (__odp_force uint32_t) odp_chksum(udph, udplen);
+
+ /* Fold sum to 16 bits: add carrier to result */
+ while (sum >> 16)
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ /* set computation result */
+ sum = (sum == 0x0) ? 0xFFFF : sum;
+
+ return sum;
+}
+
+/** @internal Compile time assert */
+ODP_STATIC_ASSERT(sizeof(odph_udphdr_t) == ODPH_UDPHDR_LEN, "ODPH_UDPHDR_T__SIZE_ERROR");
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif