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:
parent
2abf5ab7f3
commit
a6348cad51
88
tcp.c
88
tcp.c
@ -877,68 +877,54 @@ 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
|
||||
* @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
|
||||
* @payload: TCP payload
|
||||
* @check: Checksum, if already known
|
||||
* @ip4_check: IPv4 checksum, if already known
|
||||
* @seq: Sequence number for this segment
|
||||
* @no_tcp_csum: Do not set TCP checksum
|
||||
*/
|
||||
void tcp_fill_headers4(const struct tcp_tap_conn *conn,
|
||||
struct tap_hdr *taph, struct iphdr *iph,
|
||||
void tcp_fill_headers(const struct tcp_tap_conn *conn,
|
||||
struct tap_hdr *taph,
|
||||
struct iphdr *ip4h, struct ipv6hdr *ip6h,
|
||||
struct tcphdr *th, struct iov_tail *payload,
|
||||
const uint16_t *check, uint32_t seq, bool no_tcp_csum)
|
||||
const uint16_t *ip4_check, uint32_t seq, bool no_tcp_csum)
|
||||
{
|
||||
const struct flowside *tapside = TAPFLOW(conn);
|
||||
size_t l4len = iov_tail_size(payload) + sizeof(*th);
|
||||
size_t l3len = l4len;
|
||||
uint32_t psum = 0;
|
||||
|
||||
if (ip4h) {
|
||||
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 l3len = l4len + sizeof(*iph);
|
||||
|
||||
ASSERT(src4 && dst4);
|
||||
|
||||
iph->tot_len = htons(l3len);
|
||||
iph->saddr = src4->s_addr;
|
||||
iph->daddr = dst4->s_addr;
|
||||
l3len += + sizeof(*ip4h);
|
||||
|
||||
iph->check = check ? *check :
|
||||
csum_ip4_header(l3len, IPPROTO_TCP, *src4, *dst4);
|
||||
ip4h->tot_len = htons(l3len);
|
||||
ip4h->saddr = src4->s_addr;
|
||||
ip4h->daddr = dst4->s_addr;
|
||||
|
||||
tcp_fill_header(th, conn, seq);
|
||||
|
||||
if (no_tcp_csum) {
|
||||
th->check = 0;
|
||||
} else {
|
||||
uint32_t psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP,
|
||||
if (ip4_check)
|
||||
ip4h->check = *ip4_check;
|
||||
else
|
||||
ip4h->check = csum_ip4_header(l3len, IPPROTO_TCP,
|
||||
*src4, *dst4);
|
||||
|
||||
tcp_update_csum(psum, th, payload);
|
||||
if (!no_tcp_csum) {
|
||||
psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP,
|
||||
*src4, *dst4);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (ip6h) {
|
||||
l3len += sizeof(*ip6h);
|
||||
|
||||
ip6h->payload_len = htons(l4len);
|
||||
ip6h->saddr = tapside->oaddr.a6;
|
||||
@ -952,19 +938,21 @@ 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,
|
||||
if (!no_tcp_csum) {
|
||||
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_fill_header(th, conn, seq);
|
||||
|
||||
if (no_tcp_csum)
|
||||
th->check = 0;
|
||||
else
|
||||
tcp_update_csum(psum, th, payload);
|
||||
|
||||
tap_hdr_update(taph, l3len + sizeof(struct ethhdr));
|
||||
}
|
||||
|
||||
/**
|
||||
|
19
tcp_buf.c
19
tcp_buf.c
@ -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 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 in_addr *a4 = inany_v4(&tapside->oaddr);
|
||||
struct ipv6hdr *ip6h = NULL;
|
||||
struct iphdr *ip4h = NULL;
|
||||
|
||||
if (a4) {
|
||||
tcp_fill_headers4(conn, iov[TCP_IOV_TAP].iov_base,
|
||||
iov[TCP_IOV_IP].iov_base, th,
|
||||
&tail, check, seq, no_tcp_csum);
|
||||
} else {
|
||||
tcp_fill_headers6(conn, iov[TCP_IOV_TAP].iov_base,
|
||||
iov[TCP_IOV_IP].iov_base, th,
|
||||
&tail, seq, no_tcp_csum);
|
||||
}
|
||||
if (a4)
|
||||
ip4h = iov[TCP_IOV_IP].iov_base;
|
||||
else
|
||||
ip6h = iov[TCP_IOV_IP].iov_base;
|
||||
|
||||
tcp_fill_headers(conn, taph, ip4h, ip6h, th, &tail,
|
||||
check, seq, no_tcp_csum);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,14 +164,11 @@ struct tcp_info_linux;
|
||||
|
||||
void tcp_update_csum(uint32_t psum, struct tcphdr *th,
|
||||
struct iov_tail *payload);
|
||||
void tcp_fill_headers4(const struct tcp_tap_conn *conn,
|
||||
struct tap_hdr *taph, struct iphdr *iph,
|
||||
void tcp_fill_headers(const struct tcp_tap_conn *conn,
|
||||
struct tap_hdr *taph,
|
||||
struct iphdr *ip4h, struct ipv6hdr *ip6h,
|
||||
struct tcphdr *th, struct iov_tail *payload,
|
||||
const uint16_t *check, uint32_t seq, bool no_tcp_csum);
|
||||
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);
|
||||
const uint16_t *ip4_check, uint32_t seq, bool no_tcp_csum);
|
||||
|
||||
int tcp_update_seqack_wnd(const struct ctx *c, struct tcp_tap_conn *conn,
|
||||
bool force_seq, struct tcp_info_linux *tinfo);
|
||||
|
28
tcp_vu.c
28
tcp_vu.c
@ -111,9 +111,9 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
|
||||
size_t optlen, hdrlen;
|
||||
struct vu_virtq_element flags_elem[2];
|
||||
struct ipv6hdr *ip6h = NULL;
|
||||
struct iphdr *ip4h = NULL;
|
||||
struct iovec flags_iov[2];
|
||||
struct tcp_syn_opts *opts;
|
||||
struct iphdr *iph = NULL;
|
||||
struct iov_tail payload;
|
||||
struct tcphdr *th;
|
||||
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)) {
|
||||
eh->h_proto = htons(ETH_P_IP);
|
||||
|
||||
iph = vu_ip(flags_elem[0].in_sg[0].iov_base);
|
||||
*iph = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP);
|
||||
ip4h = vu_ip(flags_elem[0].in_sg[0].iov_base);
|
||||
*ip4h = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP);
|
||||
|
||||
th = vu_payloadv4(flags_elem[0].in_sg[0].iov_base);
|
||||
} 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;
|
||||
payload = IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen);
|
||||
|
||||
if (CONN_V4(conn)) {
|
||||
tcp_fill_headers4(conn, NULL, iph, th, &payload,
|
||||
tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
|
||||
NULL, seq, true);
|
||||
} else {
|
||||
tcp_fill_headers6(conn, NULL, ip6h, th, &payload, seq, true);
|
||||
}
|
||||
|
||||
if (*c->pcap) {
|
||||
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);
|
||||
char *base = iov[0].iov_base;
|
||||
struct ipv6hdr *ip6h = NULL;
|
||||
struct iphdr *iph = NULL;
|
||||
struct iphdr *ip4h = NULL;
|
||||
struct tcphdr *th;
|
||||
struct ethhdr *eh;
|
||||
|
||||
@ -358,8 +354,8 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn,
|
||||
if (!v6) {
|
||||
eh->h_proto = htons(ETH_P_IP);
|
||||
|
||||
iph = vu_ip(base);
|
||||
*iph = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP);
|
||||
ip4h = vu_ip(base);
|
||||
*ip4h = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_TCP);
|
||||
th = vu_payloadv4(base);
|
||||
} else {
|
||||
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->ack = 1;
|
||||
|
||||
if (!v6) {
|
||||
tcp_fill_headers4(conn, NULL, iph, th, &payload,
|
||||
tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
|
||||
*check, conn->seq_to_tap, true);
|
||||
*check = &iph->check;
|
||||
} else {
|
||||
tcp_fill_headers6(conn, NULL, ip6h, th, &payload,
|
||||
conn->seq_to_tap, true);
|
||||
}
|
||||
if (ip4h)
|
||||
*check = &ip4h->check;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user