aboutgitcodebugslistschat
path: root/tap.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-07-26 07:30:57 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-07-26 07:30:57 +0200
commit16b08367a57f5a01af05d1067e2f77b04251e9b7 (patch)
tree84bfde044cb13cd5df7ff7745014e26369e480b9 /tap.c
parent17765f8de0782de09ebdf79940f934b8ccb83c41 (diff)
downloadpasst-16b08367a57f5a01af05d1067e2f77b04251e9b7.tar
passt-16b08367a57f5a01af05d1067e2f77b04251e9b7.tar.gz
passt-16b08367a57f5a01af05d1067e2f77b04251e9b7.tar.bz2
passt-16b08367a57f5a01af05d1067e2f77b04251e9b7.tar.lz
passt-16b08367a57f5a01af05d1067e2f77b04251e9b7.tar.xz
passt-16b08367a57f5a01af05d1067e2f77b04251e9b7.tar.zst
passt-16b08367a57f5a01af05d1067e2f77b04251e9b7.zip
tap: Fill the IPv6 flow label field to represent flow association
This isn't optional: TCP streams must carry a unique, hard-to-guess, non-zero label for each direction. Linux, probably among others, will otherwise refuse to associate packets in a given stream to the same connection. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'tap.c')
-rw-r--r--tap.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/tap.c b/tap.c
index 08b85ff..9fc84c1 100644
--- a/tap.c
+++ b/tap.c
@@ -91,9 +91,10 @@ int tap_send(struct ctx *c, void *data, size_t len, int vnet_pre)
* @proto: L4 protocol number
* @in: Payload
* @len: L4 payload length
+ * @flow: Flow label for TCP over IPv6
*/
void tap_ip_send(struct ctx *c, struct in6_addr *src, uint8_t proto,
- char *in, size_t len)
+ char *in, size_t len, uint32_t flow)
{
char buf[USHRT_MAX];
char *pkt = buf + 4;
@@ -161,21 +162,30 @@ void tap_ip_send(struct ctx *c, struct in6_addr *src, uint8_t proto,
struct tcphdr *th = (struct tcphdr *)(ip6h + 1);
th->check = 0;
- th->check = csum_ip4(ip6h, len + sizeof(*ip6h));
+ th->check = csum_unaligned(ip6h, len + sizeof(*ip6h),
+ 0);
} else if (proto == IPPROTO_UDP) {
struct udphdr *uh = (struct udphdr *)(ip6h + 1);
uh->check = 0;
- uh->check = csum_ip4(ip6h, len + sizeof(*ip6h));
+ uh->check = csum_unaligned(ip6h, len + sizeof(*ip6h),
+ 0);
} else if (proto == IPPROTO_ICMPV6) {
struct icmp6hdr *ih = (struct icmp6hdr *)(ip6h + 1);
ih->icmp6_cksum = 0;
- ih->icmp6_cksum = csum_ip4(ip6h, len + sizeof(*ip6h));
+ ih->icmp6_cksum = csum_unaligned(ip6h,
+ len + sizeof(*ip6h),
+ 0);
}
ip6h->version = 6;
ip6h->nexthdr = proto;
ip6h->hop_limit = 255;
+ if (flow) {
+ ip6h->flow_lbl[0] = (flow >> 16) & 0xf;
+ ip6h->flow_lbl[1] = (flow >> 8) & 0xff;
+ ip6h->flow_lbl[2] = (flow >> 0) & 0xff;
+ }
tap_send(c, buf, len + sizeof(*ip6h) + sizeof(*eh), 1);
}