diff options
| author | Jon Maloy <jmaloy@redhat.com> | 2025-11-26 19:53:16 -0500 |
|---|---|---|
| committer | Stefano Brivio <sbrivio@redhat.com> | 2025-11-27 22:29:25 +0100 |
| commit | 2002c7d39c9d4fa01099d7f780b66cfb213b6454 (patch) | |
| tree | 3358e60e554c0bb8f5e9781fdc2d3d6a9b853127 | |
| parent | 391c15afedacbc4c5e01bfd05ef73be5ab1770ac (diff) | |
| download | passt-2002c7d39c9d4fa01099d7f780b66cfb213b6454.tar passt-2002c7d39c9d4fa01099d7f780b66cfb213b6454.tar.gz passt-2002c7d39c9d4fa01099d7f780b66cfb213b6454.tar.bz2 passt-2002c7d39c9d4fa01099d7f780b66cfb213b6454.tar.lz passt-2002c7d39c9d4fa01099d7f780b66cfb213b6454.tar.xz passt-2002c7d39c9d4fa01099d7f780b66cfb213b6454.tar.zst passt-2002c7d39c9d4fa01099d7f780b66cfb213b6454.zip | |
arp/ndp: don't send messages on uninitialized tap interface
When running pasta without --config-net, the tap interface is opened
and assigned a valid file descriptor, but intentionally not brought
up in the namespace. This is the expected behavior when the user wants
to configure the namespace manually.
However, in PASTA mode the code is attempting to send ARP announcements
and NDP messages (initial requests and unsolicited NAs) based solely on
whether c->fd_tap is valid, without checking if the interface actually
is up and ready to transmit. This results in send failures, and when
debug is activated (pasta -d) we see error printouts for these early
messages.
We now add new function tap_is_ready() which checks both conditions:
- Whether fd_tap is valid (all modes)
- Whether the tap interface is up (pasta mode only). In this mode, we
use the existing c->pasta_conf_ns flag, which indicates whether
pasta_ns_conf() configured and brought up the interface. This test
is simple, and good enough for now.
We update all functions that send unsolicited ARP/NDP messages to
check with the new function before making any send attempt.
This eliminates spurious send errors when starting pasta without
--config-net, while preserving correct behavior when the interface
is properly initialized.
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
| -rw-r--r-- | arp.c | 3 | ||||
| -rw-r--r-- | ndp.c | 5 | ||||
| -rw-r--r-- | tap.c | 27 | ||||
| -rw-r--r-- | tap.h | 1 |
4 files changed, 34 insertions, 2 deletions
@@ -168,6 +168,9 @@ void arp_announce(const struct ctx *c, struct in_addr *ip, struct arpmsg am; } __attribute__((__packed__)) msg; + if (!tap_is_ready(c)) + return; + /* Ethernet header */ msg.eh.h_proto = htons(ETH_P_ARP); memcpy(msg.eh.h_dest, MAC_BROADCAST, sizeof(msg.eh.h_dest)); @@ -227,7 +227,8 @@ static void ndp_na(const struct ctx *c, const struct in6_addr *dst, */ void ndp_unsolicited_na(const struct ctx *c, const struct in6_addr *addr) { - ndp_na(c, &in6addr_ll_all_nodes, addr); + if (tap_is_ready(c)) + ndp_na(c, &in6addr_ll_all_nodes, addr); } /** @@ -411,7 +412,7 @@ void ndp_timer(const struct ctx *c, const struct timespec *now) time_t max_rtr_adv_interval = DEFAULT_MAX_RTR_ADV_INTERVAL; time_t min_rtr_adv_interval, interval; - if (c->fd_tap < 0 || c->no_ra || now->tv_sec < next_ra) + if (!tap_is_ready(c) || c->no_ra || now->tv_sec < next_ra) return; /* We must advertise before the route's lifetime expires */ @@ -1340,6 +1340,30 @@ static void tap_sock_unix_init(const struct ctx *c) } /** + * tap_is_ready() - Check if tap interface is ready to send packets + * @c: Execution context + * + * For pasta mode, checks if the tap interface is up. + * For other modes, just checks if fd_tap is valid. + * + * Return: true if ready, false otherwise + */ +bool tap_is_ready(const struct ctx *c) +{ + if (c->fd_tap < 0) + return false; + + if (c->mode == MODE_PASTA) { + /* If pasta_conf_ns is set, the interface was configured and + * brought up during initialization. If not, it's still down. + */ + return c->pasta_conf_ns; + } + + return true; +} + +/** * tap_start_connection() - start a new connection * @c: Execution context */ @@ -1362,6 +1386,9 @@ static void tap_start_connection(const struct ctx *c) epoll_add(c->epollfd, EPOLLIN | EPOLLRDHUP, ref); + if (!tap_is_ready(c)) + return; + if (c->ifi4) arp_send_init_req(c); if (c->ifi6 && !c->no_ndp) @@ -109,6 +109,7 @@ size_t tap_send_frames(const struct ctx *c, const struct iovec *iov, size_t bufs_per_frame, size_t nframes); void eth_update_mac(struct ethhdr *eh, const unsigned char *eth_d, const unsigned char *eth_s); +bool tap_is_ready(const struct ctx *c); void tap_listen_handler(struct ctx *c, uint32_t events); void tap_handler_pasta(struct ctx *c, uint32_t events, const struct timespec *now); |
