1
0
mirror of https://passt.top/passt synced 2024-12-22 05:35:23 +00:00

tcp: Merge tcp_fill_headers[46]() with each other

We have different versions of this function for IPv4 and IPv6, but the
caller already requires some IP version specific code to get the right
header pointers.  Instead, have a common function that fills either an
IPv4 or an IPv6 header based on which header pointer it is passed.  This
allows us to remove a small amount of code duplication and make a few
slightly ugly conditionals.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-11-27 14:54:09 +11:00 committed by Stefano Brivio
parent 2abf5ab7f3
commit a6348cad51
4 changed files with 83 additions and 105 deletions

124
tcp.c
View File

@ -877,96 +877,84 @@ static void tcp_fill_header(struct tcphdr *th,
} }
/** /**
* tcp_fill_headers4() - Fill 802.3, IPv4, TCP headers in pre-cooked buffers * tcp_fill_headers() - Fill 802.3, IP, TCP headers
* @conn: Connection pointer * @conn: Connection pointer
* @taph: tap backend specific header * @taph: tap backend specific header
* @iph: Pointer to IPv4 header * @ip4h: Pointer to IPv4 header, or NULL
* @ip6h: Pointer to IPv6 header, or NULL
* @th: Pointer to TCP header * @th: Pointer to TCP header
* @payload: TCP payload * @payload: TCP payload
* @check: Checksum, if already known * @ip4_check: IPv4 checksum, if already known
* @seq: Sequence number for this segment * @seq: Sequence number for this segment
* @no_tcp_csum: Do not set TCP checksum * @no_tcp_csum: Do not set TCP checksum
*/ */
void tcp_fill_headers4(const struct tcp_tap_conn *conn, void tcp_fill_headers(const struct tcp_tap_conn *conn,
struct tap_hdr *taph, struct iphdr *iph, struct tap_hdr *taph,
struct tcphdr *th, struct iov_tail *payload, struct iphdr *ip4h, struct ipv6hdr *ip6h,
const uint16_t *check, uint32_t seq, bool no_tcp_csum) struct tcphdr *th, struct iov_tail *payload,
const uint16_t *ip4_check, uint32_t seq, bool no_tcp_csum)
{ {
const struct flowside *tapside = TAPFLOW(conn); const struct flowside *tapside = TAPFLOW(conn);
const struct in_addr *src4 = inany_v4(&tapside->oaddr);
const struct in_addr *dst4 = inany_v4(&tapside->eaddr);
size_t l4len = iov_tail_size(payload) + sizeof(*th); size_t l4len = iov_tail_size(payload) + sizeof(*th);
size_t l3len = l4len + sizeof(*iph); size_t l3len = l4len;
uint32_t psum = 0;
ASSERT(src4 && dst4); if (ip4h) {
const struct in_addr *src4 = inany_v4(&tapside->oaddr);
const struct in_addr *dst4 = inany_v4(&tapside->eaddr);
iph->tot_len = htons(l3len); ASSERT(src4 && dst4);
iph->saddr = src4->s_addr;
iph->daddr = dst4->s_addr;
iph->check = check ? *check : l3len += + sizeof(*ip4h);
csum_ip4_header(l3len, IPPROTO_TCP, *src4, *dst4);
ip4h->tot_len = htons(l3len);
ip4h->saddr = src4->s_addr;
ip4h->daddr = dst4->s_addr;
if (ip4_check)
ip4h->check = *ip4_check;
else
ip4h->check = csum_ip4_header(l3len, IPPROTO_TCP,
*src4, *dst4);
if (!no_tcp_csum) {
psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP,
*src4, *dst4);
}
}
if (ip6h) {
l3len += sizeof(*ip6h);
ip6h->payload_len = htons(l4len);
ip6h->saddr = tapside->oaddr.a6;
ip6h->daddr = tapside->eaddr.a6;
ip6h->hop_limit = 255;
ip6h->version = 6;
ip6h->nexthdr = IPPROTO_TCP;
ip6h->flow_lbl[0] = (conn->sock >> 16) & 0xf;
ip6h->flow_lbl[1] = (conn->sock >> 8) & 0xff;
ip6h->flow_lbl[2] = (conn->sock >> 0) & 0xff;
if (!no_tcp_csum) {
psum = proto_ipv6_header_psum(l4len, IPPROTO_TCP,
&ip6h->saddr,
&ip6h->daddr);
}
}
tcp_fill_header(th, conn, seq); tcp_fill_header(th, conn, seq);
if (no_tcp_csum) { if (no_tcp_csum)
th->check = 0; th->check = 0;
} else { else
uint32_t psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP,
*src4, *dst4);
tcp_update_csum(psum, th, payload); tcp_update_csum(psum, th, payload);
}
tap_hdr_update(taph, l3len + sizeof(struct ethhdr)); tap_hdr_update(taph, l3len + sizeof(struct ethhdr));
} }
/**
* tcp_fill_headers6() - Fill 802.3, IPv6, TCP headers in pre-cooked buffers
* @conn: Connection pointer
* @taph: tap backend specific header
* @ip6h: Pointer to IPv6 header
* @th: Pointer to TCP header
* @payload: TCP payload
* @check: Checksum, if already known
* @seq: Sequence number for this segment
* @no_tcp_csum: Do not set TCP checksum
*/
void tcp_fill_headers6(const struct tcp_tap_conn *conn,
struct tap_hdr *taph, struct ipv6hdr *ip6h,
struct tcphdr *th, struct iov_tail *payload,
uint32_t seq, bool no_tcp_csum)
{
size_t l4len = iov_tail_size(payload) + sizeof(*th);
const struct flowside *tapside = TAPFLOW(conn);
ip6h->payload_len = htons(l4len);
ip6h->saddr = tapside->oaddr.a6;
ip6h->daddr = tapside->eaddr.a6;
ip6h->hop_limit = 255;
ip6h->version = 6;
ip6h->nexthdr = IPPROTO_TCP;
ip6h->flow_lbl[0] = (conn->sock >> 16) & 0xf;
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, payload);
}
tap_hdr_update(taph, l4len + sizeof(*ip6h) + sizeof(struct ethhdr));
}
/** /**
* tcp_update_seqack_wnd() - Update ACK sequence and window to guest/tap * tcp_update_seqack_wnd() - Update ACK sequence and window to guest/tap
* @c: Execution context * @c: Execution context

View File

@ -161,18 +161,19 @@ static void tcp_l2_buf_fill_headers(const struct tcp_tap_conn *conn,
{ {
struct iov_tail tail = IOV_TAIL(&iov[TCP_IOV_PAYLOAD], 1, 0); struct iov_tail tail = IOV_TAIL(&iov[TCP_IOV_PAYLOAD], 1, 0);
struct tcphdr *th = IOV_REMOVE_HEADER(&tail, struct tcphdr); struct tcphdr *th = IOV_REMOVE_HEADER(&tail, struct tcphdr);
struct tap_hdr *taph = iov[TCP_IOV_TAP].iov_base;
const struct flowside *tapside = TAPFLOW(conn); const struct flowside *tapside = TAPFLOW(conn);
const struct in_addr *a4 = inany_v4(&tapside->oaddr); const struct in_addr *a4 = inany_v4(&tapside->oaddr);
struct ipv6hdr *ip6h = NULL;
struct iphdr *ip4h = NULL;
if (a4) { if (a4)
tcp_fill_headers4(conn, iov[TCP_IOV_TAP].iov_base, ip4h = iov[TCP_IOV_IP].iov_base;
iov[TCP_IOV_IP].iov_base, th, else
&tail, check, seq, no_tcp_csum); ip6h = iov[TCP_IOV_IP].iov_base;
} else {
tcp_fill_headers6(conn, iov[TCP_IOV_TAP].iov_base, tcp_fill_headers(conn, taph, ip4h, ip6h, th, &tail,
iov[TCP_IOV_IP].iov_base, th, check, seq, no_tcp_csum);
&tail, seq, no_tcp_csum);
}
} }
/** /**

View File

@ -164,14 +164,11 @@ struct tcp_info_linux;
void tcp_update_csum(uint32_t psum, struct tcphdr *th, void tcp_update_csum(uint32_t psum, struct tcphdr *th,
struct iov_tail *payload); struct iov_tail *payload);
void tcp_fill_headers4(const struct tcp_tap_conn *conn, void tcp_fill_headers(const struct tcp_tap_conn *conn,
struct tap_hdr *taph, struct iphdr *iph, struct tap_hdr *taph,
struct tcphdr *th, struct iov_tail *payload, struct iphdr *ip4h, struct ipv6hdr *ip6h,
const uint16_t *check, uint32_t seq, bool no_tcp_csum); struct tcphdr *th, struct iov_tail *payload,
void tcp_fill_headers6(const struct tcp_tap_conn *conn, const uint16_t *ip4_check, uint32_t seq, bool no_tcp_csum);
struct tap_hdr *taph, struct ipv6hdr *ip6h,
struct tcphdr *th, struct iov_tail *payload,
uint32_t seq, bool no_tcp_csum);
int tcp_update_seqack_wnd(const struct ctx *c, struct tcp_tap_conn *conn, int tcp_update_seqack_wnd(const struct ctx *c, struct tcp_tap_conn *conn,
bool force_seq, struct tcp_info_linux *tinfo); bool force_seq, struct tcp_info_linux *tinfo);

View File

@ -111,9 +111,9 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
size_t optlen, hdrlen; size_t optlen, hdrlen;
struct vu_virtq_element flags_elem[2]; struct vu_virtq_element flags_elem[2];
struct ipv6hdr *ip6h = NULL; struct ipv6hdr *ip6h = NULL;
struct iphdr *ip4h = NULL;
struct iovec flags_iov[2]; struct iovec flags_iov[2];
struct tcp_syn_opts *opts; struct tcp_syn_opts *opts;
struct iphdr *iph = NULL;
struct iov_tail payload; struct iov_tail payload;
struct tcphdr *th; struct tcphdr *th;
struct ethhdr *eh; struct ethhdr *eh;
@ -144,8 +144,8 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
if (CONN_V4(conn)) { if (CONN_V4(conn)) {
eh->h_proto = htons(ETH_P_IP); eh->h_proto = htons(ETH_P_IP);
iph = vu_ip(flags_elem[0].in_sg[0].iov_base); ip4h = vu_ip(flags_elem[0].in_sg[0].iov_base);
*iph = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP); *ip4h = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP);
th = vu_payloadv4(flags_elem[0].in_sg[0].iov_base); th = vu_payloadv4(flags_elem[0].in_sg[0].iov_base);
} else { } else {
@ -171,12 +171,8 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
flags_elem[0].in_sg[0].iov_len = hdrlen + optlen; flags_elem[0].in_sg[0].iov_len = hdrlen + optlen;
payload = IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen); payload = IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen);
if (CONN_V4(conn)) { tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
tcp_fill_headers4(conn, NULL, iph, th, &payload, NULL, seq, true);
NULL, seq, true);
} else {
tcp_fill_headers6(conn, NULL, ip6h, th, &payload, seq, true);
}
if (*c->pcap) { if (*c->pcap) {
tcp_vu_update_check(tapside, &flags_elem[0].in_sg[0], 1); tcp_vu_update_check(tapside, &flags_elem[0].in_sg[0], 1);
@ -339,7 +335,7 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn,
struct iov_tail payload = IOV_TAIL(iov, iov_cnt, hdrlen); struct iov_tail payload = IOV_TAIL(iov, iov_cnt, hdrlen);
char *base = iov[0].iov_base; char *base = iov[0].iov_base;
struct ipv6hdr *ip6h = NULL; struct ipv6hdr *ip6h = NULL;
struct iphdr *iph = NULL; struct iphdr *ip4h = NULL;
struct tcphdr *th; struct tcphdr *th;
struct ethhdr *eh; struct ethhdr *eh;
@ -358,8 +354,8 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn,
if (!v6) { if (!v6) {
eh->h_proto = htons(ETH_P_IP); eh->h_proto = htons(ETH_P_IP);
iph = vu_ip(base); ip4h = vu_ip(base);
*iph = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP); *ip4h = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP);
th = vu_payloadv4(base); th = vu_payloadv4(base);
} else { } else {
eh->h_proto = htons(ETH_P_IPV6); eh->h_proto = htons(ETH_P_IPV6);
@ -374,14 +370,10 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn,
th->doff = sizeof(*th) / 4; th->doff = sizeof(*th) / 4;
th->ack = 1; th->ack = 1;
if (!v6) { tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
tcp_fill_headers4(conn, NULL, iph, th, &payload, *check, conn->seq_to_tap, true);
*check, conn->seq_to_tap, true); if (ip4h)
*check = &iph->check; *check = &ip4h->check;
} else {
tcp_fill_headers6(conn, NULL, ip6h, th, &payload,
conn->seq_to_tap, true);
}
} }
/** /**