Browse Source

Avoid unaligned memory accesses in VXLAN and batman-adv

Improves performance slightly.
Matthias Schiffer 6 years ago
parent
commit
a9edd43693

+ 130 - 0
patches/lede/0061-ar71xx-add-unaligned-access-hacks-for-VXLAN.patch

@@ -0,0 +1,130 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Wed, 24 Jan 2018 21:34:54 +0100
+Subject: ar71xx: add unaligned access hacks for VXLAN
+
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
+
+diff --git a/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch b/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch
+index 8882b1758fed7ac254116fb0cb0e1b95bbe5259f..b06b36317f6bae7827c280ffc7338b6487d762f5 100644
+--- a/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch
++++ b/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch
+@@ -929,3 +929,119 @@
+  	};
+  	if (skb->ip_summed != CHECKSUM_PARTIAL) {
+  		*sum = csum_fold(csum_partial(diff, sizeof(diff),
++--- a/drivers/net/vxlan.c
+++++ b/drivers/net/vxlan.c
++@@ -1759,8 +1759,8 @@ static int vxlan6_xmit_skb(struct dst_en
++ 	}
++ 
++ 	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
++-	vxh->vx_flags = htonl(VXLAN_HF_VNI);
++-	vxh->vx_vni = vni;
+++	net_hdr_word(&vxh->vx_flags) = htonl(VXLAN_HF_VNI);
+++	net_hdr_word(&vxh->vx_vni) = vni;
++ 
++ 	if (type & SKB_GSO_TUNNEL_REMCSUM) {
++ 		u32 data = (skb_checksum_start_offset(skb) - hdrlen) >>
++@@ -1769,8 +1769,8 @@ static int vxlan6_xmit_skb(struct dst_en
++ 		if (skb->csum_offset == offsetof(struct udphdr, check))
++ 			data |= VXLAN_RCO_UDP;
++ 
++-		vxh->vx_vni |= htonl(data);
++-		vxh->vx_flags |= htonl(VXLAN_HF_RCO);
+++		net_hdr_word(&vxh->vx_vni) |= htonl(data);
+++		net_hdr_word(&vxh->vx_flags) |= htonl(VXLAN_HF_RCO);
++ 
++ 		if (!skb_is_gso(skb)) {
++ 			skb->ip_summed = CHECKSUM_NONE;
++@@ -1838,8 +1838,8 @@ static int vxlan_xmit_skb(struct rtable
++ 		return PTR_ERR(skb);
++ 
++ 	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
++-	vxh->vx_flags = htonl(VXLAN_HF_VNI);
++-	vxh->vx_vni = vni;
+++	net_hdr_word(&vxh->vx_flags) = htonl(VXLAN_HF_VNI);
+++	net_hdr_word(&vxh->vx_vni) = vni;
++ 
++ 	if (type & SKB_GSO_TUNNEL_REMCSUM) {
++ 		u32 data = (skb_checksum_start_offset(skb) - hdrlen) >>
++@@ -1848,8 +1848,8 @@ static int vxlan_xmit_skb(struct rtable
++ 		if (skb->csum_offset == offsetof(struct udphdr, check))
++ 			data |= VXLAN_RCO_UDP;
++ 
++-		vxh->vx_vni |= htonl(data);
++-		vxh->vx_flags |= htonl(VXLAN_HF_RCO);
+++		net_hdr_word(&vxh->vx_vni) |= htonl(data);
+++		net_hdr_word(&vxh->vx_flags) |= htonl(VXLAN_HF_RCO);
++ 
++ 		if (!skb_is_gso(skb)) {
++ 			skb->ip_summed = CHECKSUM_NONE;
++--- a/include/linux/etherdevice.h
+++++ b/include/linux/etherdevice.h
++@@ -409,7 +409,7 @@ static inline bool is_etherdev_addr(cons
++  * @b: Pointer to Ethernet header
++  *
++  * Compare two Ethernet headers, returns 0 if equal.
++- * This assumes that the network header (i.e., IP header) is 4-byte
+++ * This assumes that the network header (i.e., IP header) is 2-byte
++  * aligned OR the platform can handle unaligned access.  This is the
++  * case for all packets coming into netif_receive_skb or similar
++  * entry points.
++@@ -432,11 +432,12 @@ static inline unsigned long compare_ethe
++ 	fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6);
++ 	return fold;
++ #else
++-	u32 *a32 = (u32 *)((u8 *)a + 2);
++-	u32 *b32 = (u32 *)((u8 *)b + 2);
+++	const u16 *a16 = a;
+++	const u16 *b16 = b;
++ 
++-	return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) |
++-	       (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]);
+++	return (a16[0] ^ b16[0]) | (a16[1] ^ b16[1]) | (a16[2] ^ b16[2]) |
+++	       (a16[3] ^ b16[3]) | (a16[4] ^ b16[4]) | (a16[5] ^ b16[5]) |
+++	       (a16[6] ^ b16[6]);
++ #endif
++ }
++ 
++--- a/net/ipv4/tcp_offload.c
+++++ b/net/ipv4/tcp_offload.c
++@@ -221,7 +221,7 @@ struct sk_buff **tcp_gro_receive(struct
++ 
++ 		th2 = tcp_hdr(p);
++ 
++-		if (*(u32 *)&th->source ^ *(u32 *)&th2->source) {
+++		if (net_hdr_word(&th->source) ^ net_hdr_word(&th2->source)) {
++ 			NAPI_GRO_CB(p)->same_flow = 0;
++ 			continue;
++ 		}
++@@ -239,8 +239,8 @@ found:
++ 		  ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH));
++ 	flush |= (__force int)(th->ack_seq ^ th2->ack_seq);
++ 	for (i = sizeof(*th); i < thlen; i += 4)
++-		flush |= *(u32 *)((u8 *)th + i) ^
++-			 *(u32 *)((u8 *)th2 + i);
+++		flush |= net_hdr_word((u8 *)th + i) ^
+++			 net_hdr_word((u8 *)th2 + i);
++ 
++ 	mss = skb_shinfo(p)->gso_size;
++ 
++--- a/net/ipv6/netfilter/ip6table_mangle.c
+++++ b/net/ipv6/netfilter/ip6table_mangle.c
++@@ -55,7 +55,7 @@ ip6t_mangle_out(struct sk_buff *skb, con
++ 	hop_limit = ipv6_hdr(skb)->hop_limit;
++ 
++ 	/* flowlabel and prio (includes version, which shouldn't change either */
++-	flowlabel = *((u_int32_t *)ipv6_hdr(skb));
+++	flowlabel = net_hdr_word(ipv6_hdr(skb));
++ 
++ 	ret = ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle);
++ 
++@@ -64,7 +64,7 @@ ip6t_mangle_out(struct sk_buff *skb, con
++ 	     !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) ||
++ 	     skb->mark != mark ||
++ 	     ipv6_hdr(skb)->hop_limit != hop_limit ||
++-	     flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) {
+++	     flowlabel != net_hdr_word(ipv6_hdr(skb)))) {
++ 		err = ip6_route_me_harder(state->net, skb);
++ 		if (err < 0)
++ 			ret = NF_DROP_ERR(err);

+ 47 - 0
patches/packages/routing/0003-batman-adv-unaligned-access-fixes.patch

@@ -0,0 +1,47 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Tue, 23 Jan 2018 21:18:34 +0100
+Subject: batman-adv: unaligned access fixes
+
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
+
+diff --git a/batman-adv/patches/900-unaligned-access.patch b/batman-adv/patches/900-unaligned-access.patch
+new file mode 100644
+index 0000000000000000000000000000000000000000..ba428b683ab146773162b0956a7e3b6260c14339
+--- /dev/null
++++ b/batman-adv/patches/900-unaligned-access.patch
+@@ -0,0 +1,35 @@
++--- a/net/batman-adv/packet.h
+++++ b/net/batman-adv/packet.h
++@@ -173,8 +173,6 @@ struct batadv_bla_claim_dst {
++ 	__be16 group;		/* group id */
++ };
++ 
++-#pragma pack()
++-
++ /**
++  * struct batadv_ogm_packet - ogm (routing protocol) packet
++  * @packet_type: batman-adv packet type, part of the general header
++@@ -382,7 +380,6 @@ struct batadv_icmp_packet_rr {
++  * misalignment of the payload after the ethernet header. It may also lead to
++  * leakage of information when the padding it not initialized before sending.
++  */
++-#pragma pack(2)
++ 
++ /**
++  * struct batadv_unicast_packet - unicast packet for network payload
++@@ -510,8 +507,6 @@ struct batadv_coded_packet {
++ 	__be16 coded_len;
++ };
++ 
++-#pragma pack()
++-
++ /**
++  * struct batadv_unicast_tvlv_packet - generic unicast packet with tvlv payload
++  * @packet_type: batman-adv packet type, part of the general header
++@@ -618,4 +613,6 @@ struct batadv_tvlv_mcast_data {
++ 	u8 reserved[3];
++ };
++ 
+++#pragma pack()
+++
++ #endif /* _NET_BATMAN_ADV_PACKET_H_ */