46
46
#include <net/act_api.h>
47
47
#include <net/pkt_cls.h>
48
48
#include <linux/netdevice.h>
49
+ #include <linux/idr.h>
49
50
50
51
struct tc_u_knode {
51
52
struct tc_u_knode __rcu * next ;
@@ -82,6 +83,7 @@ struct tc_u_hnode {
82
83
struct tc_u_common * tp_c ;
83
84
int refcnt ;
84
85
unsigned int divisor ;
86
+ struct idr handle_idr ;
85
87
struct rcu_head rcu ;
86
88
/* The 'ht' field MUST be the last field in structure to allow for
87
89
* more entries allocated at end of structure.
@@ -93,7 +95,7 @@ struct tc_u_common {
93
95
struct tc_u_hnode __rcu * hlist ;
94
96
struct Qdisc * q ;
95
97
int refcnt ;
96
- u32 hgenerator ;
98
+ struct idr handle_idr ;
97
99
struct hlist_node hnode ;
98
100
struct rcu_head rcu ;
99
101
};
@@ -311,19 +313,19 @@ static void *u32_get(struct tcf_proto *tp, u32 handle)
311
313
return u32_lookup_key (ht , handle );
312
314
}
313
315
314
- static u32 gen_new_htid (struct tc_u_common * tp_c )
316
+ static u32 gen_new_htid (struct tc_u_common * tp_c , struct tc_u_hnode * ptr )
315
317
{
316
- int i = 0x800 ;
318
+ unsigned long idr_index ;
319
+ int err ;
317
320
318
- /* hgenerator only used inside rtnl lock it is safe to increment
321
+ /* This is only used inside rtnl lock it is safe to increment
319
322
* without read _copy_ update semantics
320
323
*/
321
- do {
322
- if (++ tp_c -> hgenerator == 0x7FF )
323
- tp_c -> hgenerator = 1 ;
324
- } while (-- i > 0 && u32_lookup_ht (tp_c , (tp_c -> hgenerator |0x800 )<<20 ));
325
-
326
- return i > 0 ? (tp_c -> hgenerator |0x800 )<<20 : 0 ;
324
+ err = idr_alloc_ext (& tp_c -> handle_idr , ptr , & idr_index ,
325
+ 1 , 0x7FF , GFP_KERNEL );
326
+ if (err )
327
+ return 0 ;
328
+ return (u32 )(idr_index | 0x800 ) << 20 ;
327
329
}
328
330
329
331
static struct hlist_head * tc_u_common_hash ;
@@ -366,8 +368,9 @@ static int u32_init(struct tcf_proto *tp)
366
368
return - ENOBUFS ;
367
369
368
370
root_ht -> refcnt ++ ;
369
- root_ht -> handle = tp_c ? gen_new_htid (tp_c ) : 0x80000000 ;
371
+ root_ht -> handle = tp_c ? gen_new_htid (tp_c , root_ht ) : 0x80000000 ;
370
372
root_ht -> prio = tp -> prio ;
373
+ idr_init (& root_ht -> handle_idr );
371
374
372
375
if (tp_c == NULL ) {
373
376
tp_c = kzalloc (sizeof (* tp_c ), GFP_KERNEL );
@@ -377,6 +380,7 @@ static int u32_init(struct tcf_proto *tp)
377
380
}
378
381
tp_c -> q = tp -> q ;
379
382
INIT_HLIST_NODE (& tp_c -> hnode );
383
+ idr_init (& tp_c -> handle_idr );
380
384
381
385
h = tc_u_hash (tp );
382
386
hlist_add_head (& tp_c -> hnode , & tc_u_common_hash [h ]);
@@ -565,6 +569,7 @@ static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
565
569
rtnl_dereference (n -> next ));
566
570
tcf_unbind_filter (tp , & n -> res );
567
571
u32_remove_hw_knode (tp , n -> handle );
572
+ idr_remove_ext (& ht -> handle_idr , n -> handle );
568
573
call_rcu (& n -> rcu , u32_delete_key_freepf_rcu );
569
574
}
570
575
}
@@ -586,6 +591,8 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
586
591
hn = & phn -> next , phn = rtnl_dereference (* hn )) {
587
592
if (phn == ht ) {
588
593
u32_clear_hw_hnode (tp , ht );
594
+ idr_destroy (& ht -> handle_idr );
595
+ idr_remove_ext (& tp_c -> handle_idr , ht -> handle );
589
596
RCU_INIT_POINTER (* hn , ht -> next );
590
597
kfree_rcu (ht , rcu );
591
598
return 0 ;
@@ -633,6 +640,7 @@ static void u32_destroy(struct tcf_proto *tp)
633
640
kfree_rcu (ht , rcu );
634
641
}
635
642
643
+ idr_destroy (& tp_c -> handle_idr );
636
644
kfree (tp_c );
637
645
}
638
646
@@ -701,27 +709,21 @@ static int u32_delete(struct tcf_proto *tp, void *arg, bool *last)
701
709
return ret ;
702
710
}
703
711
704
- #define NR_U32_NODE (1<<12)
705
- static u32 gen_new_kid (struct tc_u_hnode * ht , u32 handle )
712
+ static u32 gen_new_kid (struct tc_u_hnode * ht , u32 htid )
706
713
{
707
- struct tc_u_knode * n ;
708
- unsigned long i ;
709
- unsigned long * bitmap = kzalloc (BITS_TO_LONGS (NR_U32_NODE ) * sizeof (unsigned long ),
710
- GFP_KERNEL );
711
- if (!bitmap )
712
- return handle | 0xFFF ;
713
-
714
- for (n = rtnl_dereference (ht -> ht [TC_U32_HASH (handle )]);
715
- n ;
716
- n = rtnl_dereference (n -> next ))
717
- set_bit (TC_U32_NODE (n -> handle ), bitmap );
718
-
719
- i = find_next_zero_bit (bitmap , NR_U32_NODE , 0x800 );
720
- if (i >= NR_U32_NODE )
721
- i = find_next_zero_bit (bitmap , NR_U32_NODE , 1 );
714
+ unsigned long idr_index ;
715
+ u32 start = htid | 0x800 ;
716
+ u32 max = htid | 0xFFF ;
717
+ u32 min = htid ;
718
+
719
+ if (idr_alloc_ext (& ht -> handle_idr , NULL , & idr_index ,
720
+ start , max + 1 , GFP_KERNEL )) {
721
+ if (idr_alloc_ext (& ht -> handle_idr , NULL , & idr_index ,
722
+ min + 1 , max + 1 , GFP_KERNEL ))
723
+ return max ;
724
+ }
722
725
723
- kfree (bitmap );
724
- return handle | (i >= NR_U32_NODE ? 0xFFF : i );
726
+ return (u32 )idr_index ;
725
727
}
726
728
727
729
static const struct nla_policy u32_policy [TCA_U32_MAX + 1 ] = {
@@ -806,6 +808,7 @@ static void u32_replace_knode(struct tcf_proto *tp, struct tc_u_common *tp_c,
806
808
if (pins -> handle == n -> handle )
807
809
break ;
808
810
811
+ idr_replace_ext (& ht -> handle_idr , n , n -> handle );
809
812
RCU_INIT_POINTER (n -> next , pins -> next );
810
813
rcu_assign_pointer (* ins , n );
811
814
}
@@ -937,22 +940,33 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
937
940
return - EINVAL ;
938
941
if (TC_U32_KEY (handle ))
939
942
return - EINVAL ;
940
- if (handle == 0 ) {
941
- handle = gen_new_htid (tp -> data );
942
- if (handle == 0 )
943
- return - ENOMEM ;
944
- }
945
943
ht = kzalloc (sizeof (* ht ) + divisor * sizeof (void * ), GFP_KERNEL );
946
944
if (ht == NULL )
947
945
return - ENOBUFS ;
946
+ if (handle == 0 ) {
947
+ handle = gen_new_htid (tp -> data , ht );
948
+ if (handle == 0 ) {
949
+ kfree (ht );
950
+ return - ENOMEM ;
951
+ }
952
+ } else {
953
+ err = idr_alloc_ext (& tp_c -> handle_idr , ht , NULL ,
954
+ handle , handle + 1 , GFP_KERNEL );
955
+ if (err ) {
956
+ kfree (ht );
957
+ return err ;
958
+ }
959
+ }
948
960
ht -> tp_c = tp_c ;
949
961
ht -> refcnt = 1 ;
950
962
ht -> divisor = divisor ;
951
963
ht -> handle = handle ;
952
964
ht -> prio = tp -> prio ;
965
+ idr_init (& ht -> handle_idr );
953
966
954
967
err = u32_replace_hw_hnode (tp , ht , flags );
955
968
if (err ) {
969
+ idr_remove_ext (& tp_c -> handle_idr , handle );
956
970
kfree (ht );
957
971
return err ;
958
972
}
@@ -986,24 +1000,33 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
986
1000
if (TC_U32_HTID (handle ) && TC_U32_HTID (handle ^htid ))
987
1001
return - EINVAL ;
988
1002
handle = htid | TC_U32_NODE (handle );
1003
+ err = idr_alloc_ext (& ht -> handle_idr , NULL , NULL ,
1004
+ handle , handle + 1 ,
1005
+ GFP_KERNEL );
1006
+ if (err )
1007
+ return err ;
989
1008
} else
990
1009
handle = gen_new_kid (ht , htid );
991
1010
992
- if (tb [TCA_U32_SEL ] == NULL )
993
- return - EINVAL ;
1011
+ if (tb [TCA_U32_SEL ] == NULL ) {
1012
+ err = - EINVAL ;
1013
+ goto erridr ;
1014
+ }
994
1015
995
1016
s = nla_data (tb [TCA_U32_SEL ]);
996
1017
997
1018
n = kzalloc (sizeof (* n ) + s -> nkeys * sizeof (struct tc_u32_key ), GFP_KERNEL );
998
- if (n == NULL )
999
- return - ENOBUFS ;
1019
+ if (n == NULL ) {
1020
+ err = - ENOBUFS ;
1021
+ goto erridr ;
1022
+ }
1000
1023
1001
1024
#ifdef CONFIG_CLS_U32_PERF
1002
1025
size = sizeof (struct tc_u32_pcnt ) + s -> nkeys * sizeof (u64 );
1003
1026
n -> pf = __alloc_percpu (size , __alignof__(struct tc_u32_pcnt ));
1004
1027
if (!n -> pf ) {
1005
- kfree ( n ) ;
1006
- return - ENOBUFS ;
1028
+ err = - ENOBUFS ;
1029
+ goto errfree ;
1007
1030
}
1008
1031
#endif
1009
1032
@@ -1066,9 +1089,12 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
1066
1089
errout :
1067
1090
tcf_exts_destroy (& n -> exts );
1068
1091
#ifdef CONFIG_CLS_U32_PERF
1092
+ errfree :
1069
1093
free_percpu (n -> pf );
1070
1094
#endif
1071
1095
kfree (n );
1096
+ erridr :
1097
+ idr_remove_ext (& ht -> handle_idr , handle );
1072
1098
return err ;
1073
1099
}
1074
1100
0 commit comments