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

Reply via email to