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