Skip to content

Commit

Permalink
Last attempt at patches for the ipv6 and ipv4 unalignment problem
Browse files Browse the repository at this point in the history
  • Loading branch information
Dave Taht committed May 14, 2012
1 parent fbbdb6c commit da6127a
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 5 deletions.
Expand Up @@ -81,6 +81,19 @@ index f2f7c6c..dce734c 100644
" .set noreorder \n"
" .set noat \n"
" addu %0, %5 # proto (long in network byte order)\n"
diff --git a/include/linux/icmp.h b/include/linux/icmp.h
index 474f2a5..0e0fca0 100644
--- a/include/linux/icmp.h
+++ b/include/linux/icmp.h
@@ -80,7 +80,7 @@ struct icmphdr {
__be16 mtu;
} frag;
} un;
-};
+} __packed;

#ifdef __KERNEL__
#include <linux/skbuff.h>
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index ba45e6b..5bb0258 100644
--- a/include/linux/icmpv6.h
Expand Down Expand Up @@ -307,11 +320,42 @@ index bc1b0fd..caef125 100644
sum += (__force u32)saddr->s6_addr32[0];
carry = (sum < (__force u32)saddr->s6_addr32[0]);
sum += carry;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index e4170a2..67446e6 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -105,7 +105,7 @@ struct frag_hdr {
__u8 reserved;
__be16 frag_off;
__be32 identification;
-};
+} __packed;

#define IP6_MF 0x0001

@@ -354,7 +354,7 @@ static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,

/* check incomplete u32 in prefix */
pbi = prefixlen & 0x1f;
- if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi))))
+ if (pbi && ((__get_unaligned_cpu32(&a1[pdw]) ^ __get_unaligned_cpu32(&a2[pdw])) & htonl((0xffffffff) << (32 - pbi))))
return 0;

