tcp_update_csum() is now simple enough that it makes sense to just fold it into tcp_fill_header(), meaning the latter now really does fill all the header fields. Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au> --- tcp.c | 66 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/tcp.c b/tcp.c index e9f62a4..88a285b 100644 --- a/tcp.c +++ b/tcp.c @@ -750,23 +750,6 @@ static void tcp_sock_set_bufsize(const struct ctx *c, int s) trace("TCP: failed to set SO_SNDBUF to %i", v); } -/** - * tcp_update_csum() - Calculate TCP checksum - * @psum: Unfolded partial checksum of the IPv4 or IPv6 pseudo-header - * @th: TCP header (updated) - * @iov: IO vector containing the TCP payload - * @iov_cnt: Length of @iov - * @doffset: TCP payload offset in @iov - */ -static void tcp_update_csum(uint32_t psum, struct tcphdr *th, - const struct iovec *iov, int iov_cnt, - size_t doffset) -{ - th->check = 0; - psum = csum_unfolded(th, sizeof(*th), psum); - th->check = csum_iov(iov, iov_cnt, doffset, psum); -} - /** * tcp_opt_get() - Get option, and value if any, from TCP header * @opts: Pointer to start of TCP options in header @@ -860,9 +843,16 @@ void tcp_defer_handler(struct ctx *c) * @th: Pointer to the TCP header structure * @conn: Pointer to the TCP connection structure * @seq: Sequence number + * @ppsum: Pointer to pseudo-header checksum, or NULL to omit checksum + * @iov: IO vector containing the TCP payload + * @iov_cnt: Length of @iov + * @doffset: TCP payload offset in @iov */ static void tcp_fill_header(struct tcphdr *th, - const struct tcp_tap_conn *conn, uint32_t seq) + const struct tcp_tap_conn *conn, uint32_t seq, + const uint32_t *ppsum, + const struct iovec *iov, size_t iov_cnt, + size_t doffset) { const struct flowside *tapside = TAPFLOW(conn); @@ -877,6 +867,11 @@ static void tcp_fill_header(struct tcphdr *th, th->window = htons(MIN(wnd, USHRT_MAX)); } + th->check = 0; + if (ppsum) { + uint32_t sum = csum_unfolded(th, sizeof(*th), *ppsum); + th->check = csum_iov(iov, iov_cnt, doffset, sum); + } } /** @@ -904,6 +899,8 @@ void tcp_fill_headers4(const struct tcp_tap_conn *conn, size_t dlen = iov_size(iov, iov_cnt) - doffset; size_t l4len = dlen + sizeof(*th); size_t l3len = l4len + sizeof(*iph); + const uint32_t *ppsum = NULL; + uint32_t psum; ASSERT(src4 && dst4); @@ -914,17 +911,13 @@ void tcp_fill_headers4(const struct tcp_tap_conn *conn, iph->check = check ? *check : csum_ip4_header(l3len, IPPROTO_TCP, *src4, *dst4); - tcp_fill_header(th, conn, seq); - - if (no_tcp_csum) { - th->check = 0; - } else { - uint32_t psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP, - *src4, *dst4); - - tcp_update_csum(psum, th, iov, iov_cnt, doffset); + if (!no_tcp_csum) { + psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP, *src4, *dst4); + ppsum = &psum; } + tcp_fill_header(th, conn, seq, ppsum, iov, iov_cnt, doffset); + tap_hdr_update(taph, l3len + sizeof(struct ethhdr)); } @@ -950,6 +943,8 @@ void tcp_fill_headers6(const struct tcp_tap_conn *conn, const struct flowside *tapside = TAPFLOW(conn); size_t dlen = iov_size(iov, iov_cnt) - doffset; size_t l4len = dlen + sizeof(*th); + const uint32_t *ppsum = NULL; + uint32_t psum; ip6h->payload_len = htons(l4len); ip6h->saddr = tapside->oaddr.a6; @@ -963,18 +958,15 @@ void tcp_fill_headers6(const struct tcp_tap_conn *conn, ip6h->flow_lbl[1] = (conn->sock >> 8) & 0xff; ip6h->flow_lbl[2] = (conn->sock >> 0) & 0xff; - tcp_fill_header(th, conn, seq); - - if (no_tcp_csum) { - th->check = 0; - } else { - uint32_t psum = proto_ipv6_header_psum(l4len, IPPROTO_TCP, - &ip6h->saddr, - &ip6h->daddr); - - tcp_update_csum(psum, th, iov, iov_cnt, doffset); + if (!no_tcp_csum) { + psum = proto_ipv6_header_psum(l4len, IPPROTO_TCP, + &ip6h->saddr, + &ip6h->daddr); + ppsum = &psum; } + tcp_fill_header(th, conn, seq, ppsum, iov, iov_cnt, doffset); + tap_hdr_update(taph, l4len + sizeof(*ip6h) + sizeof(struct ethhdr)); } -- 2.47.0