Agree.  Seems an elegant solution.  We should update the DEPENDENCIES files
if we're now going to require libpcap for a successful ODP build, as
currently we only call out libssl.

On Tue, Jul 28, 2015 at 2:43 PM, Mike Holmes <mike.hol...@linaro.org> wrote:

> I like it.
>
> Do we need a facility to compare output in some way to ensure correct
> operation - even if it is just to test this interface and is not a bigger
> part of regression ?
> Maybe the test suite checks that pcap-diff [1] (or similar) results in
> zero difference with a golden output file ?
>
> For testing this interface or extending it to any test I assume we would
> use the wrapper scripts to execute the test case passing in a pcap file and
> the wrapper would check the result externally when the test case has
> finished.
>
> [1] https://github.com/isginf/pcap-diff
>
> On 28 July 2015 at 13:54, Stuart Haslam <stuart.has...@linaro.org> wrote:
>
>> Create a new pktio type that allows for reading from and writing to a
>> pcap capture file. This is intended to be used as a simple way of
>> injecting test packets into an application for functional testing and
>> can be used as it is with some of the existing example applications.
>>
>> To open a pcap file the name passed to the odp_pktio_open() call needs
>> to be of the format "pcap:<filename>".
>>
>> By default all packets transmitted to a pcap pktio are simply freed, but
>> if the environment variable ODP_PKTIO_PCAP_DUMP is set, transmitted
>> packets will instead be saved to a separate pcap dump file, the name of
>> which is generated from the input filename (test.pcap -> test_out.pcap).
>>
>> MTU, MAC and promiscuous mode APIs aren't implemented.
>>
>> Signed-off-by: Stuart Haslam <stuart.has...@linaro.org>
>
>
Reviewed-by: Bill Fischofer <bill.fischo...@linaro.org>


