@@ -49,6 +49,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
49
49
int bind )
50
50
{
51
51
struct tc_action_net * tn = net_generic (net , csum_net_id );
52
+ struct tcf_csum_params * params_old , * params_new ;
52
53
struct nlattr * tb [TCA_CSUM_MAX + 1 ];
53
54
struct tc_csum * parm ;
54
55
struct tcf_csum * p ;
@@ -80,10 +81,21 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
80
81
}
81
82
82
83
p = to_tcf_csum (* a );
83
- spin_lock_bh (& p -> tcf_lock );
84
- p -> tcf_action = parm -> action ;
85
- p -> update_flags = parm -> update_flags ;
86
- spin_unlock_bh (& p -> tcf_lock );
84
+ ASSERT_RTNL ();
85
+
86
+ params_new = kzalloc (sizeof (* params_new ), GFP_KERNEL );
87
+ if (unlikely (!params_new )) {
88
+ if (ret == ACT_P_CREATED )
89
+ tcf_idr_release (* a , bind );
90
+ return - ENOMEM ;
91
+ }
92
+ params_old = rtnl_dereference (p -> params );
93
+
94
+ params_new -> action = parm -> action ;
95
+ params_new -> update_flags = parm -> update_flags ;
96
+ rcu_assign_pointer (p -> params , params_new );
97
+ if (params_old )
98
+ kfree_rcu (params_old , rcu );
87
99
88
100
if (ret == ACT_P_CREATED )
89
101
tcf_idr_insert (tn , * a );
@@ -539,19 +551,21 @@ static int tcf_csum(struct sk_buff *skb, const struct tc_action *a,
539
551
struct tcf_result * res )
540
552
{
541
553
struct tcf_csum * p = to_tcf_csum (a );
542
- int action ;
554
+ struct tcf_csum_params * params ;
543
555
u32 update_flags ;
556
+ int action ;
557
+
558
+ rcu_read_lock ();
559
+ params = rcu_dereference (p -> params );
544
560
545
561
tcf_lastuse_update (& p -> tcf_tm );
546
562
bstats_cpu_update (this_cpu_ptr (p -> common .cpu_bstats ), skb );
547
- spin_lock (& p -> tcf_lock );
548
- action = p -> tcf_action ;
549
- update_flags = p -> update_flags ;
550
- spin_unlock (& p -> tcf_lock );
551
563
564
+ action = params -> action ;
552
565
if (unlikely (action == TC_ACT_SHOT ))
553
- goto drop ;
566
+ goto drop_stats ;
554
567
568
+ update_flags = params -> update_flags ;
555
569
switch (tc_skb_protocol (skb )) {
556
570
case cpu_to_be16 (ETH_P_IP ):
557
571
if (!tcf_csum_ipv4 (skb , update_flags ))
@@ -563,27 +577,35 @@ static int tcf_csum(struct sk_buff *skb, const struct tc_action *a,
563
577
break ;
564
578
}
565
579
580
+ unlock :
581
+ rcu_read_unlock ();
566
582
return action ;
567
583
568
584
drop :
585
+ action = TC_ACT_SHOT ;
586
+
587
+ drop_stats :
569
588
qstats_drop_inc (this_cpu_ptr (p -> common .cpu_qstats ));
570
- return TC_ACT_SHOT ;
589
+ goto unlock ;
571
590
}
572
591
573
592
static int tcf_csum_dump (struct sk_buff * skb , struct tc_action * a , int bind ,
574
593
int ref )
575
594
{
576
595
unsigned char * b = skb_tail_pointer (skb );
577
596
struct tcf_csum * p = to_tcf_csum (a );
597
+ struct tcf_csum_params * params ;
578
598
struct tc_csum opt = {
579
- .update_flags = p -> update_flags ,
580
599
.index = p -> tcf_index ,
581
- .action = p -> tcf_action ,
582
600
.refcnt = p -> tcf_refcnt - ref ,
583
601
.bindcnt = p -> tcf_bindcnt - bind ,
584
602
};
585
603
struct tcf_t t ;
586
604
605
+ params = rtnl_dereference (p -> params );
606
+ opt .action = params -> action ;
607
+ opt .update_flags = params -> update_flags ;
608
+
587
609
if (nla_put (skb , TCA_CSUM_PARMS , sizeof (opt ), & opt ))
588
610
goto nla_put_failure ;
589
611
@@ -598,6 +620,15 @@ static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind,
598
620
return -1 ;
599
621
}
600
622
623
+ static void tcf_csum_cleanup (struct tc_action * a )
624
+ {
625
+ struct tcf_csum * p = to_tcf_csum (a );
626
+ struct tcf_csum_params * params ;
627
+
628
+ params = rcu_dereference_protected (p -> params , 1 );
629
+ kfree_rcu (params , rcu );
630
+ }
631
+
601
632
static int tcf_csum_walker (struct net * net , struct sk_buff * skb ,
602
633
struct netlink_callback * cb , int type ,
603
634
const struct tc_action_ops * ops )
@@ -621,6 +652,7 @@ static struct tc_action_ops act_csum_ops = {
621
652
.act = tcf_csum ,
622
653
.dump = tcf_csum_dump ,
623
654
.init = tcf_csum_init ,
655
+ .cleanup = tcf_csum_cleanup ,
624
656
.walk = tcf_csum_walker ,
625
657
.lookup = tcf_csum_search ,
626
658
.size = sizeof (struct tcf_csum ),
0 commit comments