From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH v2 06/11] udp: Unify udp[46]_l2_iov
Date: Fri, 5 Jul 2024 20:44:04 +1000 [thread overview]
Message-ID: <20240705104409.3847002-7-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20240705104409.3847002-1-david@gibson.dropbear.id.au>
The only differences between these arrays are that udp4_l2_iov is
pre-initialised to point to the IPv4 ethernet header, and IPv4 per-frame
header and udp6_l2_iov points to the IPv6 versions.
We already have to set up a bunch of headers per-frame, including updating
udp[46]_l2_iov[i][UDP_IOV_PAYLOAD].iov_len. It makes more sense to adjust
the IOV entries to point at the correct headers for the frame than to have
two complete sets of iovecs.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
udp.c | 42 +++++++++++++++++++-----------------------
1 file changed, 19 insertions(+), 23 deletions(-)
diff --git a/udp.c b/udp.c
index 2d34f6ac..8729dea2 100644
--- a/udp.c
+++ b/udp.c
@@ -241,8 +241,7 @@ static struct iovec udp_iov_splice [UDP_MAX_FRAMES];
static struct mmsghdr udp_mh_splice [UDP_MAX_FRAMES];
/* IOVs for L2 frames */
-static struct iovec udp4_l2_iov [UDP_MAX_FRAMES][UDP_NUM_IOVS];
-static struct iovec udp6_l2_iov [UDP_MAX_FRAMES][UDP_NUM_IOVS];
+static struct iovec udp_l2_iov [UDP_MAX_FRAMES][UDP_NUM_IOVS];
/**
@@ -305,8 +304,9 @@ void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s)
static void udp_iov_init_one(const struct ctx *c, size_t i)
{
struct udp_payload_t *payload = &udp_payload[i];
- struct iovec *siov = &udp_iov_recv[i];
struct udp_meta_t *meta = &udp_meta[i];
+ struct iovec *siov = &udp_iov_recv[i];
+ struct iovec *tiov = udp_l2_iov[i];
*meta = (struct udp_meta_t) {
.ip4h = L2_BUF_IP4_INIT(IPPROTO_UDP),
@@ -317,34 +317,29 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
udp4_eth_hdr.h_proto = htons_constant(ETH_P_IP);
udp6_eth_hdr.h_proto = htons_constant(ETH_P_IPV6);
+ tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph);
+ tiov[UDP_IOV_PAYLOAD].iov_base = payload;
+
+ /* It's useful to have separate msghdr arrays for receiving. Otherwise,
+ * an IPv4 recv() will alter msg_namelen, so we'd have to reset it every
+ * time or risk truncating the address on future IPv6 recv()s.
+ */
if (c->ifi4) {
struct msghdr *mh = &udp4_mh_recv[i].msg_hdr;
- struct iovec *tiov = udp4_l2_iov[i];
mh->msg_name = &meta->s_in;
mh->msg_namelen = sizeof(struct sockaddr_in);
mh->msg_iov = siov;
mh->msg_iovlen = 1;
-
- tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph);
- tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr);
- tiov[UDP_IOV_IP] = IOV_OF_LVALUE(meta->ip4h);
- tiov[UDP_IOV_PAYLOAD].iov_base = payload;
}
if (c->ifi6) {
struct msghdr *mh = &udp6_mh_recv[i].msg_hdr;
- struct iovec *tiov = udp6_l2_iov[i];
mh->msg_name = &meta->s_in;
mh->msg_namelen = sizeof(struct sockaddr_in6);
mh->msg_iov = siov;
mh->msg_iovlen = 1;
-
- tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph);
- tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr);
- tiov[UDP_IOV_IP] = IOV_OF_LVALUE(meta->ip6h);
- tiov[UDP_IOV_PAYLOAD].iov_base = payload;
}
}
@@ -729,22 +724,19 @@ static unsigned udp_tap_send(const struct ctx *c, size_t start, size_t n,
in_port_t dstport, union epoll_ref ref,
const struct timespec *now)
{
- struct iovec (*tap_iov)[UDP_NUM_IOVS];
struct mmsghdr *mmh_recv;
size_t i = start;
ASSERT(udp_meta[start].splicesrc == -1);
ASSERT(ref.type == EPOLL_TYPE_UDP);
- if (ref.udp.v6) {
- tap_iov = udp6_l2_iov;
+ if (ref.udp.v6)
mmh_recv = udp6_mh_recv;
- } else {
+ else
mmh_recv = udp4_mh_recv;
- tap_iov = udp4_l2_iov;
- }
do {
+ struct iovec (*tap_iov)[UDP_NUM_IOVS] = &udp_l2_iov[i];
struct udp_payload_t *bp = &udp_payload[i];
struct udp_meta_t *bm = &udp_meta[i];
size_t l4len;
@@ -755,14 +747,18 @@ static unsigned udp_tap_send(const struct ctx *c, size_t start, size_t n,
udp6_mh_recv[i].msg_len, now);
tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip6h) +
sizeof(udp6_eth_hdr));
+ (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr);
+ (*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip6h);
} else {
l4len = udp_update_hdr4(c, &bm->ip4h,
&bm->s_in.sa4, bp, dstport,
udp4_mh_recv[i].msg_len, now);
tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip4h) +
sizeof(udp4_eth_hdr));
+ (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr);
+ (*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip4h);
}
- tap_iov[i][UDP_IOV_PAYLOAD].iov_len = l4len;
+ (*tap_iov)[UDP_IOV_PAYLOAD].iov_len = l4len;
if (++i >= n)
break;
@@ -770,7 +766,7 @@ static unsigned udp_tap_send(const struct ctx *c, size_t start, size_t n,
udp_meta[i].splicesrc = udp_mmh_splice_port(ref, &mmh_recv[i]);
} while (udp_meta[i].splicesrc == -1);
- tap_send_frames(c, &tap_iov[start][0], UDP_NUM_IOVS, i - start);
+ tap_send_frames(c, &udp_l2_iov[start][0], UDP_NUM_IOVS, i - start);
return i - start;
}
--
@@ -241,8 +241,7 @@ static struct iovec udp_iov_splice [UDP_MAX_FRAMES];
static struct mmsghdr udp_mh_splice [UDP_MAX_FRAMES];
/* IOVs for L2 frames */
-static struct iovec udp4_l2_iov [UDP_MAX_FRAMES][UDP_NUM_IOVS];
-static struct iovec udp6_l2_iov [UDP_MAX_FRAMES][UDP_NUM_IOVS];
+static struct iovec udp_l2_iov [UDP_MAX_FRAMES][UDP_NUM_IOVS];
/**
@@ -305,8 +304,9 @@ void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s)
static void udp_iov_init_one(const struct ctx *c, size_t i)
{
struct udp_payload_t *payload = &udp_payload[i];
- struct iovec *siov = &udp_iov_recv[i];
struct udp_meta_t *meta = &udp_meta[i];
+ struct iovec *siov = &udp_iov_recv[i];
+ struct iovec *tiov = udp_l2_iov[i];
*meta = (struct udp_meta_t) {
.ip4h = L2_BUF_IP4_INIT(IPPROTO_UDP),
@@ -317,34 +317,29 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
udp4_eth_hdr.h_proto = htons_constant(ETH_P_IP);
udp6_eth_hdr.h_proto = htons_constant(ETH_P_IPV6);
+ tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph);
+ tiov[UDP_IOV_PAYLOAD].iov_base = payload;
+
+ /* It's useful to have separate msghdr arrays for receiving. Otherwise,
+ * an IPv4 recv() will alter msg_namelen, so we'd have to reset it every
+ * time or risk truncating the address on future IPv6 recv()s.
+ */
if (c->ifi4) {
struct msghdr *mh = &udp4_mh_recv[i].msg_hdr;
- struct iovec *tiov = udp4_l2_iov[i];
mh->msg_name = &meta->s_in;
mh->msg_namelen = sizeof(struct sockaddr_in);
mh->msg_iov = siov;
mh->msg_iovlen = 1;
-
- tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph);
- tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr);
- tiov[UDP_IOV_IP] = IOV_OF_LVALUE(meta->ip4h);
- tiov[UDP_IOV_PAYLOAD].iov_base = payload;
}
if (c->ifi6) {
struct msghdr *mh = &udp6_mh_recv[i].msg_hdr;
- struct iovec *tiov = udp6_l2_iov[i];
mh->msg_name = &meta->s_in;
mh->msg_namelen = sizeof(struct sockaddr_in6);
mh->msg_iov = siov;
mh->msg_iovlen = 1;
-
- tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph);
- tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr);
- tiov[UDP_IOV_IP] = IOV_OF_LVALUE(meta->ip6h);
- tiov[UDP_IOV_PAYLOAD].iov_base = payload;
}
}
@@ -729,22 +724,19 @@ static unsigned udp_tap_send(const struct ctx *c, size_t start, size_t n,
in_port_t dstport, union epoll_ref ref,
const struct timespec *now)
{
- struct iovec (*tap_iov)[UDP_NUM_IOVS];
struct mmsghdr *mmh_recv;
size_t i = start;
ASSERT(udp_meta[start].splicesrc == -1);
ASSERT(ref.type == EPOLL_TYPE_UDP);
- if (ref.udp.v6) {
- tap_iov = udp6_l2_iov;
+ if (ref.udp.v6)
mmh_recv = udp6_mh_recv;
- } else {
+ else
mmh_recv = udp4_mh_recv;
- tap_iov = udp4_l2_iov;
- }
do {
+ struct iovec (*tap_iov)[UDP_NUM_IOVS] = &udp_l2_iov[i];
struct udp_payload_t *bp = &udp_payload[i];
struct udp_meta_t *bm = &udp_meta[i];
size_t l4len;
@@ -755,14 +747,18 @@ static unsigned udp_tap_send(const struct ctx *c, size_t start, size_t n,
udp6_mh_recv[i].msg_len, now);
tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip6h) +
sizeof(udp6_eth_hdr));
+ (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr);
+ (*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip6h);
} else {
l4len = udp_update_hdr4(c, &bm->ip4h,
&bm->s_in.sa4, bp, dstport,
udp4_mh_recv[i].msg_len, now);
tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip4h) +
sizeof(udp4_eth_hdr));
+ (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr);
+ (*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip4h);
}
- tap_iov[i][UDP_IOV_PAYLOAD].iov_len = l4len;
+ (*tap_iov)[UDP_IOV_PAYLOAD].iov_len = l4len;
if (++i >= n)
break;
@@ -770,7 +766,7 @@ static unsigned udp_tap_send(const struct ctx *c, size_t start, size_t n,
udp_meta[i].splicesrc = udp_mmh_splice_port(ref, &mmh_recv[i]);
} while (udp_meta[i].splicesrc == -1);
- tap_send_frames(c, &tap_iov[start][0], UDP_NUM_IOVS, i - start);
+ tap_send_frames(c, &udp_l2_iov[start][0], UDP_NUM_IOVS, i - start);
return i - start;
}
--
2.45.2
next prev parent reply other threads:[~2024-07-05 10:44 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-05 10:43 [PATCH v2 00/11] Preliminaries for UDP flow support David Gibson
2024-07-05 10:43 ` [PATCH v2 01/11] util: sock_l4() determine protocol from epoll type rather than the reverse David Gibson
2024-07-05 10:44 ` [PATCH v2 02/11] flow: Add flow_sidx_valid() helper David Gibson
2024-07-05 10:44 ` [PATCH v2 03/11] udp: Pass full epoll reference through more of sock handler path David Gibson
2024-07-05 10:44 ` [PATCH v2 04/11] udp: Rename IOV and mmsghdr arrays David Gibson
2024-07-05 10:44 ` [PATCH v2 05/11] udp: Unify udp[46]_mh_splice David Gibson
2024-07-05 10:44 ` David Gibson [this message]
2024-07-05 10:44 ` [PATCH v2 07/11] udp: Don't repeatedly initialise udp[46]_eth_hdr David Gibson
2024-07-05 10:44 ` [PATCH v2 08/11] udp: Move some more of sock_handler tasks into sub-functions David Gibson
2024-07-05 10:44 ` [PATCH v2 09/11] udp: Consolidate datagram batching David Gibson
2024-07-05 10:44 ` [PATCH v2 10/11] doc: Add program to document and test assumptions about SO_REUSEADDR David Gibson
2024-07-12 11:42 ` David Taylor
2024-07-15 0:43 ` David Gibson
2024-07-05 10:44 ` [PATCH v2 11/11] doc: Test behaviour of zero length datagram recv()s David Gibson
2024-07-05 16:38 ` [PATCH v2 00/11] Preliminaries for UDP flow support Stefano Brivio
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240705104409.3847002-7-david@gibson.dropbear.id.au \
--to=david@gibson.dropbear.id.au \
--cc=passt-dev@passt.top \
--cc=sbrivio@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).