diff options
Diffstat (limited to 'include/net/inetpeer.h')
-rw-r--r-- | include/net/inetpeer.h | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index 2040bff945d4..c27c8f10ebdc 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h | |||
@@ -65,6 +65,69 @@ struct inet_peer { | |||
65 | atomic_t refcnt; | 65 | atomic_t refcnt; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct inet_peer_base { | ||
69 | struct inet_peer __rcu *root; | ||
70 | seqlock_t lock; | ||
71 | u32 flush_seq; | ||
72 | int total; | ||
73 | }; | ||
74 | |||
75 | #define INETPEER_BASE_BIT 0x1UL | ||
76 | |||
77 | static inline struct inet_peer *inetpeer_ptr(unsigned long val) | ||
78 | { | ||
79 | BUG_ON(val & INETPEER_BASE_BIT); | ||
80 | return (struct inet_peer *) val; | ||
81 | } | ||
82 | |||
83 | static inline struct inet_peer_base *inetpeer_base_ptr(unsigned long val) | ||
84 | { | ||
85 | if (!(val & INETPEER_BASE_BIT)) | ||
86 | return NULL; | ||
87 | val &= ~INETPEER_BASE_BIT; | ||
88 | return (struct inet_peer_base *) val; | ||
89 | } | ||
90 | |||
91 | static inline bool inetpeer_ptr_is_peer(unsigned long val) | ||
92 | { | ||
93 | return !(val & INETPEER_BASE_BIT); | ||
94 | } | ||
95 | |||
96 | static inline void __inetpeer_ptr_set_peer(unsigned long *val, struct inet_peer *peer) | ||
97 | { | ||
98 | /* This implicitly clears INETPEER_BASE_BIT */ | ||
99 | *val = (unsigned long) peer; | ||
100 | } | ||
101 | |||
102 | static inline bool inetpeer_ptr_set_peer(unsigned long *ptr, struct inet_peer *peer) | ||
103 | { | ||
104 | unsigned long val = (unsigned long) peer; | ||
105 | unsigned long orig = *ptr; | ||
106 | |||
107 | if (!(orig & INETPEER_BASE_BIT) || | ||
108 | cmpxchg(ptr, orig, val) != orig) | ||
109 | return false; | ||
110 | return true; | ||
111 | } | ||
112 | |||
113 | static inline void inetpeer_init_ptr(unsigned long *ptr, struct inet_peer_base *base) | ||
114 | { | ||
115 | *ptr = (unsigned long) base | INETPEER_BASE_BIT; | ||
116 | } | ||
117 | |||
118 | static inline void inetpeer_transfer_peer(unsigned long *to, unsigned long *from) | ||
119 | { | ||
120 | unsigned long val = *from; | ||
121 | |||
122 | *to = val; | ||
123 | if (inetpeer_ptr_is_peer(val)) { | ||
124 | struct inet_peer *peer = inetpeer_ptr(val); | ||
125 | atomic_inc(&peer->refcnt); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | extern void inet_peer_base_init(struct inet_peer_base *); | ||
130 | |||
68 | void inet_initpeers(void) __init; | 131 | void inet_initpeers(void) __init; |
69 | 132 | ||
70 | #define INETPEER_METRICS_NEW (~(u32) 0) | 133 | #define INETPEER_METRICS_NEW (~(u32) 0) |
@@ -75,31 +138,38 @@ static inline bool inet_metrics_new(const struct inet_peer *p) | |||
75 | } | 138 | } |
76 | 139 | ||
77 | /* can be called with or without local BH being disabled */ | 140 | /* can be called with or without local BH being disabled */ |
78 | struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create); | 141 | struct inet_peer *inet_getpeer(struct inet_peer_base *base, |
142 | const struct inetpeer_addr *daddr, | ||
143 | int create); | ||
79 | 144 | ||
80 | static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create) | 145 | static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base, |
146 | __be32 v4daddr, | ||
147 | int create) | ||
81 | { | 148 | { |
82 | struct inetpeer_addr daddr; | 149 | struct inetpeer_addr daddr; |
83 | 150 | ||
84 | daddr.addr.a4 = v4daddr; | 151 | daddr.addr.a4 = v4daddr; |
85 | daddr.family = AF_INET; | 152 | daddr.family = AF_INET; |
86 | return inet_getpeer(&daddr, create); | 153 | return inet_getpeer(base, &daddr, create); |
87 | } | 154 | } |
88 | 155 | ||
89 | static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create) | 156 | static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base, |
157 | const struct in6_addr *v6daddr, | ||
158 | int create) | ||
90 | { | 159 | { |
91 | struct inetpeer_addr daddr; | 160 | struct inetpeer_addr daddr; |
92 | 161 | ||
93 | *(struct in6_addr *)daddr.addr.a6 = *v6daddr; | 162 | *(struct in6_addr *)daddr.addr.a6 = *v6daddr; |
94 | daddr.family = AF_INET6; | 163 | daddr.family = AF_INET6; |
95 | return inet_getpeer(&daddr, create); | 164 | return inet_getpeer(base, &daddr, create); |
96 | } | 165 | } |
97 | 166 | ||
98 | /* can be called from BH context or outside */ | 167 | /* can be called from BH context or outside */ |
99 | extern void inet_putpeer(struct inet_peer *p); | 168 | extern void inet_putpeer(struct inet_peer *p); |
100 | extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); | 169 | extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); |
101 | 170 | ||
102 | extern void inetpeer_invalidate_tree(int family); | 171 | extern void inetpeer_invalidate_tree(struct inet_peer_base *); |
172 | extern void inetpeer_invalidate_family(int family); | ||
103 | 173 | ||
104 | /* | 174 | /* |
105 | * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, | 175 | * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, |