>
>> ---
>> This is pretty handy for testing, for example with the classifier app;
>>
>> sudo ./odp_classifier -ipcap:test.pcap -p 
>> "ODP_PMR_SIP_ADDR:192.168.111.2:FFFFFFFF:queue1"
>> -t 5
>>
>>  configure.ac                                       |   8 +
>>  platform/linux-generic/Makefile.am                 |   1 +
>>  .../linux-generic/include/odp_packet_io_internal.h |  12 +-
>>  platform/linux-generic/odp_packet_io.c             |   8 +-
>>  platform/linux-generic/pktio/io_ops.c              |   1 +
>>  platform/linux-generic/pktio/pcap.c                | 191
>> +++++++++++++++++++++
>>  6 files changed, 216 insertions(+), 5 deletions(-)
>>  create mode 100644 platform/linux-generic/pktio/pcap.c
>>
>> diff --git a/configure.ac b/configure.ac
>> index 2ea1368..2a58ba9 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>>
>> @@ -265,6 +265,14 @@ AC_CHECK_HEADERS([openssl/des.h openssl/rand.h
>> openssl/hmac.h openssl/evp.h], []
>>               [AC_MSG_ERROR([OpenSSL headers required])])
>>
>>
>>  ##########################################################################
>> +# Check for libpcap availability
>>
>> +##########################################################################
>> +AC_CHECK_LIB([pcap], [pcap_open_offline], [],
>> +             [AC_MSG_FAILURE([libpcap libraries required])])
>> +AC_CHECK_HEADERS([pcap/pcap.h pcap/bpf.h], [],
>> +             [AC_MSG_ERROR([pcap headers required])])
>> +
>>
>> +##########################################################################
>>  # Restore old saved variables
>>
>>  ##########################################################################
>>  LDFLAGS=$OLD_LDFLAGS
>> diff --git a/platform/linux-generic/Makefile.am
>> b/platform/linux-generic/Makefile.am
>> index 4ee781c..4e702af 100644
>> --- a/platform/linux-generic/Makefile.am
>> +++ b/platform/linux-generic/Makefile.am
>> @@ -142,6 +142,7 @@ __LIB__libodp_la_SOURCES = \
>>                            odp_packet_io.c \
>>                            pktio/io_ops.c \
>>                            pktio/loop.c \
>> +                          pktio/pcap.c \
>>                            pktio/socket.c \
>>                            pktio/socket_mmap.c \
>>                            odp_pool.c \
>> diff --git a/platform/linux-generic/include/odp_packet_io_internal.h
>> b/platform/linux-generic/include/odp_packet_io_internal.h
>> index f230936..5339606 100644
>> --- a/platform/linux-generic/include/odp_packet_io_internal.h
>> +++ b/platform/linux-generic/include/odp_packet_io_internal.h
>> @@ -28,6 +28,8 @@ extern "C" {
>>  #include <odp/hints.h>
>>  #include <net/if.h>
>>
>> +#define PKTIO_NAME_LEN 64
>> +
>>  /* Forward declaration */
>>  struct pktio_if_ops;
>>
>> @@ -36,6 +38,12 @@ typedef struct {
>>         odp_bool_t promisc;             /**< promiscuous mode state */
>>  } pkt_loop_t;
>>
>> +typedef struct {
>> +       odp_pool_t pool;
>> +       void *rx;
>> +       void *tx_dump;
>> +} pkt_pcap_t;
>> +
>>  struct pktio_entry {
>>         const struct pktio_if_ops *ops; /**< Implementation specific
>> methods */
>>         odp_spinlock_t lock;            /**< entry spinlock */
>> @@ -49,9 +57,10 @@ struct pktio_entry {
>>                 pkt_sock_t pkt_sock;            /**< using socket API for
>> IO */
>>                 pkt_sock_mmap_t pkt_sock_mmap;  /**< using socket mmap
>>                                                  *   API for IO */
>> +               pkt_pcap_t pkt_pcap;            /**< Using pcap for IO */
>>         };
>>         classifier_t cls;               /**< classifier linked with this
>> pktio*/
>> -       char name[IF_NAMESIZE];         /**< name of pktio provided to
>> +       char name[PKTIO_NAME_LEN];      /**< name of pktio provided to
>>                                            pktio_open() */
>>  };
>>
>> @@ -106,6 +115,7 @@ extern const pktio_if_ops_t sock_basic_pktio_ops;
>>  extern const pktio_if_ops_t sock_mmsg_pktio_ops;
>>  extern const pktio_if_ops_t sock_mmap_pktio_ops;
>>  extern const pktio_if_ops_t loopback_pktio_ops;
>> +extern const pktio_if_ops_t pcap_pktio_ops;
>>  extern const pktio_if_ops_t * const pktio_if_ops[];
>>
>>  #ifdef __cplusplus
>> diff --git a/platform/linux-generic/odp_packet_io.c
>> b/platform/linux-generic/odp_packet_io.c
>> index c159baf..7eeadd5 100644
>> --- a/platform/linux-generic/odp_packet_io.c
>> +++ b/platform/linux-generic/odp_packet_io.c
>> @@ -187,10 +187,10 @@ static odp_pktio_t setup_pktio_entry(const char
>> *dev, odp_pool_t pool)
>>         int ret = -1;
>>         int pktio_if;
>>
>> -       if (strlen(dev) >= IF_NAMESIZE) {
>> +       if (strlen(dev) >= PKTIO_NAME_LEN) {
>>                 /* ioctl names limitation */
>>                 ODP_ERR("pktio name %s is too big, limit is %d bytes\n",
>> -                       dev, IF_NAMESIZE);
>> +                       dev, PKTIO_NAME_LEN);
>>                 return ODP_PKTIO_INVALID;
>>         }
>>
>> @@ -220,7 +220,7 @@ static odp_pktio_t setup_pktio_entry(const char *dev,
>> odp_pool_t pool)
>>                 id = ODP_PKTIO_INVALID;
>>                 ODP_ERR("Unable to init any I/O type.\n");
>>         } else {
>> -               snprintf(pktio_entry->s.name, IF_NAMESIZE, "%s", dev);
>> +               snprintf(pktio_entry->s.name, PKTIO_NAME_LEN, "%s", dev);
>>                 unlock_entry_classifier(pktio_entry);
>>         }
>>
>> @@ -285,7 +285,7 @@ odp_pktio_t odp_pktio_lookup(const char *dev)
>>                 lock_entry(entry);
>>
>>                 if (!is_free(entry) &&
>> -                   strncmp(entry->s.name, dev, IF_NAMESIZE) == 0)
>> +                   strncmp(entry->s.name, dev, PKTIO_NAME_LEN) == 0)
>>
>>                         id = _odp_cast_scalar(odp_pktio_t, i);
>>
>>                 unlock_entry(entry);
>> diff --git a/platform/linux-generic/pktio/io_ops.c
>> b/platform/linux-generic/pktio/io_ops.c
>> index 6cd3d00..ddcf39e 100644
>> --- a/platform/linux-generic/pktio/io_ops.c
>> +++ b/platform/linux-generic/pktio/io_ops.c
>> @@ -15,5 +15,6 @@ const pktio_if_ops_t * const pktio_if_ops[]  = {
>>         &sock_mmap_pktio_ops,
>>         &sock_mmsg_pktio_ops,
>>         &sock_basic_pktio_ops,
>> +       &pcap_pktio_ops,
>>         NULL
>>  };
>> diff --git a/platform/linux-generic/pktio/pcap.c
>> b/platform/linux-generic/pktio/pcap.c
>> new file mode 100644
>> index 0000000..58dcd6f
>> --- /dev/null
>> +++ b/platform/linux-generic/pktio/pcap.c
>> @@ -0,0 +1,191 @@
>> +/* Copyright (c) 2015, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#ifndef _GNU_SOURCE
>> +#define _GNU_SOURCE
>> +#endif
>> +
>> +#include <odp.h>
>> +#include <odp_packet_internal.h>
>> +#include <odp_packet_io_internal.h>
>> +
>> +#include <pcap/pcap.h>
>> +#include <pcap/bpf.h>
>> +
>> +#define PCAP_DUMPFILE_SUFFIX "_out"
>> +
>> +static int _pcapif_output_fname(char *out, const char *in, size_t len)
>> +{
>> +       char tmp[len];
>> +       int ret, i;
>> +
>> +       strncpy(tmp, in, sizeof(tmp));
>> +
>> +       i = strlen(tmp);
>> +       while (i && tmp[i] != '.')
>> +               i--;
>> +
>> +       if (i) {
>> +               tmp[i] = '\0';
>> +               ret = snprintf(out, len, "%s%s.%s", tmp,
>> +                              PCAP_DUMPFILE_SUFFIX, tmp + i + 1);
>> +       } else {
>> +               ret = snprintf(out, len, "%s%s", tmp,
>> PCAP_DUMPFILE_SUFFIX);
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +static int pcapif_init(odp_pktio_t id ODP_UNUSED, pktio_entry_t
>> *pktio_entry,
>> +                      const char *devname, odp_pool_t pool)
>> +{
>> +       pkt_pcap_t *pkt_pcap = &pktio_entry->s.pkt_pcap;
>> +       const char *fname_rx;
>> +       char errbuf[PCAP_ERRBUF_SIZE];
>> +       int linktype;
>> +
>> +       if (strncmp(devname, "pcap:", 5))
>> +               return -1;
>> +
>> +       fname_rx = devname + 5;
>> +
>> +       pkt_pcap->rx = pcap_open_offline(fname_rx, errbuf);
>> +       if (!pkt_pcap->rx) {
>> +               ODP_ERR("PCAP open failure: %s\n", errbuf);
>> +               return -1;
>> +       }
>> +
>> +       pkt_pcap->pool = pool;
>> +
>> +       linktype = pcap_datalink(pkt_pcap->rx);
>> +       if (linktype != DLT_EN10MB) {
>> +               ODP_ERR("Datalink type not supported: %d\n", linktype);
>> +               return -1;
>> +       }
>> +
>> +       /* By default all packets sent to the pktio will just be freed,
>> but if
>> +        * the ODP_PKTIO_PCAP_DUMP environment variable is set sent
>> packets will
>> +        * instead be saved to a separate output pcap file. */
>> +       if (getenv("ODP_PKTIO_PCAP_DUMP")) {
>> +               char fname_tx[PKTIO_NAME_LEN +
>> sizeof(PCAP_DUMPFILE_SUFFIX)];
>> +
>> +               _pcapif_output_fname(fname_tx, fname_rx,
>> sizeof(fname_tx));
>> +
>> +               pkt_pcap->tx_dump = pcap_dump_open(pkt_pcap->rx,
>> fname_tx);
>> +               if (!pkt_pcap->tx_dump) {
>> +                       ODP_ERR("pcap_dump_open failed\n");
>> +                       return -1;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int pcapif_close(pktio_entry_t *pktio_entry)
>> +{
>> +       pkt_pcap_t *pkt_pcap = &pktio_entry->s.pkt_pcap;
>> +
>> +       if (pkt_pcap->rx)
>> +               pcap_close(pkt_pcap->rx);
>> +
>> +       if (pkt_pcap->tx_dump)
>> +               pcap_dump_close(pkt_pcap->tx_dump);
>> +
>> +       return 0;
>> +}
>> +
>> +static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, odp_packet_t
>> pkts[],
>> +                          unsigned len)
>> +{
>> +       unsigned i;
>> +       struct pcap_pkthdr *pkt_hdr;
>> +       const u_char *pkt_data;
>> +       pkt_pcap_t *pkt_pcap = &pktio_entry->s.pkt_pcap;
>> +       int nbr = 0;
>> +
>> +       for (i = 0; i < len; ++i) {
>> +               if (pcap_next_ex(pkt_pcap->rx, &pkt_hdr, &pkt_data) != 1)
>> +                       break;
>> +
>> +               pkts[i] = odp_packet_alloc(pkt_pcap->pool,
>> pkt_hdr->caplen);
>> +               if (odp_unlikely(pkts[i] == ODP_PACKET_INVALID))
>> +                       break;
>> +
>> +               odp_packet_copydata_in(pkts[i], 0, pkt_hdr->caplen,
>> pkt_data);
>> +               _odp_packet_reset_parse(pkts[i]);
>> +
>> +               nbr++;
>> +       }
>> +
>> +       return nbr;
>> +}
>> +
>> +static void pcapif_dump_pkt(pkt_pcap_t *pkt_pcap, odp_packet_t pkt)
>> +{
>> +       unsigned char *buf;
>> +       struct pcap_pkthdr hdr;
>> +
>> +       if (!pkt_pcap->tx_dump)
>> +               return;
>> +
>> +       hdr.caplen = odp_packet_len(pkt);
>> +       hdr.len = hdr.caplen;
>> +       gettimeofday(&hdr.ts, NULL);
>> +
>> +       buf = malloc(hdr.len);
>> +
>> +       if (odp_packet_copydata_out(pkt, 0, hdr.len, buf) == 0)
>> +               pcap_dump(pkt_pcap->tx_dump, &hdr, buf);
>> +
>> +       free(buf);
>> +}
>> +
>> +static int pcapif_send_pkt(pktio_entry_t *pktio_entry, odp_packet_t
>> pkts[],
>> +                          unsigned len)
>> +{
>> +       pkt_pcap_t *pkt_pcap = &pktio_entry->s.pkt_pcap;
>> +       unsigned i;
>> +
>> +       for (i = 0; i < len; ++i) {
>> +               pcapif_dump_pkt(pkt_pcap, pkts[i]);
>> +               odp_packet_free(pkts[i]);
>> +       }
>> +
>> +       return len;
>> +}
>> +
>> +static int pcapif_mtu_get(pktio_entry_t *pktio_entry ODP_UNUSED)
>> +{
>> +       return 0;
>> +}
>> +
>> +static int pcapif_mac_addr_get(pktio_entry_t *pktio_entry ODP_UNUSED,
>> +                              void *mac_addr ODP_UNUSED)
>> +{
>> +       return 0;
>> +}
>> +
>> +static int pcapif_promisc_mode_set(pktio_entry_t *pktio_entry ODP_UNUSED,
>> +                                  odp_bool_t enable ODP_UNUSED)
>> +{
>> +       return 0;
>> +}
>> +
>> +static int pcapif_promisc_mode_get(pktio_entry_t *pktio_entry ODP_UNUSED)
>> +{
>> +       return 0;
>> +}
>> +
>> +const pktio_if_ops_t pcap_pktio_ops = {
>> +       .open = pcapif_init,
>> +       .close = pcapif_close,
>> +       .recv = pcapif_recv_pkt,
>> +       .send = pcapif_send_pkt,
>> +       .mtu_get = pcapif_mtu_get,
>> +       .promisc_mode_set = pcapif_promisc_mode_set,
>> +       .promisc_mode_get = pcapif_promisc_mode_get,
>> +       .mac_get = pcapif_mac_addr_get
>> +};
>> --
>> 2.1.1
>>
>> _______________________________________________
>> lng-odp mailing list
>> lng-odp@lists.linaro.org
>> https://lists.linaro.org/mailman/listinfo/lng-odp
>>
>
>
>
> --
> Mike Holmes
> Technical Manager - Linaro Networking Group
> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
>
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
>
_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to