From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from gandalf.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 6CC785A0277 for ; Fri, 8 Mar 2024 07:53:33 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202312; t=1709880807; bh=FWO0IcNh2v3xFCBuAgsQZ8QJnHdMaTuZ3DX7EjQEz00=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ls+WtUHK162xwtz10AJgfV5dijyaoeMYLFU0q6tEYsG3tds4kezI0DtzGykvVhZjJ vWKF6AGJokAMJtORH4W7Si9VJvQ1MFhhFb2mOYYZy3Zy1vbxjYcEzxWFwCs2vcOncu xyFP79A9kgZsCT1HBQ4xQa5IadIFXrhX5Utp2app9u7W0cjyzt97WIVeHUS47TWwli Rvkoe2tbg480pCKh3weZmagbhJdDJaTisUrEfAdDcr2R1+CZSXlOEIg+90wkuDpkjZ QOoCLYp1ffkOpvSmNhnwcRJSlZi4SdtjKYksowHkveWVlyfqJivDa0yO430QGaOHom u38YdEOpeGtiA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4TrcMC5J7Tz4wxZ; Fri, 8 Mar 2024 17:53:27 +1100 (AEDT) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH 3/4] tap: Implement tap_send() "slow path" in terms of fast path Date: Fri, 8 Mar 2024 17:53:24 +1100 Message-ID: <20240308065325.2181322-4-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240308065325.2181322-1-david@gibson.dropbear.id.au> References: <20240308065325.2181322-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: VTKDBF3ZZDAWD7NUL2RHQ35NADTCDLJT X-Message-ID-Hash: VTKDBF3ZZDAWD7NUL2RHQ35NADTCDLJT X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Laurent Vivier , David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Most times we send frames to the guest it goes via tap_send_frames(). However "slow path" protocols - ARP, ICMP, ICMPv6, DHCP and DHCPv6 - go via tap_send(). As well as being a semantic duplication, tap_send() contains at least one serious problem: it doesn't properly handle short sends, which can be fatal on the qemu socket connection, since frame boundaries will get out of sync. Rewrite tap_send() to call tap_send_frames(). While we're there, rename it tap_send_single() for clarity. Signed-off-by: David Gibson --- arp.c | 4 +--- tap.c | 38 +++++++++++++++++--------------------- tap.h | 2 +- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/arp.c b/arp.c index a35c1b61..113cda2f 100644 --- a/arp.c +++ b/arp.c @@ -44,7 +44,6 @@ int arp(const struct ctx *c, const struct pool *p) struct arphdr *ah; struct arpmsg *am; size_t len; - int ret; eh = packet_get(p, 0, 0, sizeof(*eh), NULL); ah = packet_get(p, 0, sizeof(*eh), sizeof(*ah), NULL); @@ -83,8 +82,7 @@ int arp(const struct ctx *c, const struct pool *p) memcpy(eh->h_dest, eh->h_source, sizeof(eh->h_dest)); memcpy(eh->h_source, c->mac, sizeof(eh->h_source)); - if ((ret = tap_send(c, eh, len)) < 0) - warn("ARP: send: %s", strerror(ret)); + tap_send_single(c, eh, len); return 1; } diff --git a/tap.c b/tap.c index 38965842..5e3c6b13 100644 --- a/tap.c +++ b/tap.c @@ -67,28 +67,28 @@ static PACKET_POOL_NOINIT(pool_tap6, TAP_MSGS, pkt_buf); #define FRAGMENT_MSG_RATE 10 /* # seconds between fragment warnings */ /** - * tap_send() - Send frame, with qemu socket header if needed + * tap_send_single() - Send a single frame * @c: Execution context * @data: Packet buffer * @len: Total L2 packet length - * - * Return: return code from send() or write() */ -int tap_send(const struct ctx *c, const void *data, size_t len) +void tap_send_single(const struct ctx *c, const void *data, size_t len) { - pcap(data, len); + uint32_t vnet_len = htonl(len); + struct iovec iov[2]; + size_t iovcnt = 0; if (c->mode == MODE_PASST) { - int flags = MSG_NOSIGNAL | MSG_DONTWAIT; - uint32_t vnet_len = htonl(len); - - if (send(c->fd_tap, &vnet_len, 4, flags) < 0) - return -1; - - return send(c->fd_tap, data, len, flags); + iov[iovcnt].iov_base = &vnet_len; + iov[iovcnt].iov_len = sizeof(vnet_len); + iovcnt++; } - return write(c->fd_tap, (char *)data, len); + iov[iovcnt].iov_base = (void *)data; + iov[iovcnt].iov_len = len; + iovcnt++; + + tap_send_frames(c, iov, iovcnt, 1); } /** @@ -189,8 +189,7 @@ void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport, csum_udp4(uh, src, dst, in, len); memcpy(data, in, len); - if (tap_send(c, buf, len + (data - buf)) < 0) - debug("tap: failed to send %zu bytes (IPv4)", len); + tap_send_single(c, buf, len + (data - buf)); } /** @@ -212,8 +211,7 @@ void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst, memcpy(icmp4h, in, len); csum_icmp4(icmp4h, icmp4h + 1, len - sizeof(*icmp4h)); - if (tap_send(c, buf, len + ((char *)icmp4h - buf)) < 0) - debug("tap: failed to send %zu bytes (IPv4)", len); + tap_send_single(c, buf, len + ((char *)icmp4h - buf)); } /** @@ -274,8 +272,7 @@ void tap_udp6_send(const struct ctx *c, csum_udp6(uh, src, dst, in, len); memcpy(data, in, len); - if (tap_send(c, buf, len + (data - buf)) < 1) - debug("tap: failed to send %zu bytes (IPv6)", len); + tap_send_single(c, buf, len + (data - buf)); } /** @@ -298,8 +295,7 @@ void tap_icmp6_send(const struct ctx *c, memcpy(icmp6h, in, len); csum_icmp6(icmp6h, src, dst, icmp6h + 1, len - sizeof(*icmp6h)); - if (tap_send(c, buf, len + ((char *)icmp6h - buf)) < 1) - debug("tap: failed to send %zu bytes (IPv6)", len); + tap_send_single(c, buf, len + ((char *)icmp6h - buf)); } /** diff --git a/tap.h b/tap.h index c45aab3e..aa3b1af2 100644 --- a/tap.h +++ b/tap.h @@ -72,7 +72,7 @@ void tap_udp6_send(const struct ctx *c, void tap_icmp6_send(const struct ctx *c, const struct in6_addr *src, const struct in6_addr *dst, const void *in, size_t len); -int tap_send(const struct ctx *c, const void *data, size_t len); +void tap_send_single(const struct ctx *c, const void *data, size_t len); 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, -- 2.44.0