@@ -26,31 +26,35 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
2626 struct tcf_result * res )
2727{
2828 struct tcf_vlan * v = to_vlan (a );
29+ struct tcf_vlan_params * p ;
2930 int action ;
3031 int err ;
3132 u16 tci ;
3233
3334 tcf_lastuse_update (& v -> tcf_tm );
3435 bstats_cpu_update (this_cpu_ptr (v -> common .cpu_bstats ), skb );
3536
36- spin_lock (& v -> tcf_lock );
37- action = v -> tcf_action ;
38-
3937 /* Ensure 'data' points at mac_header prior calling vlan manipulating
4038 * functions.
4139 */
4240 if (skb_at_tc_ingress (skb ))
4341 skb_push_rcsum (skb , skb -> mac_len );
4442
45- switch (v -> tcfv_action ) {
43+ rcu_read_lock ();
44+
45+ action = READ_ONCE (v -> tcf_action );
46+
47+ p = rcu_dereference (v -> vlan_p );
48+
49+ switch (p -> tcfv_action ) {
4650 case TCA_VLAN_ACT_POP :
4751 err = skb_vlan_pop (skb );
4852 if (err )
4953 goto drop ;
5054 break ;
5155 case TCA_VLAN_ACT_PUSH :
52- err = skb_vlan_push (skb , v -> tcfv_push_proto , v -> tcfv_push_vid |
53- (v -> tcfv_push_prio << VLAN_PRIO_SHIFT ));
56+ err = skb_vlan_push (skb , p -> tcfv_push_proto , p -> tcfv_push_vid |
57+ (p -> tcfv_push_prio << VLAN_PRIO_SHIFT ));
5458 if (err )
5559 goto drop ;
5660 break ;
@@ -69,14 +73,14 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
6973 goto drop ;
7074 }
7175 /* replace the vid */
72- tci = (tci & ~VLAN_VID_MASK ) | v -> tcfv_push_vid ;
76+ tci = (tci & ~VLAN_VID_MASK ) | p -> tcfv_push_vid ;
7377 /* replace prio bits, if tcfv_push_prio specified */
74- if (v -> tcfv_push_prio ) {
78+ if (p -> tcfv_push_prio ) {
7579 tci &= ~VLAN_PRIO_MASK ;
76- tci |= v -> tcfv_push_prio << VLAN_PRIO_SHIFT ;
80+ tci |= p -> tcfv_push_prio << VLAN_PRIO_SHIFT ;
7781 }
7882 /* put updated tci as hwaccel tag */
79- __vlan_hwaccel_put_tag (skb , v -> tcfv_push_proto , tci );
83+ __vlan_hwaccel_put_tag (skb , p -> tcfv_push_proto , tci );
8084 break ;
8185 default :
8286 BUG ();
@@ -89,10 +93,10 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
8993 qstats_drop_inc (this_cpu_ptr (v -> common .cpu_qstats ));
9094
9195unlock :
96+ rcu_read_unlock ();
9297 if (skb_at_tc_ingress (skb ))
9398 skb_pull_rcsum (skb , skb -> mac_len );
9499
95- spin_unlock (& v -> tcf_lock );
96100 return action ;
97101}
98102
@@ -109,6 +113,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
109113{
110114 struct tc_action_net * tn = net_generic (net , vlan_net_id );
111115 struct nlattr * tb [TCA_VLAN_MAX + 1 ];
116+ struct tcf_vlan_params * p , * p_old ;
112117 struct tc_vlan * parm ;
113118 struct tcf_vlan * v ;
114119 int action ;
@@ -187,46 +192,67 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
187192
188193 v = to_vlan (* a );
189194
190- spin_lock_bh (& v -> tcf_lock );
191-
192- v -> tcfv_action = action ;
193- v -> tcfv_push_vid = push_vid ;
194- v -> tcfv_push_prio = push_prio ;
195- v -> tcfv_push_proto = push_proto ;
195+ ASSERT_RTNL ();
196+ p = kzalloc (sizeof (* p ), GFP_KERNEL );
197+ if (!p ) {
198+ if (ovr )
199+ tcf_idr_release (* a , bind );
200+ return - ENOMEM ;
201+ }
196202
197203 v -> tcf_action = parm -> action ;
198204
199- spin_unlock_bh (& v -> tcf_lock );
205+ p_old = rtnl_dereference (v -> vlan_p );
206+
207+ p -> tcfv_action = action ;
208+ p -> tcfv_push_vid = push_vid ;
209+ p -> tcfv_push_prio = push_prio ;
210+ p -> tcfv_push_proto = push_proto ;
211+
212+ rcu_assign_pointer (v -> vlan_p , p );
213+
214+ if (p_old )
215+ kfree_rcu (p_old , rcu );
200216
201217 if (ret == ACT_P_CREATED )
202218 tcf_idr_insert (tn , * a );
203219 return ret ;
204220}
205221
222+ static void tcf_vlan_cleanup (struct tc_action * a , int bind )
223+ {
224+ struct tcf_vlan * v = to_vlan (a );
225+ struct tcf_vlan_params * p ;
226+
227+ p = rcu_dereference_protected (v -> vlan_p , 1 );
228+ kfree_rcu (p , rcu );
229+ }
230+
206231static int tcf_vlan_dump (struct sk_buff * skb , struct tc_action * a ,
207232 int bind , int ref )
208233{
209234 unsigned char * b = skb_tail_pointer (skb );
210235 struct tcf_vlan * v = to_vlan (a );
236+ struct tcf_vlan_params * p = rtnl_dereference (v -> vlan_p );
211237 struct tc_vlan opt = {
212238 .index = v -> tcf_index ,
213239 .refcnt = v -> tcf_refcnt - ref ,
214240 .bindcnt = v -> tcf_bindcnt - bind ,
215241 .action = v -> tcf_action ,
216- .v_action = v -> tcfv_action ,
242+ .v_action = p -> tcfv_action ,
217243 };
218244 struct tcf_t t ;
219245
220246 if (nla_put (skb , TCA_VLAN_PARMS , sizeof (opt ), & opt ))
221247 goto nla_put_failure ;
222248
223- if ((v -> tcfv_action == TCA_VLAN_ACT_PUSH ||
224- v -> tcfv_action == TCA_VLAN_ACT_MODIFY ) &&
225- (nla_put_u16 (skb , TCA_VLAN_PUSH_VLAN_ID , v -> tcfv_push_vid ) ||
249+ if ((p -> tcfv_action == TCA_VLAN_ACT_PUSH ||
250+ p -> tcfv_action == TCA_VLAN_ACT_MODIFY ) &&
251+ (nla_put_u16 (skb , TCA_VLAN_PUSH_VLAN_ID , p -> tcfv_push_vid ) ||
226252 nla_put_be16 (skb , TCA_VLAN_PUSH_VLAN_PROTOCOL ,
227- v -> tcfv_push_proto ) ||
253+ p -> tcfv_push_proto ) ||
228254 (nla_put_u8 (skb , TCA_VLAN_PUSH_VLAN_PRIORITY ,
229- v -> tcfv_push_prio ))))
255+ p -> tcfv_push_prio ))))
230256 goto nla_put_failure ;
231257
232258 tcf_tm_dump (& t , & v -> tcf_tm );
@@ -262,6 +288,7 @@ static struct tc_action_ops act_vlan_ops = {
262288 .act = tcf_vlan ,
263289 .dump = tcf_vlan_dump ,
264290 .init = tcf_vlan_init ,
291+ .cleanup = tcf_vlan_cleanup ,
265292 .walk = tcf_vlan_walker ,
266293 .lookup = tcf_vlan_search ,
267294 .size = sizeof (struct tcf_vlan ),
0 commit comments