Skip to content

Commit 7fd4b28

Browse files
Paolo Abenidavem330
authored andcommitted
tc/act: remove unneeded RCU lock in action callback
Each lockless action currently does its own RCU locking in ->act(). This allows using plain RCU accessor, even if the context is really RCU BH. This change drops the per action RCU lock, replace the accessors with the _bh variant, cleans up a bit the surrounding code and documents the RCU status in the relevant header. No functional nor performance change is intended. The goal of this patch is clarifying that the RCU critical section used by the tc actions extends up to the classifier's caller. v1 -> v2: - preserve rcu lock in act_bpf: it's needed by eBPF helpers, as pointed out by Daniel v3 -> v4: - fixed some typos in the commit message (JiriP) Signed-off-by: Paolo Abeni <[email protected]> Acked-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 802bfb1 commit 7fd4b28

File tree

10 files changed

+29
-56
lines changed

10 files changed

+29
-56
lines changed

include/net/act_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ struct tc_action_ops {
8585
size_t size;
8686
struct module *owner;
8787
int (*act)(struct sk_buff *, const struct tc_action *,
88-
struct tcf_result *);
88+
struct tcf_result *); /* called under RCU BH lock*/
8989
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
9090
void (*cleanup)(struct tc_action *);
9191
int (*lookup)(struct net *net, struct tc_action **a, u32 index,

include/net/sch_generic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ struct tcf_proto {
285285
/* Fast access part */
286286
struct tcf_proto __rcu *next;
287287
void __rcu *root;
288+
289+
/* called under RCU BH lock*/
288290
int (*classify)(struct sk_buff *,
289291
const struct tcf_proto *,
290292
struct tcf_result *);

net/sched/act_csum.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -561,15 +561,14 @@ static int tcf_csum(struct sk_buff *skb, const struct tc_action *a,
561561
u32 update_flags;
562562
int action;
563563

564-
rcu_read_lock();
565-
params = rcu_dereference(p->params);
564+
params = rcu_dereference_bh(p->params);
566565

567566
tcf_lastuse_update(&p->tcf_tm);
568567
bstats_cpu_update(this_cpu_ptr(p->common.cpu_bstats), skb);
569568

570569
action = READ_ONCE(p->tcf_action);
571570
if (unlikely(action == TC_ACT_SHOT))
572-
goto drop_stats;
571+
goto drop;
573572

574573
update_flags = params->update_flags;
575574
switch (tc_skb_protocol(skb)) {
@@ -583,16 +582,11 @@ static int tcf_csum(struct sk_buff *skb, const struct tc_action *a,
583582
break;
584583
}
585584

586-
unlock:
587-
rcu_read_unlock();
588585
return action;
589586

590587
drop:
591-
action = TC_ACT_SHOT;
592-
593-
drop_stats:
594588
qstats_drop_inc(this_cpu_ptr(p->common.cpu_qstats));
595-
goto unlock;
589+
return TC_ACT_SHOT;
596590
}
597591

598592
static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind,

net/sched/act_ife.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,14 +820,11 @@ static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
820820
struct tcf_ife_params *p;
821821
int ret;
822822

823-
rcu_read_lock();
824-
p = rcu_dereference(ife->params);
823+
p = rcu_dereference_bh(ife->params);
825824
if (p->flags & IFE_ENCODE) {
826825
ret = tcf_ife_encode(skb, a, res, p);
827-
rcu_read_unlock();
828826
return ret;
829827
}
830-
rcu_read_unlock();
831828

832829
return tcf_ife_decode(skb, a, res);
833830
}

net/sched/act_mirred.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,10 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
181181
tcf_lastuse_update(&m->tcf_tm);
182182
bstats_cpu_update(this_cpu_ptr(m->common.cpu_bstats), skb);
183183

184-
rcu_read_lock();
185184
m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
186185
m_eaction = READ_ONCE(m->tcfm_eaction);
187186
retval = READ_ONCE(m->tcf_action);
188-
dev = rcu_dereference(m->tcfm_dev);
187+
dev = rcu_dereference_bh(m->tcfm_dev);
189188
if (unlikely(!dev)) {
190189
pr_notice_once("tc mirred: target device is gone\n");
191190
goto out;
@@ -236,7 +235,6 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
236235
if (tcf_mirred_is_act_redirect(m_eaction))
237236
retval = TC_ACT_SHOT;
238237
}
239-
rcu_read_unlock();
240238

241239
return retval;
242240
}

net/sched/act_sample.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,7 @@ static int tcf_sample_act(struct sk_buff *skb, const struct tc_action *a,
140140
bstats_cpu_update(this_cpu_ptr(s->common.cpu_bstats), skb);
141141
retval = READ_ONCE(s->tcf_action);
142142

143-
rcu_read_lock();
144-
psample_group = rcu_dereference(s->psample_group);
143+
psample_group = rcu_dereference_bh(s->psample_group);
145144

146145
/* randomly sample packets according to rate */
147146
if (psample_group && (prandom_u32() % s->rate == 0)) {
@@ -165,7 +164,6 @@ static int tcf_sample_act(struct sk_buff *skb, const struct tc_action *a,
165164
skb_pull(skb, skb->mac_len);
166165
}
167166

168-
rcu_read_unlock();
169167
return retval;
170168
}
171169

net/sched/act_skbedit.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
4343
tcf_lastuse_update(&d->tcf_tm);
4444
bstats_cpu_update(this_cpu_ptr(d->common.cpu_bstats), skb);
4545

46-
rcu_read_lock();
47-
params = rcu_dereference(d->params);
46+
params = rcu_dereference_bh(d->params);
4847
action = READ_ONCE(d->tcf_action);
4948

5049
if (params->flags & SKBEDIT_F_PRIORITY)
@@ -77,14 +76,11 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
7776
}
7877
if (params->flags & SKBEDIT_F_PTYPE)
7978
skb->pkt_type = params->ptype;
80-
81-
unlock:
82-
rcu_read_unlock();
8379
return action;
80+
8481
err:
8582
qstats_drop_inc(this_cpu_ptr(d->common.cpu_qstats));
86-
action = TC_ACT_SHOT;
87-
goto unlock;
83+
return TC_ACT_SHOT;
8884
}
8985

