Skip to content

Commit 04d7552

Browse files
jopamogregkh
authored andcommitted
net/sched: act_gate: snapshot parameters with RCU on replace
commit 62413a9 upstream. The gate action can be replaced while the hrtimer callback or dump path is walking the schedule list. Convert the parameters to an RCU-protected snapshot and swap updates under tcf_lock, freeing the previous snapshot via call_rcu(). When REPLACE omits the entry list, preserve the existing schedule so the effective state is unchanged. Fixes: a51c328 ("net: qos: introduce a gate control flow action") Cc: stable@vger.kernel.org Signed-off-by: Paul Moses <p@1g4.org> Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Reviewed-by: Victor Nogueira <victor@mojatatu.com> Link: https://patch.msgid.link/20260223150512.2251594-2-p@1g4.org Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 93ea7e1 commit 04d7552

2 files changed

Lines changed: 212 additions & 86 deletions

File tree

include/net/tc_act/tc_gate.h

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,15 @@ struct tcf_gate_params {
3232
s32 tcfg_clockid;
3333
size_t num_entries;
3434
struct list_head entries;
35+
struct rcu_head rcu;
3536
};
3637

3738
#define GATE_ACT_GATE_OPEN BIT(0)
3839
#define GATE_ACT_PENDING BIT(1)
3940

4041
struct tcf_gate {
4142
struct tc_action common;
42-
struct tcf_gate_params param;
43+
struct tcf_gate_params __rcu *param;
4344
u8 current_gate_status;
4445
ktime_t current_close_time;
4546
u32 current_entry_octets;
@@ -51,47 +52,65 @@ struct tcf_gate {
5152

5253
#define to_gate(a) ((struct tcf_gate *)a)
5354

55+
static inline struct tcf_gate_params *tcf_gate_params_locked(const struct tc_action *a)
56+
{
57+
struct tcf_gate *gact = to_gate(a);
58+
59+
return rcu_dereference_protected(gact->param,
60+
lockdep_is_held(&gact->tcf_lock));
61+
}
62+
5463
static inline s32 tcf_gate_prio(const struct tc_action *a)
5564
{
65+
struct tcf_gate_params *p;
5666
s32 tcfg_prio;
5767

58-
tcfg_prio = to_gate(a)->param.tcfg_priority;
68+
p = tcf_gate_params_locked(a);
69+
tcfg_prio = p->tcfg_priority;
5970

6071
return tcfg_prio;
6172
}
6273

6374
static inline u64 tcf_gate_basetime(const struct tc_action *a)
6475
{
76+
struct tcf_gate_params *p;
6577
u64 tcfg_basetime;
6678

67-
tcfg_basetime = to_gate(a)->param.tcfg_basetime;
79+
p = tcf_gate_params_locked(a);
80+
tcfg_basetime = p->tcfg_basetime;
6881

6982
return tcfg_basetime;
7083
}
7184

7285
static inline u64 tcf_gate_cycletime(const struct tc_action *a)
7386
{
87+
struct tcf_gate_params *p;
7488
u64 tcfg_cycletime;
7589

76-
tcfg_cycletime = to_gate(a)->param.tcfg_cycletime;
90+
p = tcf_gate_params_locked(a);
91+
tcfg_cycletime = p->tcfg_cycletime;
7792

7893
return tcfg_cycletime;
7994
}
8095

8196
static inline u64 tcf_gate_cycletimeext(const struct tc_action *a)
8297
{
98+
struct tcf_gate_params *p;
8399
u64 tcfg_cycletimeext;
84100

85-
tcfg_cycletimeext = to_gate(a)->param.tcfg_cycletime_ext;
101+
p = tcf_gate_params_locked(a);
102+
tcfg_cycletimeext = p->tcfg_cycletime_ext;
86103

87104
return tcfg_cycletimeext;
88105
}
89106

90107
static inline u32 tcf_gate_num_entries(const struct tc_action *a)
91108
{
109+
struct tcf_gate_params *p;
92110
u32 num_entries;
93111

94-
num_entries = to_gate(a)->param.num_entries;
112+
p = tcf_gate_params_locked(a);
113+
num_entries = p->num_entries;
95114

96115
return num_entries;
97116
}
@@ -105,7 +124,7 @@ static inline struct action_gate_entry
105124
u32 num_entries;
106125
int i = 0;
107126

108-
p = &to_gate(a)->param;
127+
p = tcf_gate_params_locked(a);
109128
num_entries = p->num_entries;
110129

111130
list_for_each_entry(entry, &p->entries, list)

0 commit comments

Comments
 (0)