Subject: Re: [PATCH] net: Set true network header for ECN decapsulation

From: Toke Høiland-Jørgensen <[email-masked]>
Date: Thu, 22 Jul 2021 19:21:30 +0200

Gilad Naaman <[email-masked]> writes:

> In cases where the header straight after the tunnel header was
> another ethernet header (TEB), instead of the network header,
> the ECN decapsulation code would treat the ethernet header as if
> it was an IP header, resulting in mishandling and possible
> wrong drops or corruption of the IP header.
>
> In this case, ECT(1) is sent, so IP_ECN_decapsulate tries to copy it to the
> inner IPv4 header, and correct its checksum.
>
> The offset of the ECT bits in an IPv4 header corresponds to the
> lower 2 bits of the second octet of the destination MAC address
> in the ethernet header.
> The IPv4 checksum corresponds to end of the source address.
>
> In order to reproduce:
>
>     $ ip netns add A
>     $ ip netns add B
>     $ ip -n A link add _v0 type veth peer name _v1 netns B
>     $ ip -n A link set _v0 up
>     $ ip -n A addr add dev _v0 10.254.3.1/24
>     $ ip -n A route add default dev _v0 scope global
>     $ ip -n B link set _v1 up
>     $ ip -n B addr add dev _v1 10.254.1.6/24
>     $ ip -n B route add default dev _v1 scope global
>     $ ip -n B link add gre1 type gretap local 10.254.1.6 remote 10.254.3.1 key 0x49000000
>     $ ip -n B link set gre1 up
>
>     # Now send an IPv4/GRE/Eth/IPv4 frame where the outer header has ECT(1),
>     # and the inner header has no ECT bits set:
>
>     $ cat send_pkt.py
>         #!/usr/bin/env python3
>         from scapy.all import *
>
>         pkt = IP(b'E\x01\x00\xa7\x00\x00\x00\x00@/`%\n\xfe\x03\x01\n\xfe\x01\x06 \x00eXI\x00'
>                  b'\x00\x00\x18\xbe\x92\xa0\xee&\x18\xb0\x92\xa0l&\x08\x00E\x00\x00}\x8b\x85'
>                  b'@\x00\x01\x01\xe4\xf2\x82\x82\x82\x01\x82\x82\x82\x02\x08\x00d\x11\xa6\xeb'
>                  b'3\x1e\x1e\\xf3\\xf7`\x00\x00\x00\x00ZN\x00\x00\x00\x00\x00\x00\x10\x11\x12'
>                  b'\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234'
>                  b'56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ')
>
>         send(pkt)
>     $ sudo ip netns exec B tcpdump -neqlllvi gre1 icmp & ; sleep 1
>     $ sudo ip netns exec A python3 send_pkt.py
>
> In the original packet, the source/destinatio MAC addresses are
> dst=18:be:92:a0:ee:26 src=18:b0:92:a0:6c:26
>
> In the received packet, they are
> dst=18:bd:92:a0:ee:26 src=18:b0:92:a0:6c:27
>
> Thanks to Lahav Schlesinger <[email-masked]> and Isaac Garzon <[email-masked]>
> for helping me pinpoint the origin.

Oops! Thank you for the fix :)

Acked-by: Toke Høiland-Jørgensen <[email-masked]>