Newer
Older
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 72d964df639ba2a91071fbdc893bf500ece51a48..19b1d6fc7fc8af37515fe4b5f188e856441a2436 100644
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
--- 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);