From a9edd43693a02e0829d04a83a13ebbf0f7eef3ee Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 24 Jan 2018 22:13:30 +0100 Subject: [PATCH] Avoid unaligned memory accesses in VXLAN and batman-adv Improves performance slightly. --- ...add-unaligned-access-hacks-for-VXLAN.patch | 130 ++++++++++++++++++ ...03-batman-adv-unaligned-access-fixes.patch | 47 +++++++ 2 files changed, 177 insertions(+) create mode 100644 patches/lede/0061-ar71xx-add-unaligned-access-hacks-for-VXLAN.patch create mode 100644 patches/packages/routing/0003-batman-adv-unaligned-access-fixes.patch diff --git a/patches/lede/0061-ar71xx-add-unaligned-access-hacks-for-VXLAN.patch b/patches/lede/0061-ar71xx-add-unaligned-access-hacks-for-VXLAN.patch new file mode 100644 index 00000000..efe52da4 --- /dev/null +++ b/patches/lede/0061-ar71xx-add-unaligned-access-hacks-for-VXLAN.patch @@ -0,0 +1,130 @@ +From: Matthias Schiffer +Date: Wed, 24 Jan 2018 21:34:54 +0100 +Subject: ar71xx: add unaligned access hacks for VXLAN + +Signed-off-by: Matthias Schiffer + +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); diff --git a/patches/packages/routing/0003-batman-adv-unaligned-access-fixes.patch b/patches/packages/routing/0003-batman-adv-unaligned-access-fixes.patch new file mode 100644 index 00000000..e01f2c09 --- /dev/null +++ b/patches/packages/routing/0003-batman-adv-unaligned-access-fixes.patch @@ -0,0 +1,47 @@ +From: Matthias Schiffer +Date: Tue, 23 Jan 2018 21:18:34 +0100 +Subject: batman-adv: unaligned access fixes + +Signed-off-by: Matthias Schiffer + +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_ */