Signed-off-by: Nikita Kalyazin <n.kalya...@samsung.com>
Reviewed-by: Ilya Maximets <i.maxim...@samsung.com>
---
 platform/linux-generic/include/odp_packet_netmap.h |   6 +-
 platform/linux-generic/pktio/netmap.c              | 218 +++++++++++++++++----
 2 files changed, 188 insertions(+), 36 deletions(-)

diff --git a/platform/linux-generic/include/odp_packet_netmap.h 
b/platform/linux-generic/include/odp_packet_netmap.h
index 23aea5b..c63aaf1 100644
--- a/platform/linux-generic/include/odp_packet_netmap.h
+++ b/platform/linux-generic/include/odp_packet_netmap.h
@@ -7,18 +7,18 @@
 #ifndef ODP_PACKET_NETMAP_H
 #define ODP_PACKET_NETMAP_H
 
-#include <odp/pool.h>
-
+#include <odp.h>
 #include <linux/if_ether.h>
 
 /** Packet socket using netmap mmaped rings for both Rx and Tx */
 typedef struct {
        odp_pool_t pool;                /**< pool to alloc packets from */
        size_t max_frame_len;           /**< buf_size - sizeof(pkt_hdr) */
-       struct nm_desc *desc;           /**< netmap meta-data for the device */
+       struct nm_desc *desc[ODP_CONFIG_PKTIO_QUEUES]; /**< netmap meta-data 
for the device */
        uint32_t if_flags;              /**< interface flags */
        int sockfd;                     /**< control socket */
        unsigned char if_mac[ETH_ALEN]; /**< eth mac address */
+       size_t max_num_queues;          /**< max number of queues supported */
 } pkt_netmap_t;
 
 #endif
diff --git a/platform/linux-generic/pktio/netmap.c 
b/platform/linux-generic/pktio/netmap.c
index ab4667e..1b63ecf 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -80,12 +80,80 @@ done:
        return err;
 }
 
