Added support for new multi-queue pktio API for scheduled
queues.
Signed-off-by: Petri Savolainen <[email protected]>
---
.../linux-generic/include/odp_packet_io_internal.h | 8 +-
.../linux-generic/include/odp_schedule_internal.h | 3 +-
platform/linux-generic/odp_packet_io.c | 136 +++++++++++++--------
platform/linux-generic/odp_schedule.c | 26 ++--
4 files changed, 110 insertions(+), 63 deletions(-)
diff --git a/platform/linux-generic/include/odp_packet_io_internal.h
b/platform/linux-generic/include/odp_packet_io_internal.h
index fdea65e..61bedc9 100644
--- a/platform/linux-generic/include/odp_packet_io_internal.h
+++ b/platform/linux-generic/include/odp_packet_io_internal.h
@@ -35,6 +35,8 @@ extern "C" {
#define PKTIO_NAME_LEN 256
+#define PKTIN_INVALID ((odp_pktin_queue_t) {ODP_PKTIO_INVALID, 0})
+#define PKTOUT_INVALID ((odp_pktout_queue_t) {ODP_PKTIO_INVALID, 0})
/** Determine if a socket read/write error should be reported. Transient errors
* that simply require the caller to retry are ignored, the _send/_recv APIs
@@ -71,7 +73,6 @@ struct pktio_entry {
int taken; /**< is entry taken(1) or free(0) */
int cls_enabled; /**< is classifier enabled */
odp_pktio_t handle; /**< pktio handle */
- odp_queue_t inq_default; /**< default input queue, if set */
odp_queue_t outq_default; /**< default out queue */
union {
pkt_loop_t pkt_loop; /**< Using loopback for IO */
@@ -96,6 +97,9 @@ struct pktio_entry {
/* Storage for queue handles
* Multi-queue support is pktio driver specific */
+ unsigned num_in_queue;
+ unsigned num_out_queue;
+
struct {
odp_queue_t queue;
odp_pktin_queue_t pktin;
@@ -184,7 +188,7 @@ static inline void pktio_cls_enabled_set(pktio_entry_t
*entry, int ena)
entry->s.cls_enabled = ena;
}
-int pktin_poll(pktio_entry_t *entry);
+int pktin_poll(pktio_entry_t *entry, int num_queue, int index[]);
/*
* Dummy single queue implementations of multi-queue API
diff --git a/platform/linux-generic/include/odp_schedule_internal.h
b/platform/linux-generic/include/odp_schedule_internal.h
index 6b301cd..78e16c4 100644
--- a/platform/linux-generic/include/odp_schedule_internal.h
+++ b/platform/linux-generic/include/odp_schedule_internal.h
@@ -23,7 +23,8 @@ extern "C" {
int schedule_queue_init(queue_entry_t *qe);
void schedule_queue_destroy(queue_entry_t *qe);
int schedule_queue(const queue_entry_t *qe);
-int schedule_pktio_start(odp_pktio_t pktio, int prio);
+void schedule_pktio_start(odp_pktio_t pktio, int num_in_queue,
+ int in_queue_idx[], int prio);
void odp_schedule_release_context(void);
#ifdef __cplusplus
diff --git a/platform/linux-generic/odp_packet_io.c
b/platform/linux-generic/odp_packet_io.c
index c8c262b..d625db2 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -128,9 +128,16 @@ static void unlock_entry_classifier(pktio_entry_t *entry)
static void init_pktio_entry(pktio_entry_t *entry)
{
+ int i;
+
set_taken(entry);
pktio_cls_enabled_set(entry, 0);
- entry->s.inq_default = ODP_QUEUE_INVALID;
+
+ for (i = 0; i < PKTIO_MAX_QUEUES; i++) {
+ entry->s.in_queue[i].queue = ODP_QUEUE_INVALID;
+ entry->s.in_queue[i].pktin = PKTIN_INVALID;
+ entry->s.out_queue[i].pktout = PKTOUT_INVALID;
+ }
pktio_classifier_init(entry);
}
@@ -295,6 +302,7 @@ int odp_pktio_close(odp_pktio_t id)
int odp_pktio_start(odp_pktio_t id)
{
pktio_entry_t *entry;
+ odp_pktio_input_mode_t mode;
int res = 0;
entry = get_pktio_entry(id);
@@ -310,8 +318,27 @@ int odp_pktio_start(odp_pktio_t id)
res = entry->s.ops->start(entry);
if (!res)
entry->s.state = STATE_START;
+
unlock_entry(entry);
+ mode = entry->s.param.in_mode;
+
+ if (mode == ODP_PKTIN_MODE_SCHED) {
+ unsigned i;
+
+ for (i = 0; i < entry->s.num_in_queue; i++) {
+ int index = i;
+
+ if (entry->s.in_queue[i].queue == ODP_QUEUE_INVALID) {
+ ODP_ERR("No input queue\n");
+ return -1;
+ }
+
+ schedule_pktio_start(id, 1, &index,
+ ODP_SCHED_PRIO_LOWEST);
+ }
+ }
+
return res;
}
@@ -445,30 +472,18 @@ int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t
queue)
unlock_entry(pktio_entry);
return -1;
}
- pktio_entry->s.inq_default = queue;
+
+ /* Temporary support for default input queue */
+ pktio_entry->s.in_queue[0].queue = queue;
+ pktio_entry->s.in_queue[0].pktin.pktio = id;
+ pktio_entry->s.in_queue[0].pktin.index = 0;
+ pktio_entry->s.num_in_queue = 1;
unlock_entry(pktio_entry);
- switch (qentry->s.type) {
- /* Change to ODP_QUEUE_TYPE_POLL when ODP_QUEUE_TYPE_PKTIN is removed */
- case ODP_QUEUE_TYPE_PKTIN:
- /* User polls the input queue */
- queue_lock(qentry);
- qentry->s.pktin = id;
- queue_unlock(qentry);
-
- /* Uncomment when ODP_QUEUE_TYPE_PKTIN is removed
- break;
- case ODP_QUEUE_TYPE_SCHED:
- */
- /* Packet input through the scheduler */
- if (schedule_pktio_start(id, ODP_SCHED_PRIO_LOWEST)) {
- ODP_ERR("Schedule pktio start failed\n");
- return -1;
- }
- break;
- default:
- ODP_ABORT("Bad queue type\n");
- }
+ /* User polls the input queue */
+ queue_lock(qentry);
+ qentry->s.pktin = id;
+ queue_unlock(qentry);
return 0;
}
@@ -487,14 +502,19 @@ int odp_pktio_inq_remdef(odp_pktio_t id)
unlock_entry(pktio_entry);
return -1;
}
- queue = pktio_entry->s.inq_default;
+
+ /* Temporary support for default input queue */
+ queue = pktio_entry->s.in_queue[0].queue;
qentry = queue_to_qentry(queue);
queue_lock(qentry);
qentry->s.pktin = ODP_PKTIO_INVALID;
queue_unlock(qentry);
- pktio_entry->s.inq_default = ODP_QUEUE_INVALID;
+ pktio_entry->s.in_queue[0].queue = ODP_QUEUE_INVALID;
+ pktio_entry->s.in_queue[0].pktin.pktio = ODP_PKTIO_INVALID;
+ pktio_entry->s.in_queue[0].pktin.index = 0;
+ pktio_entry->s.num_in_queue = 0;
unlock_entry(pktio_entry);
return 0;
@@ -507,7 +527,8 @@ odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
if (pktio_entry == NULL)
return ODP_QUEUE_INVALID;
- return pktio_entry->s.inq_default;
+ /* Temporary support for default input queue */
+ return pktio_entry->s.in_queue[0].queue;
}
odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
@@ -645,43 +666,47 @@ int pktin_deq_multi(queue_entry_t *qentry,
odp_buffer_hdr_t *buf_hdr[], int num)
return nbr;
}
-int pktin_poll(pktio_entry_t *entry)
+int pktin_poll(pktio_entry_t *entry, int num_queue, int index[])
{
odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
- int num, i;
+ int num, i, idx;
odp_buffer_t buf;
- odp_pktio_t pktio;
- pktio = entry->s.handle;
-
- if (odp_unlikely(is_free(entry)))
+ if (odp_unlikely(is_free(entry))) {
+ ODP_ERR("Bad pktio entry\n");
return -1;
+ }
- if (odp_unlikely(entry->s.inq_default == ODP_QUEUE_INVALID))
+ /* Temporarely needed for odp_pktio_inq_remdef() */
+ if (odp_unlikely(entry->s.num_in_queue == 0))
return -1;
if (entry->s.state == STATE_STOP)
return 0;
- num = odp_pktio_recv(pktio, pkt_tbl, QUEUE_MULTI_MAX);
-
- if (num == 0)
- return 0;
-
- if (num < 0) {
- ODP_ERR("Packet recv error\n");
- return -1;
- }
-
- for (i = 0; i < num; i++) {
- buf = _odp_packet_to_buffer(pkt_tbl[i]);
- hdr_tbl[i] = odp_buf_to_hdr(buf);
- }
-
- if (num) {
+ for (idx = 0; idx < num_queue; idx++) {
queue_entry_t *qentry;
- qentry = queue_to_qentry(entry->s.inq_default);
+ odp_queue_t queue;
+ odp_pktin_queue_t pktin = entry->s.in_queue[index[idx]].pktin;
+
+ num = odp_pktio_recv_queue(pktin, pkt_tbl, QUEUE_MULTI_MAX);
+
+ if (num == 0)
+ continue;
+
+ if (num < 0) {
+ ODP_ERR("Packet recv error\n");
+ return -1;
+ }
+
+ for (i = 0; i < num; i++) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ hdr_tbl[i] = odp_buf_to_hdr(buf);
+ }
+
+ queue = entry->s.in_queue[index[idx]].queue;
+ qentry = queue_to_qentry(queue);
queue_enq_multi(qentry, hdr_tbl, num, 0);
}
@@ -1111,11 +1136,14 @@ int single_input_queues_config(pktio_entry_t *entry,
entry->s.in_queue[0].queue = queue;
} else {
- entry->s.in_queue[0].queue = ODP_QUEUE_INVALID;
- entry->s.in_queue[0].pktin.pktio = entry->s.handle;
- entry->s.in_queue[0].pktin.index = 0;
+ entry->s.in_queue[0].queue = ODP_QUEUE_INVALID;
}
+ entry->s.in_queue[0].pktin.pktio = entry->s.handle;
+ entry->s.in_queue[0].pktin.index = 0;
+
+ entry->s.num_in_queue = 1;
+
return 0;
}
@@ -1128,6 +1156,8 @@ int single_output_queues_config(pktio_entry_t *entry,
entry->s.out_queue[0].pktout.pktio = entry->s.handle;
entry->s.out_queue[0].pktout.index = 0;
+ entry->s.num_out_queue = 1;
+
return 0;
}
diff --git a/platform/linux-generic/odp_schedule.c
b/platform/linux-generic/odp_schedule.c
index 58f1b1b..22af755 100644
--- a/platform/linux-generic/odp_schedule.c
+++ b/platform/linux-generic/odp_schedule.c
@@ -36,6 +36,8 @@ odp_thrmask_t sched_mask_all;
/* Maximum number of dequeues */
#define MAX_DEQ 4
+/* Maximum number of packet input queues per command */
+#define MAX_PKTIN 8
/* Mask of queues per priority */
typedef uint8_t pri_mask_t;
@@ -69,8 +71,10 @@ typedef struct {
struct {
odp_pktio_t pktio;
+ int num;
+ int index[MAX_PKTIN];
pktio_entry_t *pe;
- int prio;
+ int prio;
};
};
} sched_cmd_t;
@@ -357,30 +361,36 @@ void schedule_queue_destroy(queue_entry_t *qe)
qe->s.pri_queue = ODP_QUEUE_INVALID;
}
-int schedule_pktio_start(odp_pktio_t pktio, int prio)
+void schedule_pktio_start(odp_pktio_t pktio, int num_in_queue,
+ int in_queue_idx[], int prio)
{
odp_buffer_t buf;
sched_cmd_t *sched_cmd;
odp_queue_t pri_queue;
+ int i;
buf = odp_buffer_alloc(sched->pool);
if (buf == ODP_BUFFER_INVALID)
- return -1;
+ ODP_ABORT("Sched pool empty\n");
sched_cmd = odp_buffer_addr(buf);
sched_cmd->cmd = SCHED_CMD_POLL_PKTIN;
sched_cmd->pktio = pktio;
+ sched_cmd->num = num_in_queue;
sched_cmd->pe = get_pktio_entry(pktio);
sched_cmd->prio = prio;
+ if (num_in_queue > MAX_PKTIN)
+ ODP_ABORT("Too many input queues for scheduler\n");
+
+ for (i = 0; i < num_in_queue; i++)
+ sched_cmd->index[i] = in_queue_idx[i];
+
pri_queue = pri_set_pktio(pktio, prio);
if (odp_queue_enq(pri_queue, odp_buffer_to_event(buf)))
ODP_ABORT("schedule_pktio_start failed\n");
-
-
- return 0;
}
void odp_schedule_release_atomic(void)
@@ -493,7 +503,9 @@ static int schedule(odp_queue_t *out_queue, odp_event_t
out_ev[],
if (sched_cmd->cmd == SCHED_CMD_POLL_PKTIN) {
/* Poll packet input */
- if (pktin_poll(sched_cmd->pe)) {
+ if (pktin_poll(sched_cmd->pe,
+ sched_cmd->num,
+ sched_cmd->index)) {
/* Stop scheduling the pktio */
pri_clr_pktio(sched_cmd->pktio,
sched_cmd->prio);
--
2.6.3
_______________________________________________
lng-odp mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/lng-odp