On Fri, Sep 27, 2024 at 03:53:49PM +0200, Laurent Vivier wrote: > As for tcp_update_check_tcp4()/tcp_update_check_tcp6(), > change csum_udp4() and csum_udp6() to use an iovec array. > > Signed-off-by: Laurent Vivier Reviewed-by: David Gibson > --- > checksum.c | 29 ++++++++++++++++++----------- > checksum.h | 4 ++-- > tap.c | 14 +++++++++++--- > tap.h | 2 +- > udp.c | 17 +++++++++++++---- > 5 files changed, 45 insertions(+), 21 deletions(-) > > diff --git a/checksum.c b/checksum.c > index cf850196cca0..c673993d6f9c 100644 > --- a/checksum.c > +++ b/checksum.c > @@ -166,22 +166,24 @@ uint32_t proto_ipv4_header_psum(uint16_t l4len, uint8_t protocol, > * @udp4hr: UDP header, initialised apart from checksum > * @saddr: IPv4 source address > * @daddr: IPv4 destination address > - * @payload: UDP packet payload > - * @dlen: Length of @payload (not including UDP header) > + * @iov: Pointer to the array of IO vectors > + * @iov_cnt: Length of the array > + * @offset: UDP payload offset in the iovec array > */ > void csum_udp4(struct udphdr *udp4hr, > struct in_addr saddr, struct in_addr daddr, > - const void *payload, size_t dlen) > + const struct iovec *iov, int iov_cnt, size_t offset) > { > /* UDP checksums are optional, so don't bother */ > udp4hr->check = 0; > > if (UDP4_REAL_CHECKSUMS) { > - uint16_t l4len = dlen + sizeof(struct udphdr); > + uint16_t l4len = iov_size(iov, iov_cnt) - offset + > + sizeof(struct udphdr); > uint32_t psum = proto_ipv4_header_psum(l4len, IPPROTO_UDP, > saddr, daddr); > psum = csum_unfolded(udp4hr, sizeof(struct udphdr), psum); > - udp4hr->check = csum(payload, dlen, psum); > + udp4hr->check = csum_iov(iov, iov_cnt, offset, psum); > } > } > > @@ -227,19 +229,24 @@ uint32_t proto_ipv6_header_psum(uint16_t payload_len, uint8_t protocol, > /** > * csum_udp6() - Calculate and set checksum for a UDP over IPv6 packet > * @udp6hr: UDP header, initialised apart from checksum > - * @payload: UDP packet payload > - * @dlen: Length of @payload (not including UDP header) > + * @saddr: Source address > + * @daddr: Destination address > + * @iov: Pointer to the array of IO vectors > + * @iov_cnt: Length of the array > + * @offset: UDP payload offset in the iovec array > */ > void csum_udp6(struct udphdr *udp6hr, > const struct in6_addr *saddr, const struct in6_addr *daddr, > - const void *payload, size_t dlen) > + const struct iovec *iov, int iov_cnt, size_t offset) > { > - uint32_t psum = proto_ipv6_header_psum(dlen + sizeof(struct udphdr), > - IPPROTO_UDP, saddr, daddr); > + uint16_t l4len = iov_size(iov, iov_cnt) - offset + > + sizeof(struct udphdr); > + uint32_t psum = proto_ipv6_header_psum(l4len, IPPROTO_UDP, > + saddr, daddr); > udp6hr->check = 0; > > psum = csum_unfolded(udp6hr, sizeof(struct udphdr), psum); > - udp6hr->check = csum(payload, dlen, psum); > + udp6hr->check = csum_iov(iov, iov_cnt, offset, psum); > } > > /** > diff --git a/checksum.h b/checksum.h > index 49f7472dd1b6..31ba322fa98c 100644 > --- a/checksum.h > +++ b/checksum.h > @@ -19,14 +19,14 @@ uint32_t proto_ipv4_header_psum(uint16_t l4len, uint8_t protocol, > struct in_addr saddr, struct in_addr daddr); > void csum_udp4(struct udphdr *udp4hr, > struct in_addr saddr, struct in_addr daddr, > - const void *payload, size_t dlen); > + const struct iovec *iov, int iov_cnt, size_t offset); > void csum_icmp4(struct icmphdr *icmp4hr, const void *payload, size_t dlen); > uint32_t proto_ipv6_header_psum(uint16_t payload_len, uint8_t protocol, > const struct in6_addr *saddr, > const struct in6_addr *daddr); > void csum_udp6(struct udphdr *udp6hr, > const struct in6_addr *saddr, const struct in6_addr *daddr, > - const void *payload, size_t dlen); > + const struct iovec *iov, int iov_cnt, size_t offset); > void csum_icmp6(struct icmp6hdr *icmp6hr, > const struct in6_addr *saddr, const struct in6_addr *daddr, > const void *payload, size_t dlen); > diff --git a/tap.c b/tap.c > index 41af6a6d0c85..c53a39b79e62 100644 > --- a/tap.c > +++ b/tap.c > @@ -172,11 +172,15 @@ void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport, > struct iphdr *ip4h = tap_push_l2h(c, buf, ETH_P_IP); > struct udphdr *uh = tap_push_ip4h(ip4h, src, dst, l4len, IPPROTO_UDP); > char *data = (char *)(uh + 1); > + const struct iovec iov = { > + .iov_base = (void *)in, > + .iov_len = dlen > + }; > > uh->source = htons(sport); > uh->dest = htons(dport); > uh->len = htons(l4len); > - csum_udp4(uh, src, dst, in, dlen); > + csum_udp4(uh, src, dst, &iov, 1, 0); > memcpy(data, in, dlen); > > tap_send_single(c, buf, dlen + (data - buf)); > @@ -247,7 +251,7 @@ static void *tap_push_ip6h(struct ipv6hdr *ip6h, > void tap_udp6_send(const struct ctx *c, > const struct in6_addr *src, in_port_t sport, > const struct in6_addr *dst, in_port_t dport, > - uint32_t flow, const void *in, size_t dlen) > + uint32_t flow, void *in, size_t dlen) > { > size_t l4len = dlen + sizeof(struct udphdr); > char buf[USHRT_MAX]; > @@ -255,11 +259,15 @@ void tap_udp6_send(const struct ctx *c, > struct udphdr *uh = tap_push_ip6h(ip6h, src, dst, > l4len, IPPROTO_UDP, flow); > char *data = (char *)(uh + 1); > + const struct iovec iov = { > + .iov_base = in, > + .iov_len = dlen > + }; > > uh->source = htons(sport); > uh->dest = htons(dport); > uh->len = htons(l4len); > - csum_udp6(uh, src, dst, in, dlen); > + csum_udp6(uh, src, dst, &iov, 1, 0); > memcpy(data, in, dlen); > > tap_send_single(c, buf, dlen + (data - buf)); > diff --git a/tap.h b/tap.h > index ec9e2acec460..85f1e8473711 100644 > --- a/tap.h > +++ b/tap.h > @@ -53,7 +53,7 @@ const struct in6_addr *tap_ip6_daddr(const struct ctx *c, > void tap_udp6_send(const struct ctx *c, > const struct in6_addr *src, in_port_t sport, > const struct in6_addr *dst, in_port_t dport, > - uint32_t flow, const void *in, size_t dlen); > + uint32_t flow, void *in, size_t dlen); > void tap_icmp6_send(const struct ctx *c, > const struct in6_addr *src, const struct in6_addr *dst, > const void *in, size_t l4len); > diff --git a/udp.c b/udp.c > index 7b2831386db8..ac34279db253 100644 > --- a/udp.c > +++ b/udp.c > @@ -321,10 +321,15 @@ static size_t udp_update_hdr4(struct iphdr *ip4h, struct udp_payload_t *bp, > bp->uh.source = htons(toside->oport); > bp->uh.dest = htons(toside->eport); > bp->uh.len = htons(l4len); > - if (no_udp_csum) > + if (no_udp_csum) { > bp->uh.check = 0; > - else > - csum_udp4(&bp->uh, *src, *dst, bp->data, dlen); > + } else { > + const struct iovec iov = { > + .iov_base = bp->data, > + .iov_len = dlen > + }; > + csum_udp4(&bp->uh, *src, *dst, &iov, 1, 0); > + } > > return l4len; > } > @@ -363,8 +368,12 @@ static size_t udp_update_hdr6(struct ipv6hdr *ip6h, struct udp_payload_t *bp, > */ > bp->uh.check = 0xffff; > } else { > + const struct iovec iov = { > + .iov_base = bp->data, > + .iov_len = dlen > + }; > csum_udp6(&bp->uh, &toside->oaddr.a6, &toside->eaddr.a6, > - bp->data, dlen); > + &iov, 1, 0); > } > > return l4len; -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson