tap: Don't pcap frames that didn't get sent

In tap_send_frames() we send a number of frames to the tap device, then
also write them to the pcap capture file (if configured).  However the tap
send can partially fail (short write()s or similar), meaning that some
of the requested frames weren't actually sent, but we still write those
frames to the capture file.

We do give a debug message in this case, but it's misleading to add frames
that we know weren't sent to the capture file.  Rework to avoid this.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2023-02-16 16:43:08 +11:00 committed by Stefano Brivio
parent d9577965a3
commit b62ed9ca0e

26
tap.c
View file

@ -309,9 +309,11 @@ void tap_icmp6_send(const struct ctx *c,
* @iov: Array of buffers, each containing one frame * @iov: Array of buffers, each containing one frame
* @n: Number of buffers/frames in @iov * @n: Number of buffers/frames in @iov
* *
* Return: number of frames successfully sent
*
* #syscalls:pasta write * #syscalls:pasta write
*/ */
static void tap_send_frames_pasta(struct ctx *c, static size_t tap_send_frames_pasta(struct ctx *c,
const struct iovec *iov, size_t n) const struct iovec *iov, size_t n)
{ {
size_t i; size_t i;
@ -325,6 +327,8 @@ static void tap_send_frames_pasta(struct ctx *c,
i--; i--;
} }
} }
return n;
} }
/** /**
@ -357,9 +361,11 @@ static void tap_send_remainder(const struct ctx *c, const struct iovec *iov,
* @iov: Array of buffers, each containing one frame * @iov: Array of buffers, each containing one frame
* @n: Number of buffers/frames in @iov * @n: Number of buffers/frames in @iov
* *
* Return: number of frames successfully sent
*
* #syscalls:passt sendmsg * #syscalls:passt sendmsg
*/ */
static void tap_send_frames_passt(const struct ctx *c, static size_t tap_send_frames_passt(const struct ctx *c,
const struct iovec *iov, size_t n) const struct iovec *iov, size_t n)
{ {
struct msghdr mh = { struct msghdr mh = {
@ -371,7 +377,7 @@ static void tap_send_frames_passt(const struct ctx *c,
sent = sendmsg(c->fd_tap, &mh, MSG_NOSIGNAL | MSG_DONTWAIT); sent = sendmsg(c->fd_tap, &mh, MSG_NOSIGNAL | MSG_DONTWAIT);
if (sent < 0) if (sent < 0)
return; return 0;
/* Check for any partial frames due to short send */ /* Check for any partial frames due to short send */
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@ -386,8 +392,7 @@ static void tap_send_frames_passt(const struct ctx *c,
i++; i++;
} }
if (i < n) return i;
debug("tap: dropped %lu frames due to short send", n - i);
} }
/** /**
@ -398,15 +403,20 @@ static void tap_send_frames_passt(const struct ctx *c,
*/ */
void tap_send_frames(struct ctx *c, const struct iovec *iov, size_t n) void tap_send_frames(struct ctx *c, const struct iovec *iov, size_t n)
{ {
size_t m;
if (!n) if (!n)
return; return;
if (c->mode == MODE_PASST) if (c->mode == MODE_PASST)
tap_send_frames_passt(c, iov, n); m = tap_send_frames_passt(c, iov, n);
else else
tap_send_frames_pasta(c, iov, n); m = tap_send_frames_pasta(c, iov, n);
pcap_multiple(iov, n, c->mode == MODE_PASST ? sizeof(uint32_t) : 0); if (m < n)
debug("tap: dropped %lu frames of %lu due to short send", n - m, n);
pcap_multiple(iov, m, c->mode == MODE_PASST ? sizeof(uint32_t) : 0);
} }
/** /**