aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--arch/linux-generic/source/odp_packet.c7
-rw-r--r--arch/linux-generic/source/odp_packet_internal.h15
-rw-r--r--arch/linux-generic/source/odp_packet_io.c283
-rw-r--r--arch/linux-generic/source/odp_packet_io_internal.h66
-rw-r--r--arch/linux-generic/source/odp_packet_io_queue.h61
-rw-r--r--arch/linux-generic/source/odp_packet_socket.c12
-rw-r--r--arch/linux-generic/source/odp_queue.c162
-rw-r--r--arch/linux-generic/source/odp_queue_internal.h96
-rw-r--r--arch/linux-generic/source/odp_schedule.c3
-rw-r--r--arch/linux-generic/source/odp_spinlock.c13
-rw-r--r--include/odp.h4
-rw-r--r--include/odp_config.h5
-rw-r--r--include/odp_packet.h3
-rw-r--r--include/odp_packet_io.h53
-rw-r--r--include/odp_queue.h12
-rw-r--r--include/odp_spinlock.h5
-rw-r--r--test/packet/odp_example_pktio.c179
18 files changed, 791 insertions, 195 deletions
diff --git a/.gitignore b/.gitignore
index 24a9392b7..334234395 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,5 +2,8 @@
*.d
*~
lib/
-test/odp_app
-
+obj/
+test/example/odp_example
+test/packet/odp_packet
+test/api_test/odp_atomic
+test/api_test/odp_shm
diff --git a/arch/linux-generic/source/odp_packet.c b/arch/linux-generic/source/odp_packet.c
index 6b0443148..88ba84c8f 100644
--- a/arch/linux-generic/source/odp_packet.c
+++ b/arch/linux-generic/source/odp_packet.c
@@ -44,6 +44,11 @@ odp_packet_t odp_packet_from_buffer(odp_buffer_t buf)
return (odp_packet_t)buf;
}
+odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt)
+{
+ return (odp_buffer_t)pkt;
+}
+
void odp_packet_set_len(odp_packet_t pkt, size_t len)
{
odp_packet_hdr(pkt)->frame_len = len;
@@ -56,7 +61,7 @@ size_t odp_packet_get_len(odp_packet_t pkt)
uint8_t *odp_packet_payload(odp_packet_t pkt)
{
- return odp_packet_hdr(pkt)->payload;
+ return odp_buffer_addr(odp_buffer_from_packet(pkt));
}
void odp_packet_print(odp_packet_t pkt)
diff --git a/arch/linux-generic/source/odp_packet_internal.h b/arch/linux-generic/source/odp_packet_internal.h
index e4496dcdc..f678f0993 100644
--- a/arch/linux-generic/source/odp_packet_internal.h
+++ b/arch/linux-generic/source/odp_packet_internal.h
@@ -42,9 +42,9 @@
extern "C" {
#endif
-
-#include <odp_packet.h>
#include <odp_buffer_internal.h>
+#include <odp_packet.h>
+#include <odp_packet_io.h>
typedef struct odp_packet_hdr_t {
@@ -56,6 +56,11 @@ typedef struct odp_packet_hdr_t {
size_t l4_offset;
size_t frame_len;
+ odp_pktio_t input;
+ /* @TODO: pad needed to ensure that
+ * sizeof(odp_packet_hdr_t) == offsetof(odp_packet_hdr_t, payload)
+ */
+ int pad;
/*
size_t head_room;
@@ -75,12 +80,6 @@ static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt)
return (odp_packet_hdr_t *)odp_buf_to_hdr((odp_buffer_t)pkt);
}
-static inline struct odp_packet_hdr_t *odp_packet_payload_to_hdr(uint8_t *pload)
-{
- return (struct odp_packet_hdr_t *)
- ((size_t)pload - offsetof(struct odp_packet_hdr_t, payload));
-}
-
#ifdef __cplusplus
}
diff --git a/arch/linux-generic/source/odp_packet_io.c b/arch/linux-generic/source/odp_packet_io.c
index 633231e57..066b8a735 100644
--- a/arch/linux-generic/source/odp_packet_io.c
+++ b/arch/linux-generic/source/odp_packet_io.c
@@ -28,34 +28,51 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-
#include <odp_packet_io.h>
+#include <odp_packet_io_internal.h>
+#include <odp_packet_io_queue.h>
+#include <odp_packet.h>
+#include <odp_packet_internal.h>
#include <odp_internal.h>
#include <odp_spinlock.h>
#include <odp_shared_memory.h>
#include <odp_packet_socket.h>
+#include <odp_hints.h>
+#include <odp_config.h>
+#include <odp_queue_internal.h>
+#include <odp_schedule_internal.h>
#include <string.h>
#include <stdio.h>
-#define ODP_CONFIG_PKTIO_ENTRIES 512
-
-typedef struct {
- pkt_sock_t pkt_sock; /**< using socket API for IO */
- int taken; /**< is entry taken(1) or free(0) */
-} pktio_entry_t;
+ODP_ASSERT(sizeof(odp_packet_hdr_t) == offsetof(odp_packet_hdr_t, payload),
+ ODP_PACKET_HEADER_T__SIZE_ERROR);
typedef struct {
- odp_spinlock_t tbl_lock;
- pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES] ODP_ALIGNED_CACHE;
+ pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
} pktio_table_t;
static pktio_table_t *pktio_tbl;
+static pktio_entry_t *get_entry(odp_pktio_t id)
+{
+ if (odp_unlikely(id == ODP_PKTIO_INVALID ||
+ id > ODP_CONFIG_PKTIO_ENTRIES))
+ return NULL;
+
+ return &pktio_tbl->entries[id - 1];
+}
+
int odp_pktio_init_global(void)
{
+ char name[ODP_QUEUE_NAME_LEN];
+ pktio_entry_t *pktio_entry;
+ queue_entry_t *queue_entry;
+ odp_queue_t qid;
+ int id;
+
pktio_tbl = odp_shm_reserve("odp_pktio_entries",
sizeof(pktio_table_t),
sizeof(pktio_entry_t));
@@ -64,7 +81,23 @@ int odp_pktio_init_global(void)
memset(pktio_tbl, 0, sizeof(pktio_table_t));
- odp_spinlock_init(&pktio_tbl->tbl_lock);
+ for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
+ pktio_entry = get_entry(id);
+
+ odp_spinlock_init(&pktio_entry->s.lock);
+
+ /* Create a default output queue for each pktio resource */
+ snprintf(name, sizeof(name), "%i-pktio_outq_default", (int)id);
+ name[ODP_QUEUE_NAME_LEN-1] = '\0';
+
+ qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, NULL);
+ if (qid == ODP_QUEUE_INVALID)
+ return -1;
+ pktio_entry->s.outq_default = qid;
+
+ queue_entry = get_qentry(from_qhandle(qid));
+ queue_entry->s.pktout = id;
+ }
return 0;
}
@@ -76,122 +109,262 @@ int odp_pktio_init_local(void)
static int is_free(pktio_entry_t *entry)
{
- return (entry->taken == 0);
+ return (entry->s.taken == 0);
}
static void set_free(pktio_entry_t *entry)
{
- entry->taken = 0;
+ entry->s.taken = 0;
}
static void set_taken(pktio_entry_t *entry)
{
- entry->taken = 1;
+ entry->s.taken = 1;
+}
+
+static void lock_entry(pktio_entry_t *entry)
+{
+ odp_spinlock_lock(&entry->s.lock);
+}
+
+static void unlock_entry(pktio_entry_t *entry)
+{
+ odp_spinlock_unlock(&entry->s.lock);
}
static void init_pktio_entry(pktio_entry_t *entry)
{
- memset(&entry->pkt_sock, 0, sizeof(entry->pkt_sock));
set_taken(entry);
+ entry->s.inq_default = ODP_QUEUE_INVALID;
+ memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock));
}
-static odp_pktio_t alloc_pktio_entry(void)
+static odp_pktio_t alloc_lock_pktio_entry(void)
{
- odp_pktio_t id = ODP_PKTIO_INVALID;
+ odp_pktio_t id;
+ pktio_entry_t *entry;
int i;
- odp_spinlock_lock(&pktio_tbl->tbl_lock);
-
for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
- if (is_free(&pktio_tbl->entries[i])) {
- init_pktio_entry(&pktio_tbl->entries[i]);
- id = i + 1;
- break;
+ entry = &pktio_tbl->entries[i];
+ if (is_free(entry)) {
+ lock_entry(entry);
+ if (is_free(entry)) {
+ init_pktio_entry(entry);
+ id = i + 1;
+ return id; /* return with entry locked! */
+ }
+ unlock_entry(entry);
}
}
- odp_spinlock_unlock(&pktio_tbl->tbl_lock);
-
- return id;
+ return ODP_PKTIO_INVALID;
}
static int free_pktio_entry(odp_pktio_t id)
{
- int i;
+ pktio_entry_t *entry = get_entry(id);
- if (id == ODP_PKTIO_INVALID || id > ODP_CONFIG_PKTIO_ENTRIES)
+ if (entry == NULL)
return -1;
- i = id - 1;
-
- odp_spinlock_lock(&pktio_tbl->tbl_lock);
-
- set_free(&pktio_tbl->entries[i]);
-
- odp_spinlock_unlock(&pktio_tbl->tbl_lock);
+ set_free(entry);
return 0;
}
-static pktio_entry_t *get_entry(odp_pktio_t id)
-{
- if (id == ODP_PKTIO_INVALID || id > ODP_CONFIG_PKTIO_ENTRIES)
- return NULL;
-
- return &pktio_tbl->entries[id - 1];
-}
-
odp_pktio_t odp_pktio_open(char *dev, odp_buffer_pool_t pool)
{
odp_pktio_t id;
pktio_entry_t *pktio_entry;
int res;
- id = alloc_pktio_entry();
+ id = alloc_lock_pktio_entry();
if (id == ODP_PKTIO_INVALID) {
fprintf(stderr, "%s(): No resources available.\n", __func__);
return ODP_PKTIO_INVALID;
}
+ /* iff successful, alloc_pktio_entry() returns with the entry locked */
pktio_entry = get_entry(id);
- if (pktio_entry == NULL)
- return ODP_PKTIO_INVALID;
- res = setup_pkt_sock(&pktio_entry->pkt_sock, dev, pool);
- if (res == -1)
- return ODP_PKTIO_INVALID;
+ res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, pool);
+ if (res == -1) {
+ close_pkt_sock(&pktio_entry->s.pkt_sock);
+ free_pktio_entry(id);
+ id = ODP_PKTIO_INVALID;
+ }
+ unlock_entry(pktio_entry);
return id;
}
int odp_pktio_close(odp_pktio_t id)
{
- pktio_entry_t *pktio_entry;
+ pktio_entry_t *entry;
int res;
- pktio_entry = get_entry(id);
- if (pktio_entry == NULL)
+ entry = get_entry(id);
+ if (entry == NULL)
return -1;
- res = close_pkt_sock(&pktio_entry->pkt_sock);
- res |= free_pktio_entry(id);
+ lock_entry(entry);
+ if (!is_free(entry)) {
+ res = close_pkt_sock(&entry->s.pkt_sock);
+ res |= free_pktio_entry(id);
+ }
+ unlock_entry(entry);
+
if (res != 0)
return -1;
return 0;
}
+void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio)
+{
+ odp_packet_hdr(pkt)->input = pktio;
+}
+
+odp_pktio_t odp_pktio_get_input(odp_packet_t pkt)
+{
+ return odp_packet_hdr(pkt)->input;
+}
+
int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
{
pktio_entry_t *pktio_entry = get_entry(id);
+ int pkts;
+ int i;
- return recv_pkt_sock(&pktio_entry->pkt_sock, pkt_table, len);
+ if (pktio_entry == NULL)
+ return -1;
+
+ lock_entry(pktio_entry);
+ pkts = recv_pkt_sock(&pktio_entry->s.pkt_sock, pkt_table, len);
+ unlock_entry(pktio_entry);
+ for (i = 0; i < pkts; ++i)
+ odp_pktio_set_input(pkt_table[i], id);
+
+ return pkts;
}
int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
{
pktio_entry_t *pktio_entry = get_entry(id);
+ int sent_pkts;
+
+ if (pktio_entry == NULL)
+ return -1;
+
+ lock_entry(pktio_entry);
+ sent_pkts = send_pkt_sock(&pktio_entry->s.pkt_sock, pkt_table, len);
+ unlock_entry(pktio_entry);
+
+ return sent_pkts;
+}
+
+int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue)
+{
+ pktio_entry_t *pktio_entry = get_entry(id);
+ queue_entry_t *qentry = get_qentry(from_qhandle(queue));
+
+ if (pktio_entry == NULL || qentry == NULL)
+ return -1;
+
+ if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN)
+ return -1;
+
+ lock_entry(pktio_entry);
+ pktio_entry->s.inq_default = queue;
+ unlock_entry(pktio_entry);
+
+ odp_spinlock_lock(&qentry->s.lock);
+ qentry->s.pktin = id;
+ qentry->s.status = QUEUE_STATUS_SCHED;
+ odp_spinlock_unlock(&qentry->s.lock);
+
+ odp_schedule_queue(queue, qentry->s.param.sched.prio);
+
+ return 0;
+}
+
+int odp_pktio_inq_remdef(odp_pktio_t id)
+{
+ return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID);
+}
+
+odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
+{
+ pktio_entry_t *pktio_entry = get_entry(id);
+
+ if (pktio_entry == NULL)
+ return ODP_QUEUE_INVALID;
+
+ return pktio_entry->s.inq_default;
+}
+
+odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
+{
+ pktio_entry_t *pktio_entry = get_entry(id);
+
+ if (pktio_entry == NULL)
+ return ODP_QUEUE_INVALID;
+
+ return pktio_entry->s.outq_default;
+}
+
+int pktout_enqueue(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
+{
+ odp_packet_t pkt = odp_packet_from_buffer(buf_hdr->handle.handle);
+ int len = 1;
+ int nbr;
+
+ nbr = odp_pktio_send(queue->s.pktout, &pkt, len);
+ return (nbr == len ? 0 : -1);
+}
+
+odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *queue)
+{
+ (void)queue;
+ return NULL;
+}
+
+int pktin_enqueue(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
+{
+ /* Use default action */
+ return queue_enq(queue, buf_hdr);
+}
+
+odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
+{
+ odp_buffer_hdr_t *buf_hdr;
+
+ buf_hdr = queue_deq(qentry);
+
+ if (buf_hdr == NULL) {
+ odp_packet_t pkt;
+ odp_buffer_t buf;
+ odp_buffer_hdr_t *tmp_hdr;
+ odp_packet_t pkt_tbl[ODP_PKTIN_QUEUE_MAX_BURST];
+ int pkts, i;
+
+ pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
+ ODP_PKTIN_QUEUE_MAX_BURST);
+
+ if (pkts > 0) {
+ pkt = pkt_tbl[0];
+ buf = odp_buffer_from_packet(pkt);
+ buf_hdr = odp_buf_to_hdr(buf);
+
+ for (i = 1; i < pkts; ++i) {
+ buf = odp_buffer_from_packet(pkt_tbl[i]);
+ tmp_hdr = odp_buf_to_hdr(buf);
+ queue_enq(qentry, tmp_hdr);
+ }
+ }
+ }
- return send_pkt_sock(&pktio_entry->pkt_sock, pkt_table, len);
+ return buf_hdr;
}
diff --git a/arch/linux-generic/source/odp_packet_io_internal.h b/arch/linux-generic/source/odp_packet_io_internal.h
new file mode 100644
index 000000000..2328e187a
--- /dev/null
+++ b/arch/linux-generic/source/odp_packet_io_internal.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2013, Linaro Limited
+ * 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 Linaro Limited 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 HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIALDAMAGES (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.
+ */
+
+
+/**
+ * @file
+ *
+ * ODP packet IO - implementation internal
+ */
+
+#ifndef ODP_PACKET_IO_INTERNAL_H_
+#define ODP_PACKET_IO_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_spinlock.h>
+#include <odp_packet_socket.h>
+
+struct pktio_entry {
+ odp_spinlock_t lock; /**< entry spinlock */
+ int taken; /**< is entry taken(1) or free(0) */
+ odp_queue_t inq_default; /**< default input queue, if set */
+ odp_queue_t outq_default; /**< default out queue */
+ pkt_sock_t pkt_sock; /**< using socket API for IO */
+};
+
+typedef union {
+ struct pktio_entry s;
+ uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct pktio_entry))];
+} pktio_entry_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/arch/linux-generic/source/odp_packet_io_queue.h b/arch/linux-generic/source/odp_packet_io_queue.h
new file mode 100644
index 000000000..f425cdf37
--- /dev/null
+++ b/arch/linux-generic/source/odp_packet_io_queue.h
@@ -0,0 +1,61 @@
+/* Copyright (c) 2013, Linaro Limited
+ * 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 Linaro Limited 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 HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIALDAMAGES (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.
+ */
+
+
+/**
+ * @file
+ *
+ * ODP packet IO - implementation internal
+ */
+
+#ifndef ODP_PACKET_IO_QUEUE_H_
+#define ODP_PACKET_IO_QUEUE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_queue_internal.h>
+#include <odp_buffer_internal.h>
+
+#define ODP_PKTIN_QUEUE_MAX_BURST 16
+
+int pktin_enqueue(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr);
+odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *queue);
+
+int pktout_enqueue(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr);
+odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *queue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/arch/linux-generic/source/odp_packet_socket.c b/arch/linux-generic/source/odp_packet_socket.c
index cc33bb05c..61a1e3d12 100644
--- a/arch/linux-generic/source/odp_packet_socket.c
+++ b/arch/linux-generic/source/odp_packet_socket.c
@@ -243,11 +243,13 @@ int recv_pkt_sock(pkt_sock_t * const pkt_sock,
socklen_t addrlen = sizeof(sll);
int const sockfd = pkt_sock->sockfd;
odp_packet_t pkt = ODP_PACKET_INVALID;
+ odp_buffer_t buf;
int nb_rx = 0;
for (i = 0; i < len; i++) {
if (odp_likely(pkt == ODP_PACKET_INVALID)) {
- pkt = (odp_packet_t) odp_buffer_alloc(pkt_sock->pool);
+ buf = odp_buffer_alloc(pkt_sock->pool);
+ pkt = odp_packet_from_buffer(buf);
if (odp_unlikely(pkt == ODP_PACKET_INVALID))
break;
}
@@ -329,6 +331,7 @@ int recv_pkt_sock(pkt_sock_t * const pkt_sock,
int msgvec_len;
struct mmsghdr msgvec[ODP_PACKET_SOCKET_MAX_BURST_RX];
struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_RX];
+ odp_buffer_t buf;
int nb_rx = 0;
int recv_msgs;
int i;
@@ -339,7 +342,8 @@ int recv_pkt_sock(pkt_sock_t * const pkt_sock,
memset(msgvec, 0, sizeof(msgvec));
for (i = 0; i < (int)len; i++) {
- pkt_table[i] = (odp_packet_t) odp_buffer_alloc(pkt_sock->pool);
+ buf = odp_buffer_alloc(pkt_sock->pool);
+ pkt_table[i] = odp_packet_from_buffer(buf);
if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID))
break;
iovecs[i].iov_base = odp_packet_payload(pkt_table[i]);
@@ -488,6 +492,7 @@ static unsigned pkt_mmap_v2_rx(int sock, struct ring *ring,
unsigned frame_num, next_frame_num;
uint8_t *pkt;
int pkt_len;
+ odp_buffer_t buf;
unsigned i = 0;
(void)sock;
@@ -503,7 +508,8 @@ static unsigned pkt_mmap_v2_rx(int sock, struct ring *ring,
pkt = (uint8_t *)ppd.raw + ppd.v2->tp_h.tp_mac;
pkt_len = ppd.v2->tp_h.tp_snaplen;
- pkt_table[i] = (odp_packet_t)odp_buffer_alloc(pool);
+ buf = odp_buffer_alloc(pool);
+ pkt_table[i] = odp_packet_from_buffer(buf);
if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID))
break;
diff --git a/arch/linux-generic/source/odp_queue.c b/arch/linux-generic/source/odp_queue.c
index 27f53ba56..578350d85 100644
--- a/arch/linux-generic/source/odp_queue.c
+++ b/arch/linux-generic/source/odp_queue.c
@@ -29,86 +29,47 @@
*/
-
-
+#include <odp_queue.h>
+#include <odp_queue_internal.h>
#include <odp_std_types.h>
#include <odp_align.h>
#include <odp_buffer.h>
#include <odp_buffer_internal.h>
#include <odp_internal.h>
-#include <odp_queue.h>
#include <odp_shared_memory.h>
#include <odp_spinlock.h>
#include <odp_schedule_internal.h>
#include <odp_config.h>
+#include <odp_packet_io_internal.h>
+#include <odp_packet_io_queue.h>
#include <stdio.h>
#include <string.h>
-#define QUEUE_STATUS_FREE 0
-#define QUEUE_STATUS_INIT 1
-#define QUEUE_STATUS_READY 2
-#define QUEUE_STATUS_NOTSCHED 3
-#define QUEUE_STATUS_SCHED 4
-
-/* forward declaration */
-union queue_entry_u;
-
-struct queue_entry_s {
- odp_spinlock_t lock;
- int (*enqueue)(union queue_entry_u *, odp_buffer_hdr_t *);
- odp_buffer_hdr_t *(*dequeue)(union queue_entry_u *);
- odp_buffer_hdr_t *head;
- odp_buffer_hdr_t *tail;
- odp_queue_t handle;
- odp_queue_type_t type;
- int status;
- odp_queue_param_t param;
- char name[ODP_QUEUE_NAME_LEN];
-};
-
-
-typedef union queue_entry_u {
- struct queue_entry_s s;
-
- uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct queue_entry_s))];
-
-} queue_entry_t;
-
-
typedef struct queue_table_t {
queue_entry_t queue[ODP_CONFIG_QUEUES];
-
} queue_table_t;
-
static queue_table_t *queue_tbl;
-/* local function prototypes */
-static int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr);
-static odp_buffer_hdr_t *queue_deq(queue_entry_t *queue);
-
-
-static inline queue_entry_t *get_queue(uint32_t queue_id)
+queue_entry_t *get_qentry(uint32_t queue_id)
{
return &queue_tbl->queue[queue_id];
}
-
-static inline odp_queue_t to_handle(uint32_t queue_id)
+odp_queue_t to_qhandle(uint32_t queue_id)
{
return queue_id + 1;
}
-static inline uint32_t from_handle(odp_queue_t handle)
+uint32_t from_qhandle(odp_queue_t handle)
{
return handle - 1;
}
-
static void queue_init(queue_entry_t *queue, const char *name,
odp_queue_type_t type, odp_queue_param_t *param)
{
@@ -125,8 +86,20 @@ static void queue_init(queue_entry_t *queue, const char *name,
queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT;
}
- queue->s.enqueue = queue_enq;
- queue->s.dequeue = queue_deq;
+ switch (type) {
+ case ODP_QUEUE_TYPE_PKTIN:
+ queue->s.enqueue = pktin_enqueue;
+ queue->s.dequeue = pktin_dequeue;
+ break;
+ case ODP_QUEUE_TYPE_PKTOUT:
+ queue->s.enqueue = pktout_enqueue;
+ queue->s.dequeue = pktout_dequeue;
+ break;
+ default:
+ queue->s.enqueue = queue_enq;
+ queue->s.dequeue = queue_deq;
+ break;
+ }
queue->s.head = NULL;
queue->s.tail = NULL;
@@ -150,10 +123,10 @@ int odp_queue_init_global(void)
for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
/* init locks */
- queue_entry_t *queue = get_queue(i);
+ queue_entry_t *queue = get_qentry(i);
odp_spinlock_init(&queue->s.lock);
- queue->s.handle = to_handle(i);
+ queue->s.handle = to_qhandle(i);
}
printf("done\n");
@@ -166,6 +139,16 @@ int odp_queue_init_global(void)
return 0;
}
+odp_queue_type_t odp_queue_type(odp_queue_t handle)
+{
+ queue_entry_t *queue;
+ uint32_t queue_id;
+
+ queue_id = from_qhandle(handle);
+ queue = get_qentry(queue_id);
+
+ return queue->s.type;
+}
odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
odp_queue_param_t *param)
@@ -182,16 +165,15 @@ odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
odp_spinlock_lock(&queue->s.lock);
if (queue->s.status == QUEUE_STATUS_FREE) {
- queue->s.status = QUEUE_STATUS_INIT;
- odp_spinlock_unlock(&queue->s.lock);
queue_init(queue, name, type, param);
-
- if (type == ODP_QUEUE_TYPE_SCHED)
+ if (type == ODP_QUEUE_TYPE_SCHED ||
+ type == ODP_QUEUE_TYPE_PKTIN)
queue->s.status = QUEUE_STATUS_NOTSCHED;
else
queue->s.status = QUEUE_STATUS_READY;
handle = queue->s.handle;
+ odp_spinlock_unlock(&queue->s.lock);
break;
}
@@ -229,8 +211,12 @@ odp_queue_t odp_queue_lookup(const char *name)
-static int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
+int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
{
+ int sched = 0;
+
+ odp_spinlock_lock(&queue->s.lock);
+
if (queue->s.head == NULL) {
/* Empty queue */
queue->s.head = buf_hdr;
@@ -242,6 +228,17 @@ static int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
buf_hdr->next = NULL;
}
+ if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
+ queue->s.status = QUEUE_STATUS_SCHED;
+ sched = 1; /* retval: schedule queue */
+ }
+
+ odp_spinlock_unlock(&queue->s.lock);
+
+ /* Add queue to scheduling */
+ if (sched == 1)
+ odp_schedule_queue(queue->s.handle, queue->s.param.sched.prio);
+
return 0;
}
@@ -251,51 +248,38 @@ int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf)
odp_buffer_hdr_t *buf_hdr;
queue_entry_t *queue;
uint32_t queue_id;
- int sched = 0;
- queue_id = from_handle(handle);
- queue = get_queue(queue_id);
+ queue_id = from_qhandle(handle);
+ queue = get_qentry(queue_id);
buf_hdr = odp_buf_to_hdr(buf);
- odp_spinlock_lock(&queue->s.lock);
- queue->s.enqueue(queue, buf_hdr);
-
- if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
- queue->s.status = QUEUE_STATUS_SCHED;
- sched = 1;
- }
-
- odp_spinlock_unlock(&queue->s.lock);
-
- /* Add queue to scheduling */
- if (sched)
- odp_schedule_queue(handle, queue->s.param.sched.prio);
-
- return 0;
+ return queue->s.enqueue(queue, buf_hdr);
}
-static odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
+odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
{
- odp_buffer_hdr_t *buf_hdr;
+ odp_buffer_hdr_t *buf_hdr = NULL;
+
+ odp_spinlock_lock(&queue->s.lock);
if (queue->s.head == NULL) {
/* Already empty queue */
- if (queue->s.status == QUEUE_STATUS_SCHED)
+ if (queue->s.status == QUEUE_STATUS_SCHED &&
+ queue->s.type != ODP_QUEUE_TYPE_PKTIN)
queue->s.status = QUEUE_STATUS_NOTSCHED;
+ } else {
+ buf_hdr = queue->s.head;
+ queue->s.head = buf_hdr->next;
+ buf_hdr->next = NULL;
- return NULL;
+ if (queue->s.head == NULL) {
+ /* Queue is now empty */
+ queue->s.tail = NULL;
+ }
}
-
- buf_hdr = queue->s.head;
- queue->s.head = buf_hdr->next;
- buf_hdr->next = NULL;
-
- if (queue->s.head == NULL) {
- /* Queue is now empty */
- queue->s.tail = NULL;
- }
+ odp_spinlock_unlock(&queue->s.lock);
return buf_hdr;
}
@@ -307,12 +291,10 @@ odp_buffer_t odp_queue_deq(odp_queue_t handle)
uint32_t queue_id;
odp_buffer_hdr_t *buf_hdr;
- queue_id = from_handle(handle);
- queue = get_queue(queue_id);
+ queue_id = from_qhandle(handle);
+ queue = get_qentry(queue_id);
- odp_spinlock_lock(&queue->s.lock);
buf_hdr = queue->s.dequeue(queue);
- odp_spinlock_unlock(&queue->s.lock);
if (buf_hdr)
return buf_hdr->handle.handle;
diff --git a/arch/linux-generic/source/odp_queue_internal.h b/arch/linux-generic/source/odp_queue_internal.h
new file mode 100644
index 000000000..76fd239da
--- /dev/null
+++ b/arch/linux-generic/source/odp_queue_internal.h
@@ -0,0 +1,96 @@
+/* Copyright (c) 2013, Linaro Limited
+ * 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 Linaro Limited 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 HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIALDAMAGES (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.
+ */
+
+
+/**
+ * @file
+ *
+ * ODP queue - implementation internal
+ */
+
+#ifndef ODP_QUEUE_INTERNAL_H_
+#define ODP_QUEUE_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_queue.h>
+#include <odp_buffer_internal.h>
+#include <odp_packet_io.h>
+#include <odp_spinlock.h>
+#include <odp_align.h>
+
+#define QUEUE_STATUS_FREE 0
+#define QUEUE_STATUS_READY 1
+#define QUEUE_STATUS_NOTSCHED 2
+#define QUEUE_STATUS_SCHED 3
+
+/* forward declaration */
+union queue_entry_u;
+
+typedef int (*enqueue_func_t)(union queue_entry_u *, odp_buffer_hdr_t *);
+typedef odp_buffer_hdr_t *(*dequeue_func_t)(union queue_entry_u *);
+
+struct queue_entry_s {
+ odp_spinlock_t lock ODP_ALIGNED_CACHE;
+ enqueue_func_t enqueue ODP_ALIGNED_CACHE;
+ dequeue_func_t dequeue;
+ odp_buffer_hdr_t *head;
+ odp_buffer_hdr_t *tail;
+ odp_queue_t handle;
+ odp_queue_type_t type;
+ int status;
+ odp_queue_param_t param;
+ odp_pktio_t pktin;
+ odp_pktio_t pktout;
+ char name[ODP_QUEUE_NAME_LEN];
+};
+
+typedef union queue_entry_u {
+ struct queue_entry_s s;
+ uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct queue_entry_s))];
+} queue_entry_t;
+
+
+queue_entry_t *get_qentry(uint32_t queue_id);
+odp_queue_t to_qhandle(uint32_t queue_id);
+uint32_t from_qhandle(odp_queue_t handle);
+
+/* local function prototypes */
+int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr);
+odp_buffer_hdr_t *queue_deq(queue_entry_t *queue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/arch/linux-generic/source/odp_schedule.c b/arch/linux-generic/source/odp_schedule.c
index 24c61e14b..d0f10af7d 100644
--- a/arch/linux-generic/source/odp_schedule.c
+++ b/arch/linux-generic/source/odp_schedule.c
@@ -153,7 +153,8 @@ odp_buffer_t odp_schedule(void)
queue = desc->queue;
buf = odp_queue_deq(queue);
- if (odp_buffer_is_valid(buf)) {
+ if (odp_buffer_is_valid(buf) ||
+ odp_queue_type(queue) == ODP_QUEUE_TYPE_PKTIN) {
/* Continue scheduling the queue */
odp_queue_enq(pri_queue, desc_buf);
} else {
diff --git a/arch/linux-generic/source/odp_spinlock.c b/arch/linux-generic/source/odp_spinlock.c
index 5523f1132..131329c1c 100644
--- a/arch/linux-generic/source/odp_spinlock.c
+++ b/arch/linux-generic/source/odp_spinlock.c
@@ -29,23 +29,20 @@
*/
-
-
-
#include <odp_spinlock.h>
-
void odp_spinlock_init(odp_spinlock_t *spinlock)
{
- __sync_lock_release(&spinlock->lock);
+ __sync_lock_release(&spinlock->lock);
}
void odp_spinlock_lock(odp_spinlock_t *spinlock)
{
while (__sync_lock_test_and_set(&spinlock->lock, 1))
- ;
+ while (spinlock->lock)
+ ;
}
@@ -57,7 +54,7 @@ int odp_spinlock_trylock(odp_spinlock_t *spinlock)
void odp_spinlock_unlock(odp_spinlock_t *spinlock)
{
- __sync_lock_release(&spinlock->lock);
+ __sync_lock_release(&spinlock->lock);
}
@@ -68,5 +65,3 @@ int odp_spinlock_is_locked(odp_spinlock_t *spinlock)
-
-
diff --git a/include/odp.h b/include/odp.h
index 023b61a0a..758fadb97 100644
--- a/include/odp.h
+++ b/include/odp.h
@@ -306,11 +306,11 @@ extern "C" {
#include <odp_shared_memory.h>
#include <odp_buffer.h>
#include <odp_buffer_pool.h>
-#include <odp_packet.h>
#include <odp_queue.h>
#include <odp_time.h>
#include <odp_schedule.h>
-
+#include <odp_packet.h>
+#include <odp_packet_io.h>
#ifdef __cplusplus
}
diff --git a/include/odp_config.h b/include/odp_config.h
index fdd1ba53c..8e2e4e601 100644
--- a/include/odp_config.h
+++ b/include/odp_config.h
@@ -63,7 +63,10 @@ extern "C" {
*/
#define ODP_CONFIG_SCHED_PRIOS 8
-
+/**
+ * Maximum number of packet IO resources
+ */
+#define ODP_CONFIG_PKTIO_ENTRIES 64
#ifdef __cplusplus
}
diff --git a/include/odp_packet.h b/include/odp_packet.h
index d6fcf8ba2..e01515eb5 100644
--- a/include/odp_packet.h
+++ b/include/odp_packet.h
@@ -42,11 +42,9 @@
extern "C" {
#endif
-
#include <odp_buffer.h>
-
/**
* ODP packet descriptor
*/
@@ -60,6 +58,7 @@ void odp_packet_init(odp_packet_t pkt);
void odp_packet_print(odp_packet_t pkt);
odp_packet_t odp_packet_from_buffer(odp_buffer_t buf);
+odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt);
void odp_packet_set_len(odp_packet_t pkt, size_t len);
size_t odp_packet_get_len(odp_packet_t pkt);
diff --git a/include/odp_packet_io.h b/include/odp_packet_io.h
index be1d6699f..4cb8bc996 100644
--- a/include/odp_packet_io.h
+++ b/include/odp_packet_io.h
@@ -45,6 +45,7 @@ extern "C" {
#include <odp_std_types.h>
#include <odp_buffer_pool.h>
#include <odp_packet.h>
+#include <odp_queue.h>
/** ODP packet IO handle */
typedef int odp_pktio_t;
@@ -91,6 +92,58 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len);
*/
int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len);
+/**
+ * Set the default input queue to be associated with a pktio handle
+ *
+ * @param
+ */
+int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue);
+
+/**
+ * Get default input queue associated with a pktio handle
+ *
+ * @param id ODP packet IO handle
+ *
+ * @return Default input queue set or ODP_QUEUE_INVALID on error
+ */
+odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id);
+
+/**
+ * Remove default input queue (if set)
+ *
+ * @param id ODP packet IO handle
+ *
+ * @return 0 on success or -1 on error
+ */
+int odp_pktio_inq_remdef(odp_pktio_t id);
+
+/**
+ * Query default output queue
+ *
+ * @param id ODP packet IO handle
+ *
+ * @return Default out queue or ODP_QUEUE_INVALID on error
+ */
+odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id);
+
+/**
+ * Store packet input handle into packet
+ *
+ * @param pkt ODP packet buffer handle
+ * @param id ODP packet IO handle
+ *
+ * @return
+ */
+void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t id);
+
+/**
+ * Get stored packet input handle from packet
+ *
+ * @param pkt ODP packet buffer handle
+ *
+ * @return Packet IO handle
+ */
+odp_pktio_t odp_pktio_get_input(odp_packet_t pkt);
#ifdef __cplusplus
}
diff --git a/include/odp_queue.h b/include/odp_queue.h
index 6131543f1..5c89ce653 100644
--- a/include/odp_queue.h
+++ b/include/odp_queue.h
@@ -62,10 +62,10 @@ typedef uint32_t odp_queue_t;
*/
typedef int odp_queue_type_t;
-#define ODP_QUEUE_TYPE_SCHED 0
-#define ODP_QUEUE_TYPE_POLL 1
-#define ODP_QUEUE_TYPE_PKTIN 2
-#define ODP_QUEUE_TYPE_PKTOUT 3
+#define ODP_QUEUE_TYPE_SCHED 0
+#define ODP_QUEUE_TYPE_POLL 1
+#define ODP_QUEUE_TYPE_PKTIN 2
+#define ODP_QUEUE_TYPE_PKTOUT 3
/**
* ODP schedule priority
@@ -148,6 +148,10 @@ int odp_queue_enq(odp_queue_t queue, odp_buffer_t buf);
*/
odp_buffer_t odp_queue_deq(odp_queue_t queue);
+/**
+ *
+ */
+odp_queue_type_t odp_queue_type(odp_queue_t handle);
#ifdef __cplusplus
}
diff --git a/include/odp_spinlock.h b/include/odp_spinlock.h
index c345e4599..ec8a9f30d 100644
--- a/include/odp_spinlock.h
+++ b/include/odp_spinlock.h
@@ -43,17 +43,14 @@ extern "C" {
#endif
-
#include <odp_std_types.h>
-
/**
* ODP spinlock
*/
typedef struct odp_spinlock_t {
- int lock;
-
+ int lock;
} odp_spinlock_t;
diff --git a/test/packet/odp_example_pktio.c b/test/packet/odp_example_pktio.c
index 654df1e9a..c5e7aa19a 100644
--- a/test/packet/odp_example_pktio.c
+++ b/test/packet/odp_example_pktio.c
@@ -38,16 +38,21 @@
#include <string.h>
#include <stdio.h>
#include <getopt.h>
+#include <unistd.h>
#include <odp.h>
#include <odp_linux.h>
-#include <odp_packet_io.h>
#define MAX_WORKERS 32
#define SHM_PKT_POOL_SIZE (512*2048)
#define SHM_PKT_POOL_BUF_SIZE 1856
#define MAX_PKT_BURST 16
+#define APPL_MODE_PKT_BURST 0
+#define APPL_MODE_PKT_QUEUE 1
+
+#define PRINT_APPL_MODE(x) printf("%s(%i)\n", #x, (x))
+
/** Get rid of path in filename - only for unix-type paths using '/' */
#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
strrchr((file_name), '/') + 1 : (file_name))
@@ -57,6 +62,7 @@
typedef struct {
int if_count; /**< Number of interfaces to be used */
char **if_names; /**< Array of pointers to interface names */
+ int mode; /**< Packet IO mode */
odp_buffer_pool_t pool; /**< Buffer pool for packet IO */
} appl_args_t;
@@ -66,6 +72,7 @@ typedef struct {
typedef struct {
char *pktio_dev; /**< Interface name to use */
odp_buffer_pool_t pool; /**< Buffer pool for packet IO */
+ int mode; /**< Thread mode */
} thread_args_t;
/**
@@ -87,18 +94,125 @@ static void print_info(char *progname, appl_args_t *appl_args);
static void usage(char *progname);
/**
- * Packet IO loopback worker thread
+ * Packet IO loopback worker thread using ODP queues
+ *
+ * @param arg thread arguments of type 'thread_args_t *'
+ */
+static void *pktio_queue_thread(void *arg)
+{
+ int thr;
+ odp_buffer_pool_t pkt_pool;
+ odp_pktio_t pktio;
+ thread_args_t *thr_args;
+ odp_queue_t outq_def;
+ odp_queue_t inq_def;
+ char inq_name[ODP_QUEUE_NAME_LEN];
+ odp_queue_param_t qparam;
+ odp_packet_t pkt;
+ odp_buffer_t buf;
+ int ret;
+ unsigned long pkt_cnt = 0;
+
+ thr = odp_thread_id();
+ thr_args = arg;
+
+ printf("Pktio thread [%02i] starts, pktio_dev:%s\n", thr,
+ thr_args->pktio_dev);
+
+ /* Lookup the packet pool */
+ pkt_pool = odp_buffer_pool_lookup("packet_pool");
+ if (pkt_pool == ODP_BUFFER_POOL_INVALID) {
+ fprintf(stderr, " [%02i] Error: pkt_pool not found\n", thr);
+ return NULL;
+ }
+
+ /* Open a packet IO instance for this thread */
+ pktio = odp_pktio_open(thr_args->pktio_dev, thr_args->pool);
+ if (pktio == ODP_PKTIO_INVALID) {
+ fprintf(stderr, " [%02i] Error: pktio create failed\n", thr);
+ return NULL;
+ }
+
+ /*
+ * Create and set the default INPUT queue associated with the 'pktio'
+ * resource
+ */
+ qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
+ qparam.sched.sync = ODP_SCHED_SYNC_NONE;
+ qparam.sched.group = ODP_SCHED_GROUP_DEFAULT;
+ snprintf(inq_name, sizeof(inq_name), "%i-pktio_inq_def", (int)pktio);
+ inq_name[ODP_QUEUE_NAME_LEN - 1] = '\0';
+
+ inq_def = odp_queue_create(inq_name, ODP_QUEUE_TYPE_PKTIN, &qparam);
+ if (inq_def == ODP_QUEUE_INVALID) {
+ fprintf(stderr, " [%02i] Error: pktio queue creation failed\n",
+ thr);
+ return NULL;
+ }
+
+ ret = odp_pktio_inq_setdef(pktio, inq_def);
+ if (ret != 0) {
+ fprintf(stderr, " [%02i] Error: default input-Q setup\n"
+ , thr);
+ return NULL;
+ }
+
+ printf(" [%02i] created pktio:%02i, queue mode\n"
+ " default pktio%02i-INPUT queue:%u\n",
+ thr, pktio, pktio, inq_def);
+
+ /* Loop packets */
+ for (;;) {
+ odp_pktio_t pktio_tmp;
+
+#if 1
+ /* Use schedule to get buf from any input queue */
+ buf = odp_schedule_poll();
+#else
+ /* Always dequeue from the same input queue */
+ buf = odp_queue_deq(inq_def);
+ if (!odp_buffer_is_valid(buf))
+ continue;
+#endif
+
+ pkt = odp_packet_from_buffer(buf);
+ pktio_tmp = odp_pktio_get_input(pkt);
+ outq_def = odp_pktio_outq_getdef(pktio_tmp);
+
+ if (outq_def == ODP_QUEUE_INVALID) {
+ fprintf(stderr, " [%02i] Error: def output-Q query\n",
+ thr);
+ return NULL;
+ }
+
+ /* Enqueue the packet for output */
+ odp_queue_enq(outq_def, buf);
+
+ /* Print packet counts every once in a while */
+ if (odp_unlikely(pkt_cnt++ % 100000 == 0)) {
+ printf(" [%02i] pkt_cnt:%lu\n", thr, pkt_cnt);
+ fflush(NULL);
+ }
+ }
+
+ return arg;
+}
+
+/**
+ * Packet IO loopback worker thread using bursts from/to IO resources
*
* @param arg thread arguments of type 'thread_args_t *'
*/
-static void *pktio_thread(void *arg)
+static void *pktio_ifburst_thread(void *arg)
{
int thr;
odp_buffer_pool_t pkt_pool;
odp_pktio_t pktio;
thread_args_t *thr_args;
int pkts;
- odp_packet_t pkt_table[MAX_PKT_BURST];
+ odp_packet_t pkt_tbl[MAX_PKT_BURST];
+ unsigned long pkt_cnt = 0;
+ unsigned long tmp = 0;
thr = odp_thread_id();
thr_args = arg;
@@ -119,13 +233,25 @@ static void *pktio_thread(void *arg)
fprintf(stderr, " [%02i] Error: pktio create failed.\n", thr);
return NULL;
}
- printf(" [%02i] created pktio:%i\n", thr, pktio);
- /* Packet loopback */
+ printf(" [%02i] created pktio:%02i, burst mode\n",
+ thr, pktio);
+
+ /* Loop packets */
for (;;) {
- pkts = odp_pktio_recv(pktio, pkt_table, MAX_PKT_BURST);
+ pkts = odp_pktio_recv(pktio, pkt_tbl, MAX_PKT_BURST);
if (pkts > 0)
- (void)odp_pktio_send(pktio, pkt_table, pkts);
+ odp_pktio_send(pktio, pkt_tbl, pkts);
+
+ /* Print packet counts every once in a while */
+ tmp += pkts;
+ if (odp_unlikely((tmp >= 100000) || /* OR first print: */
+ ((pkt_cnt == 0) && ((tmp-1) < MAX_PKT_BURST)))) {
+ pkt_cnt += tmp;
+ printf(" [%02i] pkt_cnt:%lu\n", thr, pkt_cnt);
+ fflush(NULL);
+ tmp = 0;
+ }
}
return arg;
@@ -193,14 +319,22 @@ int main(int argc, char *argv[])
/* Create and init worker threads */
memset(thread_tbl, 0, sizeof(thread_tbl));
for (i = 0; i < num_workers; ++i) {
+ void *(*thr_run_func) (void *);
int if_idx = i % args->appl.if_count;
+
args->thread[i].pktio_dev = args->appl.if_names[if_idx];
args->thread[i].pool = pool;
+ args->thread[i].mode = args->appl.mode;
+
+ if (args->appl.mode == APPL_MODE_PKT_BURST)
+ thr_run_func = pktio_ifburst_thread;
+ else /* APPL_MODE_PKT_QUEUE */
+ thr_run_func = pktio_queue_thread;
/*
* Create threads one-by-one instead of all-at-once,
* because each thread might get different arguments
*/
- odp_linux_pthread_create(thread_tbl, 1, i, pktio_thread,
+ odp_linux_pthread_create(thread_tbl, 1, i, thr_run_func,
&args->thread[i]);
}
@@ -228,12 +362,15 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
int i;
static struct option longopts[] = {
{"interface", required_argument, NULL, 'i'}, /* return 'i' */
+ {"mode", required_argument, NULL, 'm'}, /* return 'm' */
{"help", no_argument, NULL, 'h'}, /* return 'h' */
{NULL, 0, NULL, 0}
};
+ appl_args->mode = -1; /* Invalid, must be changed by parsing */
+
while (1) {
- opt = getopt_long(argc, argv, "+i:h", longopts, &long_index);
+ opt = getopt_long(argc, argv, "+i:m:h", longopts, &long_index);
if (opt == -1)
break; /* No more options */
@@ -282,6 +419,14 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
}
break;
+ case 'm':
+ i = atoi(optarg);
+ if (i == 0)
+ appl_args->mode = APPL_MODE_PKT_BURST;
+ else
+ appl_args->mode = APPL_MODE_PKT_QUEUE;
+ break;
+
case 'h':
usage(argv[0]);
exit(EXIT_SUCCESS);
@@ -292,7 +437,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
}
}
- if (appl_args->if_count == 0) {
+ if (appl_args->if_count == 0 || appl_args->mode == -1) {
usage(argv[0]);
exit(EXIT_FAILURE);
}
@@ -326,6 +471,12 @@ static void print_info(char *progname, appl_args_t *appl_args)
progname, appl_args->if_count);
for (i = 0; i < appl_args->if_count; ++i)
printf(" %s", appl_args->if_names[i]);
+ printf("\n"
+ "Mode: ");
+ if (appl_args->mode == APPL_MODE_PKT_BURST)
+ PRINT_APPL_MODE(APPL_MODE_PKT_BURST);
+ else
+ PRINT_APPL_MODE(APPL_MODE_PKT_QUEUE);
printf("\n\n");
fflush(NULL);
}
@@ -337,12 +488,14 @@ static void usage(char *progname)
{
printf("\n"
"Usage: %s OPTIONS\n"
- " E.g. %s -i eth1,eth2,eth3\n"
+ " E.g. %s -i eth1,eth2,eth3 -m 0\n"
"\n"
"OpenDataPlane example application.\n"
"\n"
"Mandatory OPTIONS:\n"
- " -i, --interface Eth interfaces (comma-separated list, no spaces)\n"
+ " -i, --interface Eth interfaces (comma-separated, no spaces)\n"
+ " -m, --mode 0: Burst send&receive packets (no queues)\n"
+ " 1: Send&receive packets through ODP queues.\n"
"\n"
"Optional OPTIONS\n"
" -h, --help Display help and exit.\n"