diff options
Diffstat (limited to 'include/net/inetpeer.h')
-rw-r--r-- | include/net/inetpeer.h | 95 |
1 files changed, 81 insertions, 14 deletions
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index b94765e38e80..53f464d7cddc 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h | |||
@@ -36,22 +36,19 @@ struct inet_peer { | |||
36 | u32 metrics[RTAX_MAX]; | 36 | u32 metrics[RTAX_MAX]; |
37 | u32 rate_tokens; /* rate limiting for ICMP */ | 37 | u32 rate_tokens; /* rate limiting for ICMP */ |
38 | unsigned long rate_last; | 38 | unsigned long rate_last; |
39 | unsigned long pmtu_expires; | 39 | union { |
40 | u32 pmtu_orig; | 40 | struct list_head gc_list; |
41 | u32 pmtu_learned; | 41 | struct rcu_head gc_rcu; |
42 | struct inetpeer_addr_base redirect_learned; | 42 | }; |
43 | struct list_head gc_list; | ||
44 | /* | 43 | /* |
45 | * Once inet_peer is queued for deletion (refcnt == -1), following fields | 44 | * Once inet_peer is queued for deletion (refcnt == -1), following fields |
46 | * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp | 45 | * are not available: rid, ip_id_count |
47 | * We can share memory with rcu_head to help keep inet_peer small. | 46 | * We can share memory with rcu_head to help keep inet_peer small. |
48 | */ | 47 | */ |
49 | union { | 48 | union { |
50 | struct { | 49 | struct { |
51 | atomic_t rid; /* Frag reception counter */ | 50 | atomic_t rid; /* Frag reception counter */ |
52 | atomic_t ip_id_count; /* IP ID for the next packet */ | 51 | atomic_t ip_id_count; /* IP ID for the next packet */ |
53 | __u32 tcp_ts; | ||
54 | __u32 tcp_ts_stamp; | ||
55 | }; | 52 | }; |
56 | struct rcu_head rcu; | 53 | struct rcu_head rcu; |
57 | struct inet_peer *gc_next; | 54 | struct inet_peer *gc_next; |
@@ -62,6 +59,69 @@ struct inet_peer { | |||
62 | atomic_t refcnt; | 59 | atomic_t refcnt; |
63 | }; | 60 | }; |
64 | 61 | ||
62 | struct inet_peer_base { | ||
63 | struct inet_peer __rcu *root; | ||
64 | seqlock_t lock; | ||
65 | u32 flush_seq; | ||
66 | int total; | ||
67 | }; | ||
68 | |||
69 | #define INETPEER_BASE_BIT 0x1UL | ||
70 | |||
71 | static inline struct inet_peer *inetpeer_ptr(unsigned long val) | ||
72 | { | ||
73 | BUG_ON(val & INETPEER_BASE_BIT); | ||
74 | return (struct inet_peer *) val; | ||
75 | } | ||
76 | |||
77 | static inline struct inet_peer_base *inetpeer_base_ptr(unsigned long val) | ||
78 | { | ||
79 | if (!(val & INETPEER_BASE_BIT)) | ||
80 | return NULL; | ||
81 | val &= ~INETPEER_BASE_BIT; | ||
82 | return (struct inet_peer_base *) val; | ||
83 | } | ||
84 | |||
85 | static inline bool inetpeer_ptr_is_peer(unsigned long val) | ||
86 | { | ||
87 | return !(val & INETPEER_BASE_BIT); | ||
88 | } | ||
89 | |||
90 | static inline void __inetpeer_ptr_set_peer(unsigned long *val, struct inet_peer *peer) | ||
91 | { | ||
92 | /* This implicitly clears INETPEER_BASE_BIT */ | ||
93 | *val = (unsigned long) peer; | ||
94 | } | ||
95 | |||
96 | static inline bool inetpeer_ptr_set_peer(unsigned long *ptr, struct inet_peer *peer) | ||
97 | { | ||
98 | unsigned long val = (unsigned long) peer; | ||
99 | unsigned long orig = *ptr; | ||
100 | |||
101 | if (!(orig & INETPEER_BASE_BIT) || | ||
102 | cmpxchg(ptr, orig, val) != orig) | ||
103 | return false; | ||
104 | return true; | ||
105 | } | ||
106 | |||
107 | static inline void inetpeer_init_ptr(unsigned long *ptr, struct inet_peer_base *base) | ||
108 | { | ||
109 | *ptr = (unsigned long) base | INETPEER_BASE_BIT; | ||
110 | } | ||
111 | |||
112 | static inline void inetpeer_transfer_peer(unsigned long *to, unsigned long *from) | ||
113 | { | ||
114 | unsigned long val = *from; | ||
115 | |||
116 | *to = val; | ||
117 | if (inetpeer_ptr_is_peer(val)) { | ||
118 | struct inet_peer *peer = inetpeer_ptr(val); | ||
119 | atomic_inc(&peer->refcnt); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | extern void inet_peer_base_init(struct inet_peer_base *); | ||
124 | |||
65 | void inet_initpeers(void) __init; | 125 | void inet_initpeers(void) __init; |
66 | 126 | ||
67 | #define INETPEER_METRICS_NEW (~(u32) 0) | 127 | #define INETPEER_METRICS_NEW (~(u32) 0) |
@@ -72,31 +132,38 @@ static inline bool inet_metrics_new(const struct inet_peer *p) | |||
72 | } | 132 | } |
73 | 133 | ||
74 | /* can be called with or without local BH being disabled */ | 134 | /* can be called with or without local BH being disabled */ |
75 | struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create); | 135 | struct inet_peer *inet_getpeer(struct inet_peer_base *base, |
136 | const struct inetpeer_addr *daddr, | ||
137 | int create); | ||
76 | 138 | ||
77 | static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create) | 139 | static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base, |
140 | __be32 v4daddr, | ||
141 | int create) | ||
78 | { | 142 | { |
79 | struct inetpeer_addr daddr; | 143 | struct inetpeer_addr daddr; |
80 | 144 | ||
81 | daddr.addr.a4 = v4daddr; | 145 | daddr.addr.a4 = v4daddr; |
82 | daddr.family = AF_INET; | 146 | daddr.family = AF_INET; |
83 | return inet_getpeer(&daddr, create); | 147 | return inet_getpeer(base, &daddr, create); |
84 | } | 148 | } |
85 | 149 | ||
86 | static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create) | 150 | static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base, |
151 | const struct in6_addr *v6daddr, | ||
152 | int create) | ||
87 | { | 153 | { |
88 | struct inetpeer_addr daddr; | 154 | struct inetpeer_addr daddr; |
89 | 155 | ||
90 | *(struct in6_addr *)daddr.addr.a6 = *v6daddr; | 156 | *(struct in6_addr *)daddr.addr.a6 = *v6daddr; |
91 | daddr.family = AF_INET6; | 157 | daddr.family = AF_INET6; |
92 | return inet_getpeer(&daddr, create); | 158 | return inet_getpeer(base, &daddr, create); |
93 | } | 159 | } |
94 | 160 | ||
95 | /* can be called from BH context or outside */ | 161 | /* can be called from BH context or outside */ |
96 | extern void inet_putpeer(struct inet_peer *p); | 162 | extern void inet_putpeer(struct inet_peer *p); |
97 | extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); | 163 | extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); |
98 | 164 | ||
99 | extern void inetpeer_invalidate_tree(int family); | 165 | extern void inetpeer_invalidate_tree(struct inet_peer_base *); |
166 | extern void inetpeer_invalidate_family(int family); | ||
100 | 167 | ||
101 | /* | 168 | /* |
102 | * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, | 169 | * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, |