| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | *		INETPEER - A storage for permanent information about peers | 
|  | 3 | * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4 | *  Authors:	Andrey V. Savochkin <saw@msu.ru> | 
|  | 5 | */ | 
|  | 6 |  | 
|  | 7 | #ifndef _NET_INETPEER_H | 
|  | 8 | #define _NET_INETPEER_H | 
|  | 9 |  | 
|  | 10 | #include <linux/types.h> | 
|  | 11 | #include <linux/init.h> | 
|  | 12 | #include <linux/jiffies.h> | 
|  | 13 | #include <linux/spinlock.h> | 
| David S. Miller | 6065982 | 2011-01-26 20:55:53 -0800 | [diff] [blame] | 14 | #include <linux/rtnetlink.h> | 
| David S. Miller | 672f007 | 2010-11-30 12:20:00 -0800 | [diff] [blame] | 15 | #include <net/ipv6.h> | 
| Arun Sharma | 60063497 | 2011-07-26 16:09:06 -0700 | [diff] [blame] | 16 | #include <linux/atomic.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 17 |  | 
| David S. Miller | 7a71ed8 | 2011-02-09 14:30:26 -0800 | [diff] [blame] | 18 | struct inetpeer_addr_base { | 
| David S. Miller | 582a72d | 2010-11-30 11:53:55 -0800 | [diff] [blame] | 19 | union { | 
| David S. Miller | 7a71ed8 | 2011-02-09 14:30:26 -0800 | [diff] [blame] | 20 | __be32			a4; | 
|  | 21 | __be32			a6[4]; | 
| David S. Miller | 582a72d | 2010-11-30 11:53:55 -0800 | [diff] [blame] | 22 | }; | 
| David S. Miller | 7a71ed8 | 2011-02-09 14:30:26 -0800 | [diff] [blame] | 23 | }; | 
|  | 24 |  | 
|  | 25 | struct inetpeer_addr { | 
|  | 26 | struct inetpeer_addr_base	addr; | 
|  | 27 | __u16				family; | 
| David S. Miller | 8790ca1 | 2010-12-01 17:28:18 -0800 | [diff] [blame] | 28 | }; | 
| David S. Miller | 582a72d | 2010-11-30 11:53:55 -0800 | [diff] [blame] | 29 |  | 
| Eric Dumazet | fd2c3ef | 2009-11-03 03:26:03 +0000 | [diff] [blame] | 30 | struct inet_peer { | 
| Eric Dumazet | 78d7942 | 2006-10-20 00:28:35 -0700 | [diff] [blame] | 31 | /* group together avl_left,avl_right,v4daddr to speedup lookups */ | 
| Eric Dumazet | b914c4e | 2010-10-25 23:55:38 +0000 | [diff] [blame] | 32 | struct inet_peer __rcu	*avl_left, *avl_right; | 
| David S. Miller | 8790ca1 | 2010-12-01 17:28:18 -0800 | [diff] [blame] | 33 | struct inetpeer_addr	daddr; | 
| Eric Dumazet | 2c1409a | 2009-11-12 09:33:09 +0000 | [diff] [blame] | 34 | __u32			avl_height; | 
| Eric Dumazet | 2b77bdd | 2011-06-08 23:31:27 -0700 | [diff] [blame] | 35 |  | 
|  | 36 | u32			metrics[RTAX_MAX]; | 
|  | 37 | u32			rate_tokens;	/* rate limiting for ICMP */ | 
|  | 38 | unsigned long		rate_last; | 
|  | 39 | unsigned long		pmtu_expires; | 
|  | 40 | u32			pmtu_orig; | 
|  | 41 | u32			pmtu_learned; | 
|  | 42 | struct inetpeer_addr_base redirect_learned; | 
| Eric Dumazet | 55432d2 | 2012-06-05 03:00:18 +0000 | [diff] [blame] | 43 | union { | 
|  | 44 | struct list_head	gc_list; | 
|  | 45 | struct rcu_head     gc_rcu; | 
|  | 46 | }; | 
| Eric Dumazet | 317fe0e | 2010-06-16 04:52:13 +0000 | [diff] [blame] | 47 | /* | 
|  | 48 | * Once inet_peer is queued for deletion (refcnt == -1), following fields | 
| Eric Dumazet | 2b77bdd | 2011-06-08 23:31:27 -0700 | [diff] [blame] | 49 | * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp | 
| David S. Miller | 6065982 | 2011-01-26 20:55:53 -0800 | [diff] [blame] | 50 | * We can share memory with rcu_head to help keep inet_peer small. | 
| Eric Dumazet | 317fe0e | 2010-06-16 04:52:13 +0000 | [diff] [blame] | 51 | */ | 
|  | 52 | union { | 
|  | 53 | struct { | 
| David S. Miller | ddd4aa4 | 2011-02-09 15:36:47 -0800 | [diff] [blame] | 54 | atomic_t			rid;		/* Frag reception counter */ | 
|  | 55 | atomic_t			ip_id_count;	/* IP ID for the next packet */ | 
|  | 56 | __u32				tcp_ts; | 
|  | 57 | __u32				tcp_ts_stamp; | 
| Eric Dumazet | 317fe0e | 2010-06-16 04:52:13 +0000 | [diff] [blame] | 58 | }; | 
|  | 59 | struct rcu_head         rcu; | 
| Eric Dumazet | 4b9d9be | 2011-06-08 13:35:34 +0000 | [diff] [blame] | 60 | struct inet_peer	*gc_next; | 
| Eric Dumazet | 317fe0e | 2010-06-16 04:52:13 +0000 | [diff] [blame] | 61 | }; | 
| Eric Dumazet | 2b77bdd | 2011-06-08 23:31:27 -0700 | [diff] [blame] | 62 |  | 
|  | 63 | /* following fields might be frequently dirtied */ | 
|  | 64 | __u32			dtime;	/* the time of last use of not referenced entries */ | 
|  | 65 | atomic_t		refcnt; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 66 | }; | 
|  | 67 |  | 
|  | 68 | void			inet_initpeers(void) __init; | 
|  | 69 |  | 
| David S. Miller | 144001b | 2011-01-27 13:52:16 -0800 | [diff] [blame] | 70 | #define INETPEER_METRICS_NEW	(~(u32) 0) | 
|  | 71 |  | 
|  | 72 | static inline bool inet_metrics_new(const struct inet_peer *p) | 
|  | 73 | { | 
|  | 74 | return p->metrics[RTAX_LOCK-1] == INETPEER_METRICS_NEW; | 
|  | 75 | } | 
|  | 76 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 77 | /* can be called with or without local BH being disabled */ | 
| Eric Dumazet | 87c48fa | 2011-07-21 21:25:58 -0700 | [diff] [blame] | 78 | struct inet_peer	*inet_getpeer(const struct inetpeer_addr *daddr, int create); | 
| David S. Miller | b534ecf | 2010-11-30 11:54:19 -0800 | [diff] [blame] | 79 |  | 
|  | 80 | static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create) | 
|  | 81 | { | 
| David S. Miller | 8790ca1 | 2010-12-01 17:28:18 -0800 | [diff] [blame] | 82 | struct inetpeer_addr daddr; | 
| David S. Miller | b534ecf | 2010-11-30 11:54:19 -0800 | [diff] [blame] | 83 |  | 
| David S. Miller | 7a71ed8 | 2011-02-09 14:30:26 -0800 | [diff] [blame] | 84 | daddr.addr.a4 = v4daddr; | 
| David S. Miller | b534ecf | 2010-11-30 11:54:19 -0800 | [diff] [blame] | 85 | daddr.family = AF_INET; | 
|  | 86 | return inet_getpeer(&daddr, create); | 
|  | 87 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 |  | 
| Eric Dumazet | b71d1d4 | 2011-04-22 04:53:02 +0000 | [diff] [blame] | 89 | static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create) | 
| David S. Miller | 672f007 | 2010-11-30 12:20:00 -0800 | [diff] [blame] | 90 | { | 
| David S. Miller | 8790ca1 | 2010-12-01 17:28:18 -0800 | [diff] [blame] | 91 | struct inetpeer_addr daddr; | 
| David S. Miller | 672f007 | 2010-11-30 12:20:00 -0800 | [diff] [blame] | 92 |  | 
| Alexey Dobriyan | 4e3fd7a | 2011-11-21 03:39:03 +0000 | [diff] [blame] | 93 | *(struct in6_addr *)daddr.addr.a6 = *v6daddr; | 
| David S. Miller | 672f007 | 2010-11-30 12:20:00 -0800 | [diff] [blame] | 94 | daddr.family = AF_INET6; | 
|  | 95 | return inet_getpeer(&daddr, create); | 
|  | 96 | } | 
|  | 97 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 | /* can be called from BH context or outside */ | 
| Eric Dumazet | 4663afe | 2006-10-12 21:21:06 -0700 | [diff] [blame] | 99 | extern void inet_putpeer(struct inet_peer *p); | 
| David S. Miller | 92d8682 | 2011-02-04 15:55:25 -0800 | [diff] [blame] | 100 | extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 101 |  | 
| Steffen Klassert | 5faa5df | 2012-03-06 21:20:26 +0000 | [diff] [blame] | 102 | extern void inetpeer_invalidate_tree(int family); | 
|  | 103 |  | 
| Eric Dumazet | 317fe0e | 2010-06-16 04:52:13 +0000 | [diff] [blame] | 104 | /* | 
|  | 105 | * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, | 
|  | 106 | * tcp_ts_stamp if no refcount is taken on inet_peer | 
|  | 107 | */ | 
|  | 108 | static inline void inet_peer_refcheck(const struct inet_peer *p) | 
|  | 109 | { | 
|  | 110 | WARN_ON_ONCE(atomic_read(&p->refcnt) <= 0); | 
|  | 111 | } | 
|  | 112 |  | 
|  | 113 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 114 | /* can be called with or without local BH being disabled */ | 
| Eric Dumazet | 87c48fa | 2011-07-21 21:25:58 -0700 | [diff] [blame] | 115 | static inline int inet_getid(struct inet_peer *p, int more) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 116 | { | 
| Eric Dumazet | 87c48fa | 2011-07-21 21:25:58 -0700 | [diff] [blame] | 117 | int old, new; | 
| Eric Dumazet | 2c1409a | 2009-11-12 09:33:09 +0000 | [diff] [blame] | 118 | more++; | 
| Eric Dumazet | 317fe0e | 2010-06-16 04:52:13 +0000 | [diff] [blame] | 119 | inet_peer_refcheck(p); | 
| Eric Dumazet | 87c48fa | 2011-07-21 21:25:58 -0700 | [diff] [blame] | 120 | do { | 
|  | 121 | old = atomic_read(&p->ip_id_count); | 
|  | 122 | new = old + more; | 
|  | 123 | if (!new) | 
|  | 124 | new = 1; | 
|  | 125 | } while (atomic_cmpxchg(&p->ip_id_count, old, new) != old); | 
|  | 126 | return new; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 127 | } | 
|  | 128 |  | 
|  | 129 | #endif /* _NET_INETPEER_H */ |