The following API is implemented: - odp_pktio_max_num_queues() - odp_pktio_configure() - odp_pktio_num_queues() - odp_pktio_recv_queue() - odp_pktio_send_queue()
Signed-off-by: Nikita Kalyazin <[email protected]> Reviewed-by: Ilya Maximets <[email protected]> --- .../linux-generic/include/odp_packet_io_internal.h | 11 ++ platform/linux-generic/odp_packet_io.c | 169 +++++++++++++++++++-- 2 files changed, 166 insertions(+), 14 deletions(-) diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h index 2eb66bb..74c6338 100644 --- a/platform/linux-generic/include/odp_packet_io_internal.h +++ b/platform/linux-generic/include/odp_packet_io_internal.h @@ -47,6 +47,8 @@ struct pktio_entry { odp_pktio_t handle; /**< pktio handle */ odp_queue_t inq_default; /**< default input queue, if set */ odp_queue_t outq_default; /**< default out queue */ + uint32_t num_rx_queues; /**< current number of rx hw queues */ + uint32_t num_tx_queues; /**< current number of tx hw queues */ union { pkt_loop_t pkt_loop; /**< Using loopback for IO */ pkt_sock_t pkt_sock; /**< using socket API for IO */ @@ -80,12 +82,21 @@ typedef struct pktio_if_ops { int (*open)(odp_pktio_t pktio, pktio_entry_t *pktio_entry, const char *devname, odp_pool_t pool); int (*close)(pktio_entry_t *pktio_entry); + int (*max_num_queues_get)(pktio_entry_t *pktio_entry, + uint32_t *num_rx_queues, + uint32_t *num_tx_queues); + int (*configure)(pktio_entry_t *pktio_entry, uint32_t nr_rx_queues, + uint32_t nr_tx_queues); int (*start)(pktio_entry_t *pktio_entry); int (*stop)(pktio_entry_t *pktio_entry); int (*recv)(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], unsigned len); + int (*recv_queue)(pktio_entry_t *pktio_entry, uint32_t queue_index, + odp_packet_t pkt_table[], unsigned len); int (*send)(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], unsigned len); + int (*send_queue)(pktio_entry_t *pktio_entry, uint32_t queue_index, + odp_packet_t pkt_table[], unsigned len); int (*mtu_get)(pktio_entry_t *pktio_entry); int (*promisc_mode_set)(pktio_entry_t *pktio_entry, int enable); int (*promisc_mode_get)(pktio_entry_t *pktio_entry); diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index a1f51e7..202e850 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -75,6 +75,9 @@ int odp_pktio_init_global(void) queue_entry = queue_to_qentry(qid); queue_entry->s.pktout = _odp_cast_scalar(odp_pktio_t, id); + + pktio_entry->s.num_rx_queues = 1; + pktio_entry->s.num_tx_queues = 1; } for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) { @@ -133,13 +136,35 @@ static void set_taken(pktio_entry_t *entry) entry->s.taken = 1; } +static void lock_entry_queue(pktio_entry_t *entry, uint32_t queue_idx) +{ + odp_ticketlock_lock(&entry->s.queue_locks[queue_idx]); +} + static void lock_entry(pktio_entry_t *entry) { + unsigned i, num; + odp_ticketlock_lock(&entry->s.lock); + num = entry->s.num_rx_queues > entry->s.num_tx_queues ? + entry->s.num_rx_queues : entry->s.num_tx_queues; + for (i = 0; i < num; i++) + lock_entry_queue(entry, i); +} + +static void unlock_entry_queue(pktio_entry_t *entry, uint32_t queue_idx) +{ + odp_ticketlock_unlock(&entry->s.queue_locks[queue_idx]); } static void unlock_entry(pktio_entry_t *entry) { + unsigned i, num; + + num = entry->s.num_rx_queues > entry->s.num_tx_queues ? + entry->s.num_rx_queues : entry->s.num_tx_queues; + for (i = 0; i < num; i++) + unlock_entry_queue(entry, i); odp_ticketlock_unlock(&entry->s.lock); } @@ -292,6 +317,90 @@ int odp_pktio_close(odp_pktio_t id) return 0; } +int odp_pktio_max_num_queues(odp_pktio_t id, uint32_t *num_rx_queues, + uint32_t *num_tx_queues) +{ + pktio_entry_t *entry; + int res = 0; + + entry = get_pktio_entry(id); + if (!entry) + return -1; + + lock_entry(entry); + if (entry->s.ops->max_num_queues_get) { + res = entry->s.ops->max_num_queues_get(entry, num_rx_queues, + num_tx_queues); + *num_rx_queues = *num_rx_queues > ODP_CONFIG_PKTIO_QUEUES ? + ODP_CONFIG_PKTIO_QUEUES : *num_rx_queues; + *num_tx_queues = *num_tx_queues > ODP_CONFIG_PKTIO_QUEUES ? + ODP_CONFIG_PKTIO_QUEUES : *num_tx_queues; + } else { + /* If the pktio is not aware of multiqueue, + * then fallback to single queue mode */ + *num_rx_queues = *num_tx_queues = 1; + res = 0; + } + unlock_entry(entry); + + return res; +} + +int odp_pktio_configure(odp_pktio_t id, uint32_t num_rx_queues, + uint32_t num_tx_queues) +{ + pktio_entry_t *entry; + int res = 0; + + entry = get_pktio_entry(id); + if (!entry) + return -1; + + if (num_rx_queues > ODP_CONFIG_PKTIO_QUEUES || + num_tx_queues > ODP_CONFIG_PKTIO_QUEUES) + return -1; + + odp_ticketlock_lock(&entry->s.lock); + if (odp_unlikely(entry->s.state == STATE_START)) { + odp_ticketlock_unlock(&entry->s.lock); + return -1; + } + + if (entry->s.ops->configure) + res = entry->s.ops->configure(entry, num_rx_queues, + num_tx_queues); + else + /* If configure() is not implemented, we assume that the pktio + * supports single queue mode only */ + if (num_rx_queues != 1 || num_tx_queues != 1) + res = -1; + if (!res) { + entry->s.num_rx_queues = num_rx_queues; + entry->s.num_tx_queues = num_tx_queues; + } + odp_ticketlock_unlock(&entry->s.lock); + + return res; +} + +int odp_pktio_num_queues(odp_pktio_t id, uint32_t *num_rx_queues, + uint32_t *num_tx_queues) +{ + pktio_entry_t *entry; + int res = 0; + + entry = get_pktio_entry(id); + if (!entry) + return -1; + + lock_entry(entry); + *num_rx_queues = entry->s.num_rx_queues; + *num_tx_queues = entry->s.num_tx_queues; + unlock_entry(entry); + + return res; +} + int odp_pktio_start(odp_pktio_t id) { pktio_entry_t *entry; @@ -360,9 +469,8 @@ odp_pktio_t odp_pktio_lookup(const char *dev) return id; } - - -int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], int len) +int odp_pktio_recv_queue(odp_pktio_t id, uint32_t queue_index, + odp_packet_t pkt_table[], int len) { pktio_entry_t *pktio_entry = get_pktio_entry(id); int pkts; @@ -371,14 +479,25 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], int len) if (pktio_entry == NULL) return -1; - lock_entry(pktio_entry); - if (pktio_entry->s.state == STATE_STOP) { - unlock_entry(pktio_entry); + lock_entry_queue(pktio_entry, queue_index); + if (odp_unlikely(pktio_entry->s.state == STATE_STOP)) { + unlock_entry_queue(pktio_entry, queue_index); __odp_errno = EPERM; return -1; } - pkts = pktio_entry->s.ops->recv(pktio_entry, pkt_table, len); - unlock_entry(pktio_entry); + if (odp_unlikely(!pktio_entry->s.ops->recv_queue)) { + unlock_entry_queue(pktio_entry, queue_index); + __odp_errno = ENOSYS; + return -1; + } + if (odp_unlikely(queue_index >= pktio_entry->s.num_rx_queues)) { + unlock_entry_queue(pktio_entry, queue_index); + __odp_errno = EINVAL; + return -1; + } + pkts = pktio_entry->s.ops->recv_queue(pktio_entry, queue_index, + pkt_table, len); + unlock_entry_queue(pktio_entry, queue_index); if (pkts < 0) return pkts; @@ -389,7 +508,13 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], int len) return pkts; } -int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], int len) +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], int len) +{ + return odp_pktio_recv_queue(id, 0, pkt_table, len); +} + +int odp_pktio_send_queue(odp_pktio_t id, uint32_t queue_index, + odp_packet_t pkt_table[], int len) { pktio_entry_t *pktio_entry = get_pktio_entry(id); int pkts; @@ -397,18 +522,34 @@ int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], int len) if (pktio_entry == NULL) return -1; - lock_entry(pktio_entry); - if (pktio_entry->s.state == STATE_STOP) { - unlock_entry(pktio_entry); + lock_entry_queue(pktio_entry, queue_index); + if (odp_unlikely(pktio_entry->s.state == STATE_STOP)) { + unlock_entry_queue(pktio_entry, queue_index); __odp_errno = EPERM; return -1; } - pkts = pktio_entry->s.ops->send(pktio_entry, pkt_table, len); - unlock_entry(pktio_entry); + if (odp_unlikely(!pktio_entry->s.ops->send_queue)) { + unlock_entry_queue(pktio_entry, queue_index); + __odp_errno = ENOSYS; + return -1; + } + if (odp_unlikely(queue_index >= pktio_entry->s.num_tx_queues)) { + unlock_entry_queue(pktio_entry, queue_index); + __odp_errno = EINVAL; + return -1; + } + pkts = pktio_entry->s.ops->send_queue(pktio_entry, queue_index, + pkt_table, len); + unlock_entry_queue(pktio_entry, queue_index); return pkts; } +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], int len) +{ + return odp_pktio_send_queue(id, 0, pkt_table, len); +} + int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue) { pktio_entry_t *pktio_entry = get_pktio_entry(id); -- 2.5.3 _______________________________________________ lng-odp mailing list [email protected] https://lists.linaro.org/mailman/listinfo/lng-odp
