4444
4545/* we will save the tuples of all connections we care about */
4646struct nf_conncount_tuple {
47- struct hlist_node node ;
47+ struct list_head node ;
4848 struct nf_conntrack_tuple tuple ;
4949 struct nf_conntrack_zone zone ;
5050 int cpu ;
@@ -53,7 +53,7 @@ struct nf_conncount_tuple {
5353
5454struct nf_conncount_rb {
5555 struct rb_node node ;
56- struct hlist_head hhead ; /* connections/hosts in same subnet */
56+ struct nf_conncount_list list ;
5757 u32 key [MAX_KEYLEN ];
5858};
5959
@@ -82,26 +82,42 @@ static int key_diff(const u32 *a, const u32 *b, unsigned int klen)
8282 return memcmp (a , b , klen * sizeof (u32 ));
8383}
8484
85- bool nf_conncount_add (struct hlist_head * head ,
85+ bool nf_conncount_add (struct nf_conncount_list * list ,
8686 const struct nf_conntrack_tuple * tuple ,
8787 const struct nf_conntrack_zone * zone )
8888{
8989 struct nf_conncount_tuple * conn ;
9090
91+ if (WARN_ON_ONCE (list -> count > INT_MAX ))
92+ return false;
93+
9194 conn = kmem_cache_alloc (conncount_conn_cachep , GFP_ATOMIC );
9295 if (conn == NULL )
9396 return false;
9497 conn -> tuple = * tuple ;
9598 conn -> zone = * zone ;
9699 conn -> cpu = raw_smp_processor_id ();
97100 conn -> jiffies32 = (u32 )jiffies ;
98- hlist_add_head (& conn -> node , head );
101+ list_add_tail (& conn -> node , & list -> head );
102+ list -> count ++ ;
99103 return true;
100104}
101105EXPORT_SYMBOL_GPL (nf_conncount_add );
102106
107+ static void conn_free (struct nf_conncount_list * list ,
108+ struct nf_conncount_tuple * conn )
109+ {
110+ if (WARN_ON_ONCE (list -> count == 0 ))
111+ return ;
112+
113+ list -> count -- ;
114+ list_del (& conn -> node );
115+ kmem_cache_free (conncount_conn_cachep , conn );
116+ }
117+
103118static const struct nf_conntrack_tuple_hash *
104- find_or_evict (struct net * net , struct nf_conncount_tuple * conn )
119+ find_or_evict (struct net * net , struct nf_conncount_list * list ,
120+ struct nf_conncount_tuple * conn )
105121{
106122 const struct nf_conntrack_tuple_hash * found ;
107123 unsigned long a , b ;
@@ -121,30 +137,29 @@ find_or_evict(struct net *net, struct nf_conncount_tuple *conn)
121137 */
122138 age = a - b ;
123139 if (conn -> cpu == cpu || age >= 2 ) {
124- hlist_del (& conn -> node );
125- kmem_cache_free (conncount_conn_cachep , conn );
140+ conn_free (list , conn );
126141 return ERR_PTR (- ENOENT );
127142 }
128143
129144 return ERR_PTR (- EAGAIN );
130145}
131146
132- unsigned int nf_conncount_lookup (struct net * net , struct hlist_head * head ,
147+ unsigned int nf_conncount_lookup (struct net * net ,
148+ struct nf_conncount_list * list ,
133149 const struct nf_conntrack_tuple * tuple ,
134150 const struct nf_conntrack_zone * zone ,
135151 bool * addit )
136152{
137153 const struct nf_conntrack_tuple_hash * found ;
138- struct nf_conncount_tuple * conn ;
154+ struct nf_conncount_tuple * conn , * conn_n ;
139155 struct nf_conn * found_ct ;
140- struct hlist_node * n ;
141156 unsigned int length = 0 ;
142157
143158 * addit = tuple ? true : false;
144159
145160 /* check the saved connections */
146- hlist_for_each_entry_safe (conn , n , head , node ) {
147- found = find_or_evict (net , conn );
161+ list_for_each_entry_safe (conn , conn_n , & list -> head , node ) {
162+ found = find_or_evict (net , list , conn );
148163 if (IS_ERR (found )) {
149164 /* Not found, but might be about to be confirmed */
150165 if (PTR_ERR (found ) == - EAGAIN ) {
@@ -157,6 +172,7 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
157172 nf_ct_zone_id (zone , zone -> dir ))
158173 * addit = false;
159174 }
175+
160176 continue ;
161177 }
162178
@@ -176,8 +192,7 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
176192 * closed already -> ditch it
177193 */
178194 nf_ct_put (found_ct );
179- hlist_del (& conn -> node );
180- kmem_cache_free (conncount_conn_cachep , conn );
195+ conn_free (list , conn );
181196 continue ;
182197 }
183198
@@ -189,17 +204,23 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
189204}
190205EXPORT_SYMBOL_GPL (nf_conncount_lookup );
191206
207+ void nf_conncount_list_init (struct nf_conncount_list * list )
208+ {
209+ INIT_LIST_HEAD (& list -> head );
210+ list -> count = 1 ;
211+ }
212+ EXPORT_SYMBOL_GPL (nf_conncount_list_init );
213+
192214static void nf_conncount_gc_list (struct net * net ,
193- struct nf_conncount_rb * rbconn )
215+ struct nf_conncount_list * list )
194216{
195217 const struct nf_conntrack_tuple_hash * found ;
196- struct nf_conncount_tuple * conn ;
197- struct hlist_node * n ;
218+ struct nf_conncount_tuple * conn , * conn_n ;
198219 struct nf_conn * found_ct ;
199220 unsigned int collected = 0 ;
200221
201- hlist_for_each_entry_safe (conn , n , & rbconn -> hhead , node ) {
202- found = find_or_evict (net , conn );
222+ list_for_each_entry_safe (conn , conn_n , & list -> head , node ) {
223+ found = find_or_evict (net , list , conn );
203224 if (IS_ERR (found )) {
204225 if (PTR_ERR (found ) == - ENOENT )
205226 collected ++ ;
@@ -213,8 +234,7 @@ static void nf_conncount_gc_list(struct net *net,
213234 * closed already -> ditch it
214235 */
215236 nf_ct_put (found_ct );
216- hlist_del (& conn -> node );
217- kmem_cache_free (conncount_conn_cachep , conn );
237+ conn_free (list , conn );
218238 collected ++ ;
219239 continue ;
220240 }
@@ -271,14 +291,14 @@ count_tree(struct net *net, struct rb_root *root,
271291 /* same source network -> be counted! */
272292 unsigned int count ;
273293
274- count = nf_conncount_lookup (net , & rbconn -> hhead , tuple ,
294+ count = nf_conncount_lookup (net , & rbconn -> list , tuple ,
275295 zone , & addit );
276296
277297 tree_nodes_free (root , gc_nodes , gc_count );
278298 if (!addit )
279299 return count ;
280300
281- if (!nf_conncount_add (& rbconn -> hhead , tuple , zone ))
301+ if (!nf_conncount_add (& rbconn -> list , tuple , zone ))
282302 return 0 ; /* hotdrop */
283303
284304 return count + 1 ;
@@ -287,8 +307,8 @@ count_tree(struct net *net, struct rb_root *root,
287307 if (no_gc || gc_count >= ARRAY_SIZE (gc_nodes ))
288308 continue ;
289309
290- nf_conncount_gc_list (net , rbconn );
291- if (hlist_empty (& rbconn -> hhead ))
310+ nf_conncount_gc_list (net , & rbconn -> list );
311+ if (list_empty (& rbconn -> list . head ))
292312 gc_nodes [gc_count ++ ] = rbconn ;
293313 }
294314
@@ -322,8 +342,8 @@ count_tree(struct net *net, struct rb_root *root,
322342 conn -> zone = * zone ;
323343 memcpy (rbconn -> key , key , sizeof (u32 ) * keylen );
324344
325- INIT_HLIST_HEAD (& rbconn -> hhead );
326- hlist_add_head (& conn -> node , & rbconn -> hhead );
345+ nf_conncount_list_init (& rbconn -> list );
346+ list_add (& conn -> node , & rbconn -> list . head );
327347
328348 rb_link_node (& rbconn -> node , parent , rbnode );
329349 rb_insert_color (& rbconn -> node , root );
@@ -388,12 +408,11 @@ struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family
388408}
389409EXPORT_SYMBOL_GPL (nf_conncount_init );
390410
391- void nf_conncount_cache_free (struct hlist_head * hhead )
411+ void nf_conncount_cache_free (struct nf_conncount_list * list )
392412{
393- struct nf_conncount_tuple * conn ;
394- struct hlist_node * n ;
413+ struct nf_conncount_tuple * conn , * conn_n ;
395414
396- hlist_for_each_entry_safe (conn , n , hhead , node )
415+ list_for_each_entry_safe (conn , conn_n , & list -> head , node )
397416 kmem_cache_free (conncount_conn_cachep , conn );
398417}
399418EXPORT_SYMBOL_GPL (nf_conncount_cache_free );
@@ -408,7 +427,7 @@ static void destroy_tree(struct rb_root *r)
408427
409428 rb_erase (node , r );
410429
411- nf_conncount_cache_free (& rbconn -> hhead );
430+ nf_conncount_cache_free (& rbconn -> list );
412431
413432 kmem_cache_free (conncount_rb_cachep , rbconn );
414433 }
0 commit comments