Introduce a new function pcap_iov() to capture packet desribed by an IO vector. Move packet header writing to to pcap_header() and use it in pcap_frame() and pcap_iov(). Signed-off-by: Laurent Vivier <lvivier(a)redhat.com> --- Notes: v3: - update rational - update comment - use strerror(errno) - use size_t for io vector length v2: - introduce pcap_header(), a common helper to write packet header - use writev() rather than write() in a loop - add functions comment pcap.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++------- pcap.h | 1 + 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/pcap.c b/pcap.c index 501d52d4992b..4e213eea8113 100644 --- a/pcap.c +++ b/pcap.c @@ -20,6 +20,7 @@ #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/uio.h> #include <fcntl.h> #include <time.h> #include <errno.h> @@ -31,6 +32,7 @@ #include "util.h" #include "passt.h" #include "log.h" +#include "iov.h" #define PCAP_VERSION_MINOR 4 @@ -65,6 +67,28 @@ struct pcap_pkthdr { uint32_t len; }; +/* + * pcap_header() - Write a pcap packet header to pcap file + * + * @len: Length of the packet data. + * @tv: Timestamp for the packet. + * + * Return: -1 in case of error, otherwise, 0 to indicate success. + */ +static int pcap_header(size_t len, const struct timeval *tv) +{ + struct pcap_pkthdr h; + + h.tv_sec = tv->tv_sec; + h.tv_usec = tv->tv_usec; + h.caplen = h.len = len; + + if (write(pcap_fd, &h, sizeof(h)) < 0) + return -1; + + return 0; +} + /** * pcap_frame() - Capture a single frame to pcap file with given timestamp * @pkt: Pointer to data buffer, including L2 headers @@ -75,13 +99,7 @@ struct pcap_pkthdr { */ static int pcap_frame(const char *pkt, size_t len, const struct timeval *tv) { - struct pcap_pkthdr h; - - h.tv_sec = tv->tv_sec; - h.tv_usec = tv->tv_usec; - h.caplen = h.len = len; - - if (write(pcap_fd, &h, sizeof(h)) < 0 || write(pcap_fd, pkt, len) < 0) + if (pcap_header(len, tv) < 0 || write(pcap_fd, pkt, len) < 0) return -errno; return 0; @@ -130,6 +148,36 @@ void pcap_multiple(const struct iovec *iov, unsigned int n, size_t offset) } } +/* + * pcap_iov - Write packet data described by a scatter/gather I/O vector (iov) + * to a pcap file descriptor (pcap_fd). + * + * @iov: Pointer to the array of struct iovec describing the scatter/gather + * I/O vector containing packet data to write, including L2 header + * @n: Number of elements in the iov array. + */ +void pcap_iov(const struct iovec *iov, size_t n) +{ + struct timeval tv; + size_t len; + + if (pcap_fd == -1) + return; + + gettimeofday(&tv, NULL); + + len = iov_size(iov, n); + + if (pcap_header(len, &tv) < 0) { + debug("Cannot write pcap header"); + return; + } + + if (writev(pcap_fd, iov, n) < 0) + debug("Cannot log packet using writev(): %s\n", + strerror(errno)); +} + /** * pcap_init() - Initialise pcap file * @c: Execution context diff --git a/pcap.h b/pcap.h index da5a7e846b72..4950f617f4c8 100644 --- a/pcap.h +++ b/pcap.h @@ -8,6 +8,7 @@ void pcap(const char *pkt, size_t len); void pcap_multiple(const struct iovec *iov, unsigned int n, size_t offset); +void pcap_iov(const struct iovec *iov, size_t n); void pcap_init(struct ctx *c); #endif /* PCAP_H */ -- 2.42.0