derp/xdp: fix handling of zero value UDP checksums (#12510)
validate_udp_checksum was previously indeterminate (not zero) at declaration, and IPv4 zero value UDP checksum packets were being passed to the kernel. Updates tailscale/corp#20689 Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
parent
8cc2738609
commit
315f3d5df1
Binary file not shown.
Binary file not shown.
|
@ -244,7 +244,7 @@ static __always_inline int handle_packet(struct xdp_md *ctx, struct packet_conte
|
||||||
struct ipv6hdr *ip6;
|
struct ipv6hdr *ip6;
|
||||||
struct udphdr *udp;
|
struct udphdr *udp;
|
||||||
|
|
||||||
int validate_udp_csum;
|
int validate_udp_csum = 0;
|
||||||
if (eth->h_proto == bpf_htons(ETH_P_IP)) {
|
if (eth->h_proto == bpf_htons(ETH_P_IP)) {
|
||||||
pctx->af = COUNTER_KEY_AF_IPV4;
|
pctx->af = COUNTER_KEY_AF_IPV4;
|
||||||
ip = (void *)(eth + 1);
|
ip = (void *)(eth + 1);
|
||||||
|
|
|
@ -426,6 +426,18 @@ func TestXDP(t *testing.T) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipv4STUNBindingReqUDPZeroCsumTx := getIPv4STUNBindingReq(&ipv4Mutations{
|
||||||
|
udpHeaderFn: func(udpH header.UDP) {
|
||||||
|
udpH.SetChecksum(0)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
ipv6STUNBindingReqUDPZeroCsumPass := getIPv6STUNBindingReq(&ipv6Mutations{
|
||||||
|
udpHeaderFn: func(udpH header.UDP) {
|
||||||
|
udpH.SetChecksum(0)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
packetIn []byte
|
packetIn []byte
|
||||||
|
@ -865,6 +877,42 @@ func TestXDP(t *testing.T) {
|
||||||
}: uint64(len(ipv6STUNBindingReqSTUNFirstAttrPass)),
|
}: uint64(len(ipv6STUNBindingReqSTUNFirstAttrPass)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ipv4 UDP zero csum TX",
|
||||||
|
packetIn: ipv4STUNBindingReqUDPZeroCsumTx,
|
||||||
|
wantCode: xdpActionTX,
|
||||||
|
wantPacketOut: getIPv4STUNBindingResp(),
|
||||||
|
wantMetrics: map[bpfCountersKey]uint64{
|
||||||
|
{
|
||||||
|
Af: uint8(bpfCounterKeyAfCOUNTER_KEY_AF_IPV4),
|
||||||
|
Pba: uint8(bpfCounterKeyPacketsBytesActionCOUNTER_KEY_PACKETS_TX_TOTAL),
|
||||||
|
ProgEnd: uint8(bpfCounterKeyProgEndCOUNTER_KEY_END_UNSPECIFIED),
|
||||||
|
}: 1,
|
||||||
|
{
|
||||||
|
Af: uint8(bpfCounterKeyAfCOUNTER_KEY_AF_IPV4),
|
||||||
|
Pba: uint8(bpfCounterKeyPacketsBytesActionCOUNTER_KEY_BYTES_TX_TOTAL),
|
||||||
|
ProgEnd: uint8(bpfCounterKeyProgEndCOUNTER_KEY_END_UNSPECIFIED),
|
||||||
|
}: uint64(len(getIPv4STUNBindingResp())),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ipv6 UDP zero csum PASS",
|
||||||
|
packetIn: ipv6STUNBindingReqUDPZeroCsumPass,
|
||||||
|
wantCode: xdpActionPass,
|
||||||
|
wantPacketOut: ipv6STUNBindingReqUDPZeroCsumPass,
|
||||||
|
wantMetrics: map[bpfCountersKey]uint64{
|
||||||
|
{
|
||||||
|
Af: uint8(bpfCounterKeyAfCOUNTER_KEY_AF_IPV6),
|
||||||
|
Pba: uint8(bpfCounterKeyPacketsBytesActionCOUNTER_KEY_PACKETS_PASS_TOTAL),
|
||||||
|
ProgEnd: uint8(bpfCounterKeyProgEndCOUNTER_KEY_END_INVALID_UDP_CSUM),
|
||||||
|
}: 1,
|
||||||
|
{
|
||||||
|
Af: uint8(bpfCounterKeyAfCOUNTER_KEY_AF_IPV6),
|
||||||
|
Pba: uint8(bpfCounterKeyPacketsBytesActionCOUNTER_KEY_BYTES_PASS_TOTAL),
|
||||||
|
ProgEnd: uint8(bpfCounterKeyProgEndCOUNTER_KEY_END_INVALID_UDP_CSUM),
|
||||||
|
}: uint64(len(ipv6STUNBindingReqUDPZeroCsumPass)),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
server, err := NewSTUNServer(&STUNServerConfig{DeviceName: "fake", DstPort: defaultSTUNPort},
|
server, err := NewSTUNServer(&STUNServerConfig{DeviceName: "fake", DstPort: defaultSTUNPort},
|
||||||
|
|
Loading…
Reference in New Issue