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