-static int netmap_close(pktio_entry_t *pktio_entry)
+static int netmap_ethtool_max_queues_get(pktio_entry_t *pktio_entry,
+                                        size_t *num)
+{
+       pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+       struct ifreq ifr;
+       int err;
+       int fd = pkt_nm->sockfd;
+       struct ethtool_channels echannels = { .cmd = ETHTOOL_GCHANNELS };
+
+       memset(&ifr, 0, sizeof(ifr));
+       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s",
+                pktio_entry->s.name);
+
+       ifr.ifr_data = (caddr_t)&echannels;
+       err = ioctl(fd, SIOCETHTOOL, &ifr);
+
+       if (err)
+               goto done;
+       *num = echannels.max_combined;
+
+done:
+       return err;
+}
+
+static int netmap_ethtool_queues_set(pktio_entry_t *pktio_entry, size_t num)
 {
        pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+       struct ifreq ifr;
+       int err;
+       int fd = pkt_nm->sockfd;
+       struct ethtool_channels echannels = {
+               .cmd = ETHTOOL_SCHANNELS,
+               .combined_count = num
+       };
+
+       if (pktio_entry->s.num_rx_queues == num)
+               return 0;
 
-       if (pkt_nm->desc != NULL)
-               nm_close(pkt_nm->desc);
+       memset(&ifr, 0, sizeof(ifr));
+       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s",
+                pktio_entry->s.name);
+
+       ifr.ifr_data = (caddr_t)&echannels;
+       err = ioctl(fd, SIOCETHTOOL, &ifr);
+
+       return err;
+}
+
+static int netmap_ethtool_queues_get(pktio_entry_t *pktio_entry, size_t *num)
+{
+               pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+       struct ifreq ifr;
+       int err;
+       int fd = pkt_nm->sockfd;
+       struct ethtool_channels echannels = { .cmd = ETHTOOL_GCHANNELS };
+
+       memset(&ifr, 0, sizeof(ifr));
+       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s",
+                pktio_entry->s.name);
+
+       ifr.ifr_data = (caddr_t)&echannels;
+       err = ioctl(fd, SIOCETHTOOL, &ifr);
+
+       if (err)
+               goto done;
+       *num = echannels.combined_count;
+
+done:
+       return err;
+}
+
+static int netmap_close(pktio_entry_t *pktio_entry)
+{
+       pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
 
        if (pkt_nm->sockfd != -1 && close(pkt_nm->sockfd) != 0) {
                __odp_errno = errno;
@@ -98,10 +166,10 @@ static int netmap_close(pktio_entry_t *pktio_entry)
 static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
                       const char *netdev, odp_pool_t pool)
 {
-       char ifname[IFNAMSIZ + 7]; /* netmap:<ifname> */
        int err;
        int sockfd;
        pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+       size_t num;
 
        if (getenv("ODP_PKTIO_DISABLE_NETMAP"))
                return -1;
@@ -121,22 +189,6 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, 
pktio_entry_t *pktio_entry,
 
        snprintf(pktio_entry->s.name, sizeof(pktio_entry->s.name), "%s",
                 netdev);
-       snprintf(ifname, sizeof(ifname), "netmap:%s", netdev);
-
-       if (mmap_desc.mem == NULL)
-               pkt_nm->desc = nm_open(ifname, NULL, NETMAP_NO_TX_POLL, NULL);
-       else
-               pkt_nm->desc = nm_open(ifname, NULL, NETMAP_NO_TX_POLL |
-                                      NM_OPEN_NO_MMAP, &mmap_desc);
-       if (pkt_nm->desc == NULL) {
-               ODP_ERR("nm_open(%s) failed\n", ifname);
-               goto error;
-       }
-
-       if (mmap_desc.mem == NULL) {
-               mmap_desc.mem = pkt_nm->desc->mem;
-               mmap_desc.memsize = pkt_nm->desc->memsize;
-       }
 
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd == -1) {
@@ -155,6 +207,19 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, 
pktio_entry_t *pktio_entry,
        if (err)
                goto error;
 
+       err = netmap_ethtool_max_queues_get(pktio_entry, &num);
+       if (err) {
+               ODP_DBG("max queues get failed\n");
+               goto error;
+       }
+       pkt_nm->max_num_queues = num;
+
+       err = netmap_ethtool_queues_get(pktio_entry, &num);
+       if (err) {
+               ODP_DBG("queues get failed\n");
+               goto error;
+       }
+
        return 0;
 
 error:
@@ -162,10 +227,85 @@ error:
        return -1;
 }
 
-static void netmap_recv_cb(u_char *arg, const struct nm_pkthdr *hdr,
-                          const u_char *buf)
+static int netmap_start(pktio_entry_t *pktio_entry)
+{
+       pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+       unsigned int i, err_queue;
+       char ifname[IFNAMSIZ + 7]; /* netmap: */
+
+       for (i = 0; i < pktio_entry->s.num_rx_queues; i++) {
+               snprintf(ifname, sizeof(ifname), "netmap:%s-%d",
+                        pktio_entry->s.name, i);
+
+               if (mmap_desc.mem == NULL)
+                       pkt_nm->desc[i] = nm_open(ifname, NULL, 0, NULL);
+               else
+                       pkt_nm->desc[i] = nm_open(ifname, NULL, NM_OPEN_NO_MMAP,
+                                                 &mmap_desc);
+
+               if (pkt_nm->desc[i] == NULL) {
+                       ODP_ERR("nm_open(%s-%d) failed\n", ifname, i);
+                       err_queue = i;
+                       goto error;
+               }
+
+               if (mmap_desc.mem == NULL) {
+                       mmap_desc.mem = pkt_nm->desc[i]->mem;
+                       mmap_desc.memsize = pkt_nm->desc[i]->memsize;
+               }
+       }
+
+       return 0;
+
+error:
+
+       for (i = 0; i < err_queue; i++)
+               nm_close(pkt_nm->desc[i]);
+
+       return -1;
+}
+
+static int netmap_stop(pktio_entry_t *pktio_entry)
 {
-       struct dispatch_args *args = (struct dispatch_args *)arg;
+       pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+       unsigned int i;
+
+       for (i = 0; i < pktio_entry->s.num_rx_queues; i++)
+               nm_close(pkt_nm->desc[i]);
+
+       return 0;
+}
+
+static int netmap_max_num_queues_get(pktio_entry_t *pktio,
+                                    uint32_t *num_rx_queues,
+                                    uint32_t *num_tx_queues)
+{
+       *num_rx_queues = *num_tx_queues = pktio->s.pkt_nm.max_num_queues;
+       return 0;
+}
+
+static int netmap_configure(pktio_entry_t *pktio, uint32_t num_rx_queues,
+                           uint32_t num_tx_queues)
+{
+       /* netmap API does not allow to set up different number of
+        * rx and tx queues */
+       if (num_rx_queues != num_tx_queues ||
+           num_rx_queues > ODP_CONFIG_PKTIO_QUEUES) {
+               ODP_DBG("configure: wrong number of queues\n");
+               return -1;
+       }
+       if (netmap_ethtool_queues_set(pktio, num_rx_queues)) {
+               ODP_DBG("configure: failed to set number of queues\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static void netmap_recv_cb(uint8_t *arg, const struct nm_pkthdr *hdr,
+                          const uint8_t *buf)
+{
+       struct dispatch_args *args = (struct dispatch_args *)(void *)arg;
        pkt_netmap_t *pkt_nm = &args->pktio_entry->s.pkt_nm;
        odp_packet_t pkt;
        size_t frame_len = (size_t)hdr->len;
@@ -197,13 +337,18 @@ static void netmap_recv_cb(u_char *arg, const struct 
nm_pkthdr *hdr,
        args->pkt_table[args->nb_rx++] = pkt;
 }
 
-static int netmap_recv(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
-                      unsigned num)
+static int netmap_recv_queue(pktio_entry_t *pktio_entry, uint32_t queue_id,
+                            odp_packet_t pkt_table[], unsigned num)
 {
        struct dispatch_args args;
-       struct nm_desc *nm_desc = pktio_entry->s.pkt_nm.desc;
+       struct nm_desc *nm_desc;
        struct pollfd polld;
 
+       if (queue_id >= pktio_entry->s.num_rx_queues)
+               return -1;
+
+       nm_desc = pktio_entry->s.pkt_nm.desc[queue_id];
+
        polld.fd = nm_desc->fd;
        polld.events = POLLIN;
 
@@ -219,15 +364,20 @@ static int netmap_recv(pktio_entry_t *pktio_entry, 
odp_packet_t pkt_table[],
        return args.nb_rx;
 }
 
-static int netmap_send(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
-                      unsigned num)
+static int netmap_send_queue(pktio_entry_t *pktio_entry, uint32_t queue_id,
+                            odp_packet_t pkt_table[], unsigned num)
 {
-       struct nm_desc *nm_desc = pktio_entry->s.pkt_nm.desc;
+       struct nm_desc *nm_desc;
        struct pollfd polld;
        unsigned i, nb_tx;
        uint8_t *frame;
        uint32_t frame_len;
 
+       if (queue_id >= pktio_entry->s.num_tx_queues)
+               return -1;
+
+       nm_desc = pktio_entry->s.pkt_nm.desc[queue_id];
+
        polld.fd = nm_desc->fd;
        polld.events = POLLOUT;
 
@@ -280,10 +430,12 @@ const pktio_if_ops_t netmap_pktio_ops = {
        .term = NULL,
        .open = netmap_open,
        .close = netmap_close,
-       .start = NULL,
-       .stop = NULL,
-       .recv = netmap_recv,
-       .send = netmap_send,
+       .start = netmap_start,
+       .stop = netmap_stop,
+       .max_num_queues_get = netmap_max_num_queues_get,
+       .configure = netmap_configure,
+       .recv_queue = netmap_recv_queue,
+       .send_queue = netmap_send_queue,
        .mtu_get = netmap_mtu_get,
        .promisc_mode_set = netmap_promisc_mode_set,
        .promisc_mode_get = netmap_promisc_mode_get,
-- 
2.5.3

_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to