9086
static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {

net/sched/act_skbmod.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,28 +41,21 @@ static int tcf_skbmod_run(struct sk_buff *skb, const struct tc_action *a,
4141
* then MAX_EDIT_LEN needs to change appropriately
4242
*/
4343
err = skb_ensure_writable(skb, MAX_EDIT_LEN);
44-
if (unlikely(err)) { /* best policy is to drop on the floor */
45-
qstats_overlimit_inc(this_cpu_ptr(d->common.cpu_qstats));
46-
return TC_ACT_SHOT;
47-
}
44+
if (unlikely(err)) /* best policy is to drop on the floor */
45+
goto drop;
4846

49-
rcu_read_lock();
5047
action = READ_ONCE(d->tcf_action);
51-
if (unlikely(action == TC_ACT_SHOT)) {
52-
qstats_overlimit_inc(this_cpu_ptr(d->common.cpu_qstats));
53-
rcu_read_unlock();
54-
return action;
55-
}
48+
if (unlikely(action == TC_ACT_SHOT))
49+
goto drop;
5650

57-
p = rcu_dereference(d->skbmod_p);
51+
p = rcu_dereference_bh(d->skbmod_p);
5852
flags = p->flags;
5953
if (flags & SKBMOD_F_DMAC)
6054
ether_addr_copy(eth_hdr(skb)->h_dest, p->eth_dst);
6155
if (flags & SKBMOD_F_SMAC)
6256
ether_addr_copy(eth_hdr(skb)->h_source, p->eth_src);
6357
if (flags & SKBMOD_F_ETYPE)
6458
eth_hdr(skb)->h_proto = p->eth_type;
65-
rcu_read_unlock();
6659

6760
if (flags & SKBMOD_F_SWAPMAC) {
6861
u16 tmpaddr[ETH_ALEN / 2]; /* ether_addr_copy() requirement */
@@ -73,6 +66,10 @@ static int tcf_skbmod_run(struct sk_buff *skb, const struct tc_action *a,
7366
}
7467

7568
return action;
69+
70+
drop:
71+
qstats_overlimit_inc(this_cpu_ptr(d->common.cpu_qstats));
72+
return TC_ACT_SHOT;
7673
}
7774

7875
static const struct nla_policy skbmod_policy[TCA_SKBMOD_MAX + 1] = {

net/sched/act_tunnel_key.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ static int tunnel_key_act(struct sk_buff *skb, const struct tc_action *a,
3131
struct tcf_tunnel_key_params *params;
3232
int action;
3333

34-
rcu_read_lock();
35-
36-
params = rcu_dereference(t->params);
34+
params = rcu_dereference_bh(t->params);
3735

3836
tcf_lastuse_update(&t->tcf_tm);
3937
bstats_cpu_update(this_cpu_ptr(t->common.cpu_bstats), skb);
@@ -53,8 +51,6 @@ static int tunnel_key_act(struct sk_buff *skb, const struct tc_action *a,
5351
break;
5452
}
5553

56-
rcu_read_unlock();
57-
5854
return action;
5955
}
6056

net/sched/act_vlan.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,9 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
4040
if (skb_at_tc_ingress(skb))
4141
skb_push_rcsum(skb, skb->mac_len);
4242

43-
rcu_read_lock();
44-
4543
action = READ_ONCE(v->tcf_action);
4644

47-
p = rcu_dereference(v->vlan_p);
45+
p = rcu_dereference_bh(v->vlan_p);
4846

4947
switch (p->tcfv_action) {
5048
case TCA_VLAN_ACT_POP:
@@ -61,7 +59,7 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
6159
case TCA_VLAN_ACT_MODIFY:
6260
/* No-op if no vlan tag (either hw-accel or in-payload) */
6361
if (!skb_vlan_tagged(skb))
64-
goto unlock;
62+
goto out;
6563
/* extract existing tag (and guarantee no hw-accel tag) */
6664
if (skb_vlan_tag_present(skb)) {
6765
tci = skb_vlan_tag_get(skb);
@@ -86,18 +84,15 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
8684
BUG();
8785
}
8886

89-
goto unlock;
90-
91-
drop:
92-
action = TC_ACT_SHOT;
93-
qstats_drop_inc(this_cpu_ptr(v->common.cpu_qstats));
94-
95-
unlock:
96-
rcu_read_unlock();
87+
out:
9788
if (skb_at_tc_ingress(skb))
9889
skb_pull_rcsum(skb, skb->mac_len);
9990

10091
return action;
92+
93+
drop:
94+
qstats_drop_inc(this_cpu_ptr(v->common.cpu_qstats));
95+
return TC_ACT_SHOT;
10196
}
10297

10398
static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {

0 commit comments

Comments
 (0)