diff options
author | Anders Roxell <anders.roxell@linaro.org> | 2014-09-02 20:38:00 +0200 |
---|---|---|
committer | Maxim Uvarov <maxim.uvarov@linaro.org> | 2014-09-02 22:56:11 +0400 |
commit | 8deea2005ad3f42eb5987171e0b3b1a428aac057 (patch) | |
tree | 43a49b97376396ff77ce13b486607c98ca4565cf /helper | |
parent | 8e1bf298be449b8f91f25b96870732c433f4ddc0 (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.h | 53 | ||||
-rw-r--r-- | helper/include/odph_eth.h | 87 | ||||
-rw-r--r-- | helper/include/odph_icmp.h | 99 | ||||
-rw-r--r-- | helper/include/odph_ip.h | 156 | ||||
-rw-r--r-- | helper/include/odph_linux.h | 68 | ||||
-rw-r--r-- | helper/include/odph_packet.h | 97 | ||||
-rw-r--r-- | helper/include/odph_ring.h | 577 | ||||
-rw-r--r-- | helper/include/odph_udp.h | 102 |
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 |