Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net_sched: act_mpls: use RCU in tcf_mpls_dump()

Also storing tcf_action into struct tcf_mpls_params
makes sure there is no discrepancy in tcf_mpls_act().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250709090204.797558-8-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
8151684e 799c9417

+11 -11
+1
include/net/tc_act/tc_mpls.h
··· 10 10 struct tcf_mpls_params { 11 11 int tcfm_action; 12 12 u32 tcfm_label; 13 + int action; /* tcf_action */ 13 14 u8 tcfm_tc; 14 15 u8 tcfm_ttl; 15 16 u8 tcfm_bos;
+10 -11
net/sched/act_mpls.c
··· 57 57 struct tcf_mpls *m = to_mpls(a); 58 58 struct tcf_mpls_params *p; 59 59 __be32 new_lse; 60 - int ret, mac_len; 60 + int mac_len; 61 61 62 62 tcf_lastuse_update(&m->tcf_tm); 63 63 bstats_update(this_cpu_ptr(m->common.cpu_bstats), skb); ··· 71 71 } else { 72 72 mac_len = skb_network_offset(skb); 73 73 } 74 - 75 - ret = READ_ONCE(m->tcf_action); 76 74 77 75 p = rcu_dereference_bh(m->mpls_p); 78 76 ··· 120 122 if (skb_at_tc_ingress(skb)) 121 123 skb_pull_rcsum(skb, skb->mac_len); 122 124 123 - return ret; 125 + return p->action; 124 126 125 127 drop: 126 128 qstats_drop_inc(this_cpu_ptr(m->common.cpu_qstats)); ··· 294 296 ACT_MPLS_BOS_NOT_SET); 295 297 p->tcfm_proto = nla_get_be16_default(tb[TCA_MPLS_PROTO], 296 298 htons(ETH_P_MPLS_UC)); 299 + p->action = parm->action; 297 300 298 301 spin_lock_bh(&m->tcf_lock); 299 302 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); ··· 329 330 int bind, int ref) 330 331 { 331 332 unsigned char *b = skb_tail_pointer(skb); 332 - struct tcf_mpls *m = to_mpls(a); 333 - struct tcf_mpls_params *p; 333 + const struct tcf_mpls *m = to_mpls(a); 334 + const struct tcf_mpls_params *p; 334 335 struct tc_mpls opt = { 335 336 .index = m->tcf_index, 336 337 .refcnt = refcount_read(&m->tcf_refcnt) - ref, ··· 338 339 }; 339 340 struct tcf_t t; 340 341 341 - spin_lock_bh(&m->tcf_lock); 342 - opt.action = m->tcf_action; 343 - p = rcu_dereference_protected(m->mpls_p, lockdep_is_held(&m->tcf_lock)); 342 + rcu_read_lock(); 343 + p = rcu_dereference(m->mpls_p); 344 344 opt.m_action = p->tcfm_action; 345 + opt.action = p->action; 345 346 346 347 if (nla_put(skb, TCA_MPLS_PARMS, sizeof(opt), &opt)) 347 348 goto nla_put_failure; ··· 369 370 if (nla_put_64bit(skb, TCA_MPLS_TM, sizeof(t), &t, TCA_MPLS_PAD)) 370 371 goto nla_put_failure; 371 372 372 - spin_unlock_bh(&m->tcf_lock); 373 + rcu_read_unlock(); 373 374 374 375 return skb->len; 375 376 376 377 nla_put_failure: 377 - spin_unlock_bh(&m->tcf_lock); 378 + rcu_read_unlock(); 378 379 nlmsg_trim(skb, b); 379 380 return -EMSGSIZE; 380 381 }