return 1;
@@ -438,7 +438,7 @@ static inline int __ipv6_addr_diff(const void *token1, const void *token2, int a
addrlen >>= 2;

for (i = 0; i < addrlen; i++) {
- __be32 xb = a1[i] ^ a2[i];
+ __be32 xb = __get_unaligned_cpu32(&a1[i]) ^ __get_unaligned_cpu32(&a2[i]);
if (xb)
return i * 32 + 31 - __fls(ntohl(xb));
}
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index a9d350e..5be936d 100644
index e3133c2..c8e2f13 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -62,18 +62,18 @@ struct nd_msg {
@@ -61,18 +61,18 @@ struct nd_msg {
struct icmp6hdr icmph;
struct in6_addr target;
__u8 opt[0];
Expand All @@ -333,6 +377,32 @@ index a9d350e..5be936d 100644

struct nd_opt_hdr {
__u8 nd_opt_type;
@@ -83,10 +83,10 @@ static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, _
{
const u32 *p32 = pkey;

- return (((p32[0] ^ dev->ifindex) * hash_rnd[0]) +
- (p32[1] * hash_rnd[1]) +
- (p32[2] * hash_rnd[2]) +
- (p32[3] * hash_rnd[3]));
+ return (((__get_unaligned_cpu32(&p32[0]) ^ dev->ifindex) * hash_rnd[0]) +
+ (__get_unaligned_cpu32(&p32[1]) * hash_rnd[1]) +
+ (__get_unaligned_cpu32(&p32[2]) * hash_rnd[2]) +
+ (__get_unaligned_cpu32(&p32[3]) * hash_rnd[3]));
}

static inline struct neighbour *__ipv6_neigh_lookup(struct neigh_table *tbl, struct net_device *dev, const void *pkey)
@@ -104,8 +104,8 @@ static inline struct neighbour *__ipv6_neigh_lookup(struct neigh_table *tbl, str
n = rcu_dereference_bh(n->next)) {
u32 *n32 = (u32 *) n->primary_key;
if (n->dev == dev &&
- ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) |
- (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0) {
+ ((n32[0] ^ __get_unaligned_cpu32(&p32[0])) | (n32[1] ^ __get_unaligned_cpu32(&p32[1])) |
+ (n32[2] ^ __get_unaligned_cpu32(&p32[2])) | (n32[3] ^ __get_unaligned_cpu32(&p32[3]))) == 0) {
if (!atomic_inc_not_zero(&n->refcnt))
n = NULL;
break;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index a225089..019970f 100644
--- a/net/core/flow_dissector.c
Expand Down Expand Up @@ -403,7 +473,7 @@ index de9da21..2704407 100644
return true;
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 22ef5f9..bf3f773 100644
index 8c85021..4afca01 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2834,7 +2834,7 @@ found:
Expand All @@ -416,10 +486,10 @@ index 22ef5f9..bf3f773 100644
out_check_final:
flush = len < mss;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b5e315f..1a0e649 100644
index 1c30511..8630e0a 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3944,13 +3944,13 @@ static int tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
@@ -3948,13 +3948,13 @@ static int tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
{
const __be32 *ptr = (const __be32 *)(th + 1);

Expand Down Expand Up @@ -521,6 +591,19 @@ index 3d641b6..7c072da 100644
if (pkt_len <= IPV6_MAXPLEN) {
IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
IPSTATS_MIB_INHDRERRORS);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index b82bcde..9ce186a 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -141,7 +141,7 @@ static __inline__ __be32 addr_bit_set(const void *token, int fn_bit)
* See include/asm-generic/bitops/le.h.
*/
return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) &
- addr[fn_bit >> 5];
+ __get_unaligned_cpu32(&addr[fn_bit >> 5]);
}

static __inline__ struct fib6_node * node_alloc(void)
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index e6af8d7..ef83fab 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
Expand All @@ -537,6 +620,25 @@ index e6af8d7..ef83fab 100644

fragment = 0;
ptr = ip6hoff + sizeof(struct ipv6hdr);
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index b69fae7..2ffe49a 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -151,10 +151,10 @@ void ip6_frag_init(struct inet_frag_queue *q, void *a)
struct frag_queue *fq = container_of(q, struct frag_queue, q);
struct ip6_create_arg *arg = a;

- fq->id = arg->id;
- fq->user = arg->user;
- fq->saddr = *arg->src;
- fq->daddr = *arg->dst;
+ fq->id = __get_unaligned_cpu32(&arg->id);
+ fq->user = __get_unaligned_cpu32(&arg->user);
+ memcpy(&fq->saddr, arg->src, sizeof(struct in6_addr));
+ memcpy(&fq->daddr, arg->dst, sizeof(struct in6_addr));
}
EXPORT_SYMBOL(ip6_frag_init);

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 4d5915d..e1e8bad 100644
--- a/net/ipv6/route.c
Expand Down Expand Up @@ -565,6 +667,19 @@ index 8ea65e0..eecde59 100644
}
fl6->flowi6_proto = nexthdr;
return;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 3d8981f..04bad951 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1651,7 +1651,7 @@ done:
int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res)
{
- __be16 protocol = skb->protocol;
+ __be16 protocol = __get_unaligned_cpu16(&skb->protocol);
int err;

for (; tp; tp = tp->next) {
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 54a0dc2..e9c51b6 100644
--- a/net/xfrm/xfrm_input.c
Expand All @@ -590,3 +705,16 @@ index 54a0dc2..e9c51b6 100644
return 0;
}

diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 4d40384..0a83f82 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -52,7 +52,7 @@ scm_version()
# If only the short version is requested, don't bother
# running further git commands
if $short; then
- echo "+"
+ ##echo "+"
return
fi
# If we are past a tagged commit (like
31 changes: 31 additions & 0 deletions target/linux/ar71xx/patches-3.3/928-u32-unaligned.patch
@@ -0,0 +1,31 @@
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 939b627..3df39b0 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -142,7 +142,7 @@ next_knode:
data = skb_header_pointer(skb, toff, 4, &hdata);
if (!data)
goto out;
- if ((*data ^ key->val) & key->mask) {
+ if ((__get_unaligned_cpu32(data) ^ key->val) & key->mask) {
n = n->next;
goto next_knode;
}
@@ -193,7 +193,7 @@ check_terminal:
&hdata);
if (!data)
goto out;
- sel = ht->divisor & u32_hash_fold(*data, &n->sel,
+ sel = ht->divisor & u32_hash_fold(__get_unaligned_cpu32(data), &n->sel,
n->fshift);
}
if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT)))
@@ -209,7 +209,7 @@ check_terminal:
2, &hdata);
if (!data)
goto out;
- off2 += ntohs(n->sel.offmask & *data) >>
+ off2 += ntohs(n->sel.offmask & __get_unaligned_cpu16(data)) >>
n->sel.offshift;
}
off2 &= ~3;

0 comments on commit da6127a

Please sign in to comment.