aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2012-07-10 15:05:57 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-11 02:13:46 -0400
commit1a203cb33a7dc791b6c0aedf701e70ac00c50cdb (patch)
treee34337ceadbad1aef902ce621e5d81f66bb7a0f5
parent1aa8b471e09f227455c11d55c4bc94a655ee8497 (diff)
ipv6: optimize ipv6 addresses compares
On 64 bit arches having efficient unaligned accesses (eg x86_64) we can use long words to reduce number of instructions for free. Joe Perches suggested to change ipv6_masked_addr_cmp() to return a bool instead of 'int', to make sure ipv6_masked_addr_cmp() cannot be used in a sorting function. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Joe Perches <joe@perches.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ipv6.h24
1 files changed, 23 insertions, 1 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index aecf88436abf..d4261d4d6c47 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -298,14 +298,23 @@ static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr
298 return memcmp(a1, a2, sizeof(struct in6_addr)); 298 return memcmp(a1, a2, sizeof(struct in6_addr));
299} 299}
300 300
301static inline int 301static inline bool
302ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m, 302ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
303 const struct in6_addr *a2) 303 const struct in6_addr *a2)
304{ 304{
305#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
306 const unsigned long *ul1 = (const unsigned long *)a1;
307 const unsigned long *ulm = (const unsigned long *)m;
308 const unsigned long *ul2 = (const unsigned long *)a2;
309
310 return !!(((ul1[0] ^ ul2[0]) & ulm[0]) |
311 ((ul1[1] ^ ul2[1]) & ulm[1]));
312#else
305 return !!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) | 313 return !!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) |
306 ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) | 314 ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) |
307 ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) | 315 ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) |
308 ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3])); 316 ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3]));
317#endif
309} 318}
310 319
311static inline void ipv6_addr_prefix(struct in6_addr *pfx, 320static inline void ipv6_addr_prefix(struct in6_addr *pfx,
@@ -335,10 +344,17 @@ static inline void ipv6_addr_set(struct in6_addr *addr,
335static inline bool ipv6_addr_equal(const struct in6_addr *a1, 344static inline bool ipv6_addr_equal(const struct in6_addr *a1,
336 const struct in6_addr *a2) 345 const struct in6_addr *a2)
337{ 346{
347#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
348 const unsigned long *ul1 = (const unsigned long *)a1;
349 const unsigned long *ul2 = (const unsigned long *)a2;
350
351 return ((ul1[0] ^ ul2[0]) | (ul1[1] ^ ul2[1])) == 0UL;
352#else
338 return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) | 353 return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
339 (a1->s6_addr32[1] ^ a2->s6_addr32[1]) | 354 (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
340 (a1->s6_addr32[2] ^ a2->s6_addr32[2]) | 355 (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
341 (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0; 356 (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0;
357#endif
342} 358}
343 359
344static inline bool __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2, 360static inline bool __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
@@ -391,8 +407,14 @@ bool ip6_frag_match(struct inet_frag_queue *q, void *a);
391 407
392static inline bool ipv6_addr_any(const struct in6_addr *a) 408static inline bool ipv6_addr_any(const struct in6_addr *a)
393{ 409{
410#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
411 const unsigned long *ul = (const unsigned long *)a;
412
413 return (ul[0] | ul[1]) == 0UL;
414#else
394 return (a->s6_addr32[0] | a->s6_addr32[1] | 415 return (a->s6_addr32[0] | a->s6_addr32[1] |
395 a->s6_addr32[2] | a->s6_addr32[3]) == 0; 416 a->s6_addr32[2] | a->s6_addr32[3]) == 0;
417#endif
396} 418}
397 419
398static inline bool ipv6_addr_loopback(const struct in6_addr *a) 420static inline bool ipv6_addr_loopback(const struct in6_addr *a)