@@ -55,10 +55,12 @@ struct tc_u_knode {
55
55
struct tcf_result res ;
56
56
struct tc_u_hnode * ht_down ;
57
57
#ifdef CONFIG_CLS_U32_PERF
58
- struct tc_u32_pcnt * pf ;
58
+ struct tc_u32_pcnt __percpu * pf ;
59
59
#endif
60
60
#ifdef CONFIG_CLS_U32_MARK
61
- struct tc_u32_mark mark ;
61
+ u32 val ;
62
+ u32 mask ;
63
+ u32 __percpu * pcpu_success ;
62
64
#endif
63
65
struct tc_u32_sel sel ;
64
66
};
@@ -115,16 +117,16 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct
115
117
struct tc_u32_key * key = n -> sel .keys ;
116
118
117
119
#ifdef CONFIG_CLS_U32_PERF
118
- n -> pf -> rcnt += 1 ;
120
+ __this_cpu_inc ( n -> pf -> rcnt ) ;
119
121
j = 0 ;
120
122
#endif
121
123
122
124
#ifdef CONFIG_CLS_U32_MARK
123
- if ((skb -> mark & n -> mark . mask ) != n -> mark . val ) {
125
+ if ((skb -> mark & n -> mask ) != n -> val ) {
124
126
n = n -> next ;
125
127
goto next_knode ;
126
128
} else {
127
- n -> mark . success ++ ;
129
+ __this_cpu_inc ( * n -> pcpu_success ) ;
128
130
}
129
131
#endif
130
132
@@ -143,7 +145,7 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct
143
145
goto next_knode ;
144
146
}
145
147
#ifdef CONFIG_CLS_U32_PERF
146
- n -> pf -> kcnts [j ] += 1 ;
148
+ __this_cpu_inc ( n -> pf -> kcnts [j ]) ;
147
149
j ++ ;
148
150
#endif
149
151
}
@@ -159,7 +161,7 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct
159
161
}
160
162
#endif
161
163
#ifdef CONFIG_CLS_U32_PERF
162
- n -> pf -> rhit += 1 ;
164
+ __this_cpu_inc ( n -> pf -> rhit ) ;
163
165
#endif
164
166
r = tcf_exts_exec (skb , & n -> exts , res );
165
167
if (r < 0 ) {
@@ -342,7 +344,7 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n)
342
344
if (n -> ht_down )
343
345
n -> ht_down -> refcnt -- ;
344
346
#ifdef CONFIG_CLS_U32_PERF
345
- kfree (n -> pf );
347
+ free_percpu (n -> pf );
346
348
#endif
347
349
kfree (n );
348
350
return 0 ;
@@ -564,6 +566,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
564
566
struct nlattr * tb [TCA_U32_MAX + 1 ];
565
567
u32 htid ;
566
568
int err ;
569
+ #ifdef CONFIG_CLS_U32_PERF
570
+ size_t size ;
571
+ #endif
567
572
568
573
if (opt == NULL )
569
574
return handle ? - EINVAL : 0 ;
@@ -642,8 +647,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
642
647
return - ENOBUFS ;
643
648
644
649
#ifdef CONFIG_CLS_U32_PERF
645
- n -> pf = kzalloc (sizeof (struct tc_u32_pcnt ) + s -> nkeys * sizeof (u64 ), GFP_KERNEL );
646
- if (n -> pf == NULL ) {
650
+ size = sizeof (struct tc_u32_pcnt ) + s -> nkeys * sizeof (u64 );
651
+ n -> pf = __alloc_percpu (size , __alignof__(struct tc_u32_pcnt ));
652
+ if (!n -> pf ) {
647
653
kfree (n );
648
654
return - ENOBUFS ;
649
655
}
@@ -656,12 +662,14 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
656
662
tcf_exts_init (& n -> exts , TCA_U32_ACT , TCA_U32_POLICE );
657
663
658
664
#ifdef CONFIG_CLS_U32_MARK
665
+ n -> pcpu_success = alloc_percpu (u32 );
666
+
659
667
if (tb [TCA_U32_MARK ]) {
660
668
struct tc_u32_mark * mark ;
661
669
662
670
mark = nla_data (tb [TCA_U32_MARK ]);
663
- memcpy ( & n -> mark , mark , sizeof ( struct tc_u32_mark )) ;
664
- n -> mark . success = 0 ;
671
+ n -> val = mark -> val ;
672
+ n -> mask = mark -> mask ;
665
673
}
666
674
#endif
667
675
@@ -745,6 +753,11 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
745
753
if (nla_put_u32 (skb , TCA_U32_DIVISOR , divisor ))
746
754
goto nla_put_failure ;
747
755
} else {
756
+ #ifdef CONFIG_CLS_U32_PERF
757
+ struct tc_u32_pcnt * gpf ;
758
+ #endif
759
+ int cpu ;
760
+
748
761
if (nla_put (skb , TCA_U32_SEL ,
749
762
sizeof (n -> sel ) + n -> sel .nkeys * sizeof (struct tc_u32_key ),
750
763
& n -> sel ))
@@ -762,9 +775,20 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
762
775
goto nla_put_failure ;
763
776
764
777
#ifdef CONFIG_CLS_U32_MARK
765
- if ((n -> mark .val || n -> mark .mask ) &&
766
- nla_put (skb , TCA_U32_MARK , sizeof (n -> mark ), & n -> mark ))
767
- goto nla_put_failure ;
778
+ if ((n -> val || n -> mask )) {
779
+ struct tc_u32_mark mark = {.val = n -> val ,
780
+ .mask = n -> mask ,
781
+ .success = 0 };
782
+
783
+ for_each_possible_cpu (cpu ) {
784
+ __u32 cnt = * per_cpu_ptr (n -> pcpu_success , cpu );
785
+
786
+ mark .success += cnt ;
787
+ }
788
+
789
+ if (nla_put (skb , TCA_U32_MARK , sizeof (mark ), & mark ))
790
+ goto nla_put_failure ;
791
+ }
768
792
#endif
769
793
770
794
if (tcf_exts_dump (skb , & n -> exts ) < 0 )
@@ -779,10 +803,29 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
779
803
}
780
804
#endif
781
805
#ifdef CONFIG_CLS_U32_PERF
806
+ gpf = kzalloc (sizeof (struct tc_u32_pcnt ) +
807
+ n -> sel .nkeys * sizeof (u64 ),
808
+ GFP_KERNEL );
809
+ if (!gpf )
810
+ goto nla_put_failure ;
811
+
812
+ for_each_possible_cpu (cpu ) {
813
+ int i ;
814
+ struct tc_u32_pcnt * pf = per_cpu_ptr (n -> pf , cpu );
815
+
816
+ gpf -> rcnt += pf -> rcnt ;
817
+ gpf -> rhit += pf -> rhit ;
818
+ for (i = 0 ; i < n -> sel .nkeys ; i ++ )
819
+ gpf -> kcnts [i ] += pf -> kcnts [i ];
820
+ }
821
+
782
822
if (nla_put (skb , TCA_U32_PCNT ,
783
823
sizeof (struct tc_u32_pcnt ) + n -> sel .nkeys * sizeof (u64 ),
784
- n -> pf ))
824
+ gpf )) {
825
+ kfree (gpf );
785
826
goto nla_put_failure ;
827
+ }
828
+ kfree (gpf );
786
829
#endif
787
830
}
788
831
0 commit comments