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

Reply via email to