aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/ipv6.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/ipv6.h')
-rw-r--r--include/net/ipv6.h152
1 files changed, 125 insertions, 27 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 5af66b26ebdd..64d12e77719a 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -15,6 +15,7 @@
15 15
16#include <linux/ipv6.h> 16#include <linux/ipv6.h>
17#include <linux/hardirq.h> 17#include <linux/hardirq.h>
18#include <linux/jhash.h>
18#include <net/if_inet6.h> 19#include <net/if_inet6.h>
19#include <net/ndisc.h> 20#include <net/ndisc.h>
20#include <net/flow.h> 21#include <net/flow.h>
@@ -222,6 +223,7 @@ struct ip6_flowlabel {
222 struct in6_addr dst; 223 struct in6_addr dst;
223 struct ipv6_txoptions *opt; 224 struct ipv6_txoptions *opt;
224 unsigned long linger; 225 unsigned long linger;
226 struct rcu_head rcu;
225 u8 share; 227 u8 share;
226 union { 228 union {
227 struct pid *pid; 229 struct pid *pid;
@@ -238,6 +240,7 @@ struct ip6_flowlabel {
238struct ipv6_fl_socklist { 240struct ipv6_fl_socklist {
239 struct ipv6_fl_socklist *next; 241 struct ipv6_fl_socklist *next;
240 struct ip6_flowlabel *fl; 242 struct ip6_flowlabel *fl;
243 struct rcu_head rcu;
241}; 244};
242 245
243extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label); 246extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label);
@@ -288,12 +291,12 @@ static inline int ip6_frag_nqueues(struct net *net)
288 291
289static inline int ip6_frag_mem(struct net *net) 292static inline int ip6_frag_mem(struct net *net)
290{ 293{
291 return atomic_read(&net->ipv6.frags.mem); 294 return sum_frag_mem_limit(&net->ipv6.frags);
292} 295}
293#endif 296#endif
294 297
295#define IPV6_FRAG_HIGH_THRESH (256 * 1024) /* 262144 */ 298#define IPV6_FRAG_HIGH_THRESH (4 * 1024*1024) /* 4194304 */
296#define IPV6_FRAG_LOW_THRESH (192 * 1024) /* 196608 */ 299#define IPV6_FRAG_LOW_THRESH (3 * 1024*1024) /* 3145728 */
297#define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */ 300#define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */
298 301
299extern int __ipv6_addr_type(const struct in6_addr *addr); 302extern int __ipv6_addr_type(const struct in6_addr *addr);
@@ -355,14 +358,32 @@ static inline void ipv6_addr_prefix(struct in6_addr *pfx,
355 pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b); 358 pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
356} 359}
357 360
361static inline void __ipv6_addr_set_half(__be32 *addr,
362 __be32 wh, __be32 wl)
363{
364#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
365#if defined(__BIG_ENDIAN)
366 if (__builtin_constant_p(wh) && __builtin_constant_p(wl)) {
367 *(__force u64 *)addr = ((__force u64)(wh) << 32 | (__force u64)(wl));
368 return;
369 }
370#elif defined(__LITTLE_ENDIAN)
371 if (__builtin_constant_p(wl) && __builtin_constant_p(wh)) {
372 *(__force u64 *)addr = ((__force u64)(wl) << 32 | (__force u64)(wh));
373 return;
374 }
375#endif
376#endif
377 addr[0] = wh;
378 addr[1] = wl;
379}
380
358static inline void ipv6_addr_set(struct in6_addr *addr, 381static inline void ipv6_addr_set(struct in6_addr *addr,
359 __be32 w1, __be32 w2, 382 __be32 w1, __be32 w2,
360 __be32 w3, __be32 w4) 383 __be32 w3, __be32 w4)
361{ 384{
362 addr->s6_addr32[0] = w1; 385 __ipv6_addr_set_half(&addr->s6_addr32[0], w1, w2);
363 addr->s6_addr32[1] = w2; 386 __ipv6_addr_set_half(&addr->s6_addr32[2], w3, w4);
364 addr->s6_addr32[2] = w3;
365 addr->s6_addr32[3] = w4;
366} 387}
367 388
368static inline bool ipv6_addr_equal(const struct in6_addr *a1, 389static inline bool ipv6_addr_equal(const struct in6_addr *a1,
@@ -381,9 +402,37 @@ static inline bool ipv6_addr_equal(const struct in6_addr *a1,
381#endif 402#endif
382} 403}
383 404
384static inline bool __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2, 405#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
385 unsigned int prefixlen) 406static inline bool __ipv6_prefix_equal64_half(const __be64 *a1,
407 const __be64 *a2,
408 unsigned int len)
409{
410 if (len && ((*a1 ^ *a2) & cpu_to_be64((~0UL) << (64 - len))))
411 return false;
412 return true;
413}
414
415static inline bool ipv6_prefix_equal(const struct in6_addr *addr1,
416 const struct in6_addr *addr2,
417 unsigned int prefixlen)
418{
419 const __be64 *a1 = (const __be64 *)addr1;
420 const __be64 *a2 = (const __be64 *)addr2;
421
422 if (prefixlen >= 64) {
423 if (a1[0] ^ a2[0])
424 return false;
425 return __ipv6_prefix_equal64_half(a1 + 1, a2 + 1, prefixlen - 64);
426 }
427 return __ipv6_prefix_equal64_half(a1, a2, prefixlen);
428}
429#else
430static inline bool ipv6_prefix_equal(const struct in6_addr *addr1,
431 const struct in6_addr *addr2,
432 unsigned int prefixlen)
386{ 433{
434 const __be32 *a1 = addr1->s6_addr32;
435 const __be32 *a2 = addr2->s6_addr32;
387 unsigned int pdw, pbi; 436 unsigned int pdw, pbi;
388 437
389 /* check complete u32 in prefix */ 438 /* check complete u32 in prefix */
@@ -398,14 +447,7 @@ static inline bool __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
398 447
399 return true; 448 return true;
400} 449}
401 450#endif
402static inline bool ipv6_prefix_equal(const struct in6_addr *a1,
403 const struct in6_addr *a2,
404 unsigned int prefixlen)
405{
406 return __ipv6_prefix_equal(a1->s6_addr32, a2->s6_addr32,
407 prefixlen);
408}
409 451
410struct inet_frag_queue; 452struct inet_frag_queue;
411 453
@@ -473,16 +515,38 @@ static inline u32 ipv6_addr_hash(const struct in6_addr *a)
473#endif 515#endif
474} 516}
475 517
518/* more secured version of ipv6_addr_hash() */
519static inline u32 ipv6_addr_jhash(const struct in6_addr *a)
520{
521 u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1];
522
523 return jhash_3words(v,
524 (__force u32)a->s6_addr32[2],
525 (__force u32)a->s6_addr32[3],
526 ipv6_hash_secret);
527}
528
476static inline bool ipv6_addr_loopback(const struct in6_addr *a) 529static inline bool ipv6_addr_loopback(const struct in6_addr *a)
477{ 530{
531#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
532 const unsigned long *ul = (const unsigned long *)a;
533
534 return (ul[0] | (ul[1] ^ cpu_to_be64(1))) == 0UL;
535#else
478 return (a->s6_addr32[0] | a->s6_addr32[1] | 536 return (a->s6_addr32[0] | a->s6_addr32[1] |
479 a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0; 537 a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0;
538#endif
480} 539}
481 540
482static inline bool ipv6_addr_v4mapped(const struct in6_addr *a) 541static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
483{ 542{
484 return (a->s6_addr32[0] | a->s6_addr32[1] | 543 return (
485 (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0; 544#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
545 *(__be64 *)a |
546#else
547 (a->s6_addr32[0] | a->s6_addr32[1]) |
548#endif
549 (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0UL;
486} 550}
487 551
488/* 552/*
@@ -507,7 +571,7 @@ static inline void ipv6_addr_set_v4mapped(const __be32 addr,
507 * find the first different bit between two addresses 571 * find the first different bit between two addresses
508 * length of address must be a multiple of 32bits 572 * length of address must be a multiple of 32bits
509 */ 573 */
510static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen) 574static inline int __ipv6_addr_diff32(const void *token1, const void *token2, int addrlen)
511{ 575{
512 const __be32 *a1 = token1, *a2 = token2; 576 const __be32 *a1 = token1, *a2 = token2;
513 int i; 577 int i;
@@ -539,6 +603,33 @@ static inline int __ipv6_addr_diff(const void *token1, const void *token2, int a
539 return addrlen << 5; 603 return addrlen << 5;
540} 604}
541 605
606#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
607static inline int __ipv6_addr_diff64(const void *token1, const void *token2, int addrlen)
608{
609 const __be64 *a1 = token1, *a2 = token2;
610 int i;
611
612 addrlen >>= 3;
613
614 for (i = 0; i < addrlen; i++) {
615 __be64 xb = a1[i] ^ a2[i];
616 if (xb)
617 return i * 64 + 63 - __fls(be64_to_cpu(xb));
618 }
619
620 return addrlen << 6;
621}
622#endif
623
624static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen)
625{
626#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
627 if (__builtin_constant_p(addrlen) && !(addrlen & 7))
628 return __ipv6_addr_diff64(token1, token2, addrlen);
629#endif
630 return __ipv6_addr_diff32(token1, token2, addrlen);
631}
632
542static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2) 633static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2)
543{ 634{
544 return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); 635 return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
@@ -547,6 +638,20 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
547extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt); 638extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
548 639
549/* 640/*
641 * Header manipulation
642 */
643static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass,
644 __be32 flowlabel)
645{
646 *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel;
647}
648
649static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr)
650{
651 return *(__be32 *)hdr & IPV6_FLOWINFO_MASK;
652}
653
654/*
550 * Prototypes exported by ipv6 655 * Prototypes exported by ipv6
551 */ 656 */
552 657
@@ -570,13 +675,6 @@ extern int ip6_xmit(struct sock *sk,
570 struct ipv6_txoptions *opt, 675 struct ipv6_txoptions *opt,
571 int tclass); 676 int tclass);
572 677
573extern int ip6_nd_hdr(struct sock *sk,
574 struct sk_buff *skb,
575 struct net_device *dev,
576 const struct in6_addr *saddr,
577 const struct in6_addr *daddr,
578 int proto, int len);
579
580extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr); 678extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
581 679
582extern int ip6_append_data(struct sock *sk, 680extern int ip6_append_data(struct sock *sk,