diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2024-09-06 21:49:38 +1000 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2024-09-06 13:56:43 +0200 |
commit | d2a1dc744b10d3e5253149a2520db9967f9f20d5 (patch) | |
tree | 0667966efddf262ac9c37f376fd36167fa6576dd | |
parent | 11e29054fe91ceaf59d2a500e09c4da262c7b23e (diff) | |
download | passt-d2a1dc744b10d3e5253149a2520db9967f9f20d5.tar passt-d2a1dc744b10d3e5253149a2520db9967f9f20d5.tar.gz passt-d2a1dc744b10d3e5253149a2520db9967f9f20d5.tar.bz2 passt-d2a1dc744b10d3e5253149a2520db9967f9f20d5.tar.lz passt-d2a1dc744b10d3e5253149a2520db9967f9f20d5.tar.xz passt-d2a1dc744b10d3e5253149a2520db9967f9f20d5.tar.zst passt-d2a1dc744b10d3e5253149a2520db9967f9f20d5.zip |
tap: Restructure in tap_pasta_input()
tap_pasta_input() has a rather confusing structure, using two gotos.
Remove these by restructuring the function to have the main loop condition
based on filling our buffer space, with errors or running out of data
treated as the exception, rather than the other way around. This allows
us to handle the EINTR which triggered the 'restart' goto with a continue.
The outer 'redo' was triggered if we completely filled our buffer, to flush
it and do another pass. This one is unnecessary since we don't (yet) use
EPOLLET on the tap device: if there's still more data we'll get another
event and re-enter the loop.
Along the way handle a couple of extra edge cases:
- Check for EWOULDBLOCK as well as EAGAIN for the benefit of any future
ports where those might not have the same value
- Detect EOF on the tap device and exit in that case
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r-- | tap.c | 45 |
1 files changed, 19 insertions, 26 deletions
@@ -1073,42 +1073,35 @@ void tap_handler_passt(struct ctx *c, uint32_t events, static void tap_pasta_input(struct ctx *c, const struct timespec *now) { ssize_t n, len; - int ret; - -redo: - n = 0; tap_flush_pools(); -restart: - while ((len = read(c->fd_tap, pkt_buf + n, TAP_BUF_BYTES - n)) > 0) { - if (len < (ssize_t)sizeof(struct ethhdr) || - len > (ssize_t)ETH_MAX_MTU) { - n += len; - continue; - } + for (n = 0; n < (ssize_t)TAP_BUF_BYTES; n += len) { + len = read(c->fd_tap, pkt_buf + n, TAP_BUF_BYTES - n); + if (len == 0) { + die("EOF on tap device, exiting"); + } else if (len < 0) { + if (errno == EINTR) { + len = 0; + continue; + } - tap_add_packet(c, len, pkt_buf + n); + if (errno == EAGAIN && errno == EWOULDBLOCK) + break; /* all done for now */ - if ((n += len) == TAP_BUF_BYTES) - break; - } + die("Error on tap device, exiting"); + } - if (len < 0 && errno == EINTR) - goto restart; + /* Ignore frames of bad length */ + if (len < (ssize_t)sizeof(struct ethhdr) || + len > (ssize_t)ETH_MAX_MTU) + continue; - ret = errno; + tap_add_packet(c, len, pkt_buf + n); + } tap_handler(c, now); - - if (len > 0 || ret == EAGAIN) - return; - - if (n == TAP_BUF_BYTES) - goto redo; - - die("Error on tap device, exiting"); } /** |