OK. I try to prepare them. Best regards, Ilya Maximets.
On 27.11.2015 13:19, Maxim Uvarov wrote: > Hello Ilya, > > Thanks for sending that patch. Tap pktio should be interesting. > To accept it we also need coverage validation tests. > > Best regards, > Maxim. > > > On 11/25/2015 17:15, Ilya Maximets wrote: >> Creates a new pktio type that allows for creating and >> sending/receiving packets through TAP interface. >> It is intended for use as a simple conventional communication >> method between applications that use kernel network stack >> (ping, ssh, iperf, etc.) and ODP applications for the purpose >> of functional testing and can be used as it is with some >> of the existing example applications. >> >> To use this interface the name passed to odp_pktio_open() must >> begin with "tap:" and be in the format: >> >> tap:iface >> >> iface the name of TAP device to be created. >> >> TUN/TAP kernel module should be loaded to use this pktio. >> There should be no device named 'iface' in the system. >> The total length of the 'iface' is limited by IF_NAMESIZE. >> >> Signed-off-by: Ilya Maximets <i.maxim...@samsung.com> >> --- >> platform/linux-generic/Makefile.am | 2 + >> .../linux-generic/include/odp_packet_io_internal.h | 3 + >> platform/linux-generic/include/odp_packet_tap.h | 17 ++ >> platform/linux-generic/pktio/io_ops.c | 1 + >> platform/linux-generic/pktio/tap.c | 251 >> +++++++++++++++++++++ >> 5 files changed, 274 insertions(+) >> create mode 100644 platform/linux-generic/include/odp_packet_tap.h >> create mode 100644 platform/linux-generic/pktio/tap.c >> >> diff --git a/platform/linux-generic/Makefile.am >> b/platform/linux-generic/Makefile.am >> index 610e04d..8395bda 100644 >> --- a/platform/linux-generic/Makefile.am >> +++ b/platform/linux-generic/Makefile.am >> @@ -91,6 +91,7 @@ noinst_HEADERS = \ >> ${srcdir}/include/odp_packet_io_queue.h \ >> ${srcdir}/include/odp_packet_netmap.h \ >> ${srcdir}/include/odp_packet_socket.h \ >> + ${srcdir}/include/odp_packet_tap.h \ >> ${srcdir}/include/odp_pool_internal.h \ >> ${srcdir}/include/odp_queue_internal.h \ >> ${srcdir}/include/odp_schedule_internal.h \ >> @@ -119,6 +120,7 @@ __LIB__libodp_la_SOURCES = \ >> pktio/netmap.c \ >> pktio/socket.c \ >> pktio/socket_mmap.c \ >> + pktio/tap.c \ >> odp_pool.c \ >> odp_queue.c \ >> odp_rwlock.c \ >> diff --git a/platform/linux-generic/include/odp_packet_io_internal.h >> b/platform/linux-generic/include/odp_packet_io_internal.h >> index 1a1118c..de29557 100644 >> --- a/platform/linux-generic/include/odp_packet_io_internal.h >> +++ b/platform/linux-generic/include/odp_packet_io_internal.h >> @@ -22,6 +22,7 @@ extern "C" { >> #include <odp/ticketlock.h> >> #include <odp_packet_socket.h> >> #include <odp_packet_netmap.h> >> +#include <odp_packet_tap.h> >> #include <odp_classification_datamodel.h> >> #include <odp_align_internal.h> >> #include <odp_debug_internal.h> >> @@ -78,6 +79,7 @@ struct pktio_entry { >> #ifdef HAVE_PCAP >> pkt_pcap_t pkt_pcap; /**< Using pcap for IO */ >> #endif >> + pkt_tap_t pkt_tap; /**< using TAP for IO */ >> }; >> enum { >> STATE_START = 0, >> @@ -157,6 +159,7 @@ extern const pktio_if_ops_t loopback_pktio_ops; >> #ifdef HAVE_PCAP >> extern const pktio_if_ops_t pcap_pktio_ops; >> #endif >> +extern const pktio_if_ops_t tap_pktio_ops; >> extern const pktio_if_ops_t * const pktio_if_ops[]; >> >> #ifdef __cplusplus >> diff --git a/platform/linux-generic/include/odp_packet_tap.h >> b/platform/linux-generic/include/odp_packet_tap.h >> new file mode 100644 >> index 0000000..2d442fb >> --- /dev/null >> +++ b/platform/linux-generic/include/odp_packet_tap.h >> @@ -0,0 +1,17 @@ >> +/* Copyright (c) 2015, Ilya Maximets <i.maxim...@samsung.com> >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#ifndef ODP_PACKET_TAP_H_ >> +#define ODP_PACKET_TAP_H_ >> + >> +#include <odp/pool.h> >> + >> +typedef struct { >> + int fd; /**< file descriptor for tap interface */ >> + odp_pool_t pool; /**< pool to alloc packets from */ >> +} pkt_tap_t; >> + >> +#endif >> diff --git a/platform/linux-generic/pktio/io_ops.c >> b/platform/linux-generic/pktio/io_ops.c >> index 3b344e6..1933abc 100644 >> --- a/platform/linux-generic/pktio/io_ops.c >> +++ b/platform/linux-generic/pktio/io_ops.c >> @@ -18,6 +18,7 @@ const pktio_if_ops_t * const pktio_if_ops[] = { >> #ifdef HAVE_PCAP >> &pcap_pktio_ops, >> #endif >> + &tap_pktio_ops, >> &sock_mmap_pktio_ops, >> &sock_mmsg_pktio_ops, >> NULL >> diff --git a/platform/linux-generic/pktio/tap.c >> b/platform/linux-generic/pktio/tap.c >> new file mode 100644 >> index 0000000..e629986 >> --- /dev/null >> +++ b/platform/linux-generic/pktio/tap.c >> @@ -0,0 +1,251 @@ >> +/* Copyright (c) 2015, Ilya Maximets <i.maxim...@samsung.com> >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +/** >> + * @file >> + * >> + * TAP pktio type >> + * >> + * This file provides a pktio interface that allows for creating and >> + * send/receive packets through TAP interface. It is intended for use >> + * as a simple conventional communication method between applications >> + * that use kernel network stack (ping, ssh, iperf, etc.) and ODP >> + * applications for the purpose of functional testing. >> + * >> + * To use this interface the name passed to odp_pktio_open() must begin >> + * with "tap:" and be in the format: >> + * >> + * tap:iface >> + * >> + * iface the name of TAP device to be created. >> + * >> + * TUN/TAP kernel module should be loaded to use this pktio. >> + * There should be no device named 'iface' in the system. >> + * The total length of the 'iface' is limited by IF_NAMESIZE. >> + */ >> + >> +#ifndef _GNU_SOURCE >> +#define _GNU_SOURCE >> +#endif >> + >> +#include <errno.h> >> +#include <fcntl.h> >> +#include <unistd.h> >> +#include <stdio.h> >> +#include <sys/ioctl.h> >> +#include <sys/socket.h> >> +#include <sys/types.h> >> +#include <linux/if_tun.h> >> + >> +#include <odp.h> >> +#include <odp_packet_socket.h> >> +#include <odp_packet_internal.h> >> +#include <odp_packet_io_internal.h> >> + >> +#define BUF_SIZE 65536 >> + >> +static int tap_pktio_open(odp_pktio_t id ODP_UNUSED, >> + pktio_entry_t *pktio_entry, >> + const char *devname, odp_pool_t pool) >> +{ >> + int fd, flags; >> + struct ifreq ifr; >> + pkt_tap_t *tap = &pktio_entry->s.pkt_tap; >> + >> + if (strncmp(devname, "tap:", 4) != 0) >> + return -1; >> + >> + /* Init pktio entry */ >> + memset(tap, 0, sizeof(*tap)); >> + tap->fd = -1; >> + >> + if (pool == ODP_POOL_INVALID) >> + return -1; >> + >> + fd = open("/dev/net/tun", O_RDWR); >> + if (fd < 0) { >> + __odp_errno = errno; >> + ODP_ERR("failed to open /dev/net/tun: %s\n", strerror(errno)); >> + return -1; >> + } >> + >> + memset(&ifr, 0, sizeof(ifr)); >> + /* Flags: IFF_TUN - TUN device (no Ethernet headers) >> + * IFF_TAP - TAP device >> + * >> + * IFF_NO_PI - Do not provide packet information >> + */ >> + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; >> + snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", devname + 4); >> + >> + if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) { >> + __odp_errno = errno; >> + ODP_ERR("%s: creating tap device failed: %s\n", >> + ifr.ifr_name, strerror(errno)); >> + goto tap_err; >> + } >> + >> + flags = fcntl(fd, F_GETFL, 0); >> + if (flags < 0) { >> + __odp_errno = errno; >> + ODP_ERR("fcntl(F_GETFL) failed: %s\n", strerror(errno)); >> + goto tap_err; >> + } >> + >> + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { >> + __odp_errno = errno; >> + ODP_ERR("fcntl(F_SETFL) failed: %s\n", strerror(errno)); >> + goto tap_err; >> + } >> + >> + tap->fd = fd; >> + tap->pool = pool; >> + return 0; >> + >> +tap_err: >> + ODP_ERR("Tap device alloc failed.\n"); >> + close(fd); >> + return -1; >> +} >> + >> +static int tap_pktio_close(pktio_entry_t *pktio_entry) >> +{ >> + pkt_tap_t *tap = &pktio_entry->s.pkt_tap; >> + >> + if (tap->fd != -1 && close(tap->fd) != 0) { >> + __odp_errno = errno; >> + ODP_ERR("close(tap->fd): %s\n", strerror(errno)); >> + return -1; >> + } >> + >> + return 0; >> +} >> + >> +static odp_packet_t pack_odp_pkt(odp_pool_t pool, >> + const void *data, >> + unsigned int len) >> +{ >> + odp_packet_t pkt; >> + >> + pkt = packet_alloc(pool, len, 1); >> + >> + if (pkt == ODP_PACKET_INVALID) >> + return pkt; >> + >> + if (odp_packet_copydata_in(pkt, 0, len, data) < 0) { >> + ODP_ERR("failed to copy packet data\n"); >> + odp_packet_free(pkt); >> + return ODP_PACKET_INVALID; >> + } >> + >> + packet_parse_l2(odp_packet_hdr(pkt)); >> + >> + return pkt; >> +} >> + >> +static int tap_pktio_recv(pktio_entry_t *pktio_entry, odp_packet_t pkts[], >> + unsigned len) >> +{ >> + ssize_t retval; >> + unsigned i; >> + uint8_t buf[BUF_SIZE]; >> + pkt_tap_t *tap = &pktio_entry->s.pkt_tap; >> + >> + for (i = 0; i < len; i++) { >> + do { >> + retval = read(tap->fd, buf, BUF_SIZE); >> + } while (retval < 0 && errno == EINTR); >> + >> + if (retval < 0) { >> + __odp_errno = errno; >> + break; >> + } >> + >> + pkts[i] = pack_odp_pkt(tap->pool, buf, retval); >> + if (pkts[i] == ODP_PACKET_INVALID) >> + break; >> + } >> + >> + return i; >> +} >> + >> +static int tap_pktio_send(pktio_entry_t *pktio_entry, odp_packet_t pkts[], >> + unsigned len) >> +{ >> + ssize_t retval; >> + unsigned i; >> + uint32_t pkt_len; >> + uint8_t buf[BUF_SIZE]; >> + pkt_tap_t *tap = &pktio_entry->s.pkt_tap; >> + >> + for (i = 0; i < len; i++) { >> + pkt_len = odp_packet_len(pkts[i]); >> + >> + if (odp_packet_copydata_out(pkts[i], 0, pkt_len, buf) < 0) { >> + ODP_ERR("failed to copy packet data\n"); >> + break; >> + } >> + >> + do { >> + retval = write(tap->fd, buf, pkt_len); >> + } while (retval < 0 && errno == EINTR); >> + >> + if (retval < 0) { >> + __odp_errno = (errno == ENOBUFS) ? EAGAIN : errno; >> + break; >> + } else if (retval != pkt_len) { >> + __odp_errno = EMSGSIZE; >> + ODP_ERR("sent partial ethernet packet\n"); >> + break; >> + } >> + >> + odp_packet_free(pkts[i]); >> + } >> + >> + return i; >> +} >> + >> +static int tap_mtu_get(pktio_entry_t *pktio_entry) >> +{ >> + return mtu_get_fd(pktio_entry->s.pkt_tap.fd, >> + pktio_entry->s.name + 4); >> +} >> + >> +static int tap_promisc_mode_set(pktio_entry_t *pktio_entry, >> + odp_bool_t enable) >> +{ >> + return promisc_mode_set_fd(pktio_entry->s.pkt_tap.fd, >> + pktio_entry->s.name + 4, enable); >> +} >> + >> +static int tap_promisc_mode_get(pktio_entry_t *pktio_entry) >> +{ >> + return promisc_mode_get_fd(pktio_entry->s.pkt_tap.fd, >> + pktio_entry->s.name + 4); >> +} >> + >> +static int tap_mac_addr_get(pktio_entry_t *pktio_entry, void *mac_addr) >> +{ >> + int res = mac_addr_get_fd(pktio_entry->s.pkt_tap.fd, >> + pktio_entry->s.name + 4, mac_addr); >> + >> + return (res == 0) ? ETH_ALEN : res; >> +} >> + >> +const pktio_if_ops_t tap_pktio_ops = { >> + .init = NULL, >> + .term = NULL, >> + .open = tap_pktio_open, >> + .close = tap_pktio_close, >> + .start = NULL, >> + .stop = NULL, >> + .recv = tap_pktio_recv, >> + .send = tap_pktio_send, >> + .mtu_get = tap_mtu_get, >> + .promisc_mode_set = tap_promisc_mode_set, >> + .promisc_mode_get = tap_promisc_mode_get, >> + .mac_get = tap_mac_addr_get >> +}; > _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org https://lists.linaro.org/mailman/listinfo/lng-odp