Signed-off-by: Nikita Kalyazin <[email protected]>
Reviewed-by: Ilya Maximets <[email protected]>
---
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
[email protected]
https://lists.linaro.org/mailman/listinfo/lng-odp