Skip to contentSkip to conversation

openvswitch: Fix L4 checksum handling when dealing with IP fragments

PATCH In review Glenn Griffin 3 participants 5 messages Aug 3, 2015 – Aug 10, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 openvswitch: Fix L4 checksum handling when dealing with IP fragments

openvswitch modifies the L4 checksum of a packet when modifying the ip address. When an IP packet is fragmented only the first fragment contains an L4 header and checksum. Prior to this change openvswitch would modify all fragments, modifying application data in non-first fragments, causing checksum failures in the reassembled packet.

---
Changes in v2:
- Compare frag_off in network byte order rather than host byte order

 net/openvswitch/actions.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
net/openvswitch/actions.c +12 -4
index 8a8c0b8..ee34f47 100644
@@ -273,28 +273,36 @@ static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *flow_key,
 	return 0;
 }
 
-static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
-			__be32 *addr, __be32 new_addr)
+static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
+				  __be32 addr, __be32 new_addr)
 {
 	int transport_len = skb->len - skb_transport_offset(skb);
 
+	if (nh->frag_off & htons(IP_OFFSET))
+		return;
+
 	if (nh->protocol == IPPROTO_TCP) {
 		if (likely(transport_len >= sizeof(struct tcphdr)))
 			inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb,
-						 *addr, new_addr, 1);
+						 addr, new_addr, 1);
 	} else if (nh->protocol == IPPROTO_UDP) {
 		if (likely(transport_len >= sizeof(struct udphdr))) {
 			struct udphdr *uh = udp_hdr(skb);
 
 			if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
 				inet_proto_csum_replace4(&uh->check, skb,
-							 *addr, new_addr, 1);
+							 addr, new_addr, 1);
 				if (!uh->check)
 					uh->check = CSUM_MANGLED_0;
 			}
 		}
 	}
+}
 
+static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
+			__be32 *addr, __be32 new_addr)
+{
+	update_ip_l4_checksum(skb, nh, *addr, new_addr);
 	csum_replace4(&nh->check, *addr, new_addr);
 	skb_clear_hash(skb);
 	*addr = new_addr;
Signature · 6 lines
2.1.4

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev
Acked-by on v2 1/1
#1 lore raw
Quoted 8 lines · Glenn Griffin

openvswitch modifies the L4 checksum of a packet when modifying the ip address. When an IP packet is fragmented only the first fragment contains an L4 header and checksum. Prior to this change openvswitch would modify all fragments, modifying application data in non-first fragments, causing checksum failures in the reassembled packet.

Looks good.

This patch needs to be backported to stable branches.

Thanks.
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

maintainer
#2 lore raw
In reply to Glenn Griffin

From: Glenn Griffin <[email protected]>
Date: Mon, 3 Aug 2015 09:56:54 -0700

Quoted 11 lines

openvswitch modifies the L4 checksum of a packet when modifying the ip address. When an IP packet is fragmented only the first fragment contains an L4 header and checksum. Prior to this change openvswitch would modify all fragments, modifying application data in non-first fragments, causing checksum failures in the reassembled packet.

---
Changes in v2:
- Compare frag_off in network byte order rather than host byte order

Applied and queued up for -stable.

#3 lore raw
Quoted 10 lines · David Miller

From: Glenn Griffin <[email protected]>
Date: Mon, 3 Aug 2015 09:56:54 -0700

Quoted 7 lines

openvswitch modifies the L4 checksum of a packet when modifying the ip address. When an IP packet is fragmented only the first fragment contains an L4 header and checksum. Prior to this change openvswitch would modify all fragments, modifying application data in non-first fragments, causing checksum failures in the reassembled packet.

Quoted 6 lines
Quoted 4 lines

---
Changes in v2:
- Compare frag_off in network byte order rather than host byte order

Applied and queued up for -stable.

I noticed this change didn't seem to make it into 4.2-rc6. I'm not too familiar with the release schedule so wasn't sure if that was expected or an oversight. Will this remain queued up until the 4.3 merge window opens?

maintainer
#4 lore raw

From: Glenn Griffin <[email protected]>
Date: Mon, 10 Aug 2015 10:43:16 -0700

Quoted 16 lines · David Miller
Quoted 15 lines

From: Glenn Griffin <[email protected]>
Date: Mon, 3 Aug 2015 09:56:54 -0700

Quoted 11 lines

openvswitch modifies the L4 checksum of a packet when modifying the ip address. When an IP packet is fragmented only the first fragment contains an L4 header and checksum. Prior to this change openvswitch would modify all fragments, modifying application data in non-first fragments, causing checksum failures in the reassembled packet.

---
Changes in v2:
- Compare frag_off in network byte order rather than host byte order

Quoted 6 lines
Quoted 1 line

Applied and queued up for -stable.

I noticed this change didn't seem to make it into 4.2-rc6. I'm not too familiar with the release schedule so wasn't sure if that was expected or an oversight. Will this remain queued up until the 4.3 merge window opens?

It's in my 'net' tree and will be pushed to Linus's tree at a time that I deem appropriate. Usually I try to push to Linus one every week or so, in order for changes to soak and get tested in my tree before they get pushed to his.