diff options
author | John Fastabend <john.fastabend@gmail.com> | 2014-09-12 23:05:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-13 12:30:25 -0400 |
commit | 25d8c0d55f241ce2d360df1bea48e23a55836ee6 (patch) | |
tree | c0aca67607e7ce560a4a2cebef5fb6d55adf4112 /net/sched/sch_choke.c | |
parent | 46e5da40aec256155cfedee96dd21a75da941f2c (diff) |
net: rcu-ify tcf_proto
rcu'ify tcf_proto this allows calling tc_classify() without holding
any locks. Updaters are protected by RTNL.
This patch prepares the core net_sched infrastracture for running
the classifier/action chains without holding the qdisc lock however
it does nothing to ensure cls_xxx and act_xxx types also work without
locking. Additional patches are required to address the fall out.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_choke.c')
-rw-r--r-- | net/sched/sch_choke.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index ed30e436128b..74813e6b6ff6 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c | |||
@@ -57,7 +57,7 @@ struct choke_sched_data { | |||
57 | 57 | ||
58 | /* Variables */ | 58 | /* Variables */ |
59 | struct red_vars vars; | 59 | struct red_vars vars; |
60 | struct tcf_proto *filter_list; | 60 | struct tcf_proto __rcu *filter_list; |
61 | struct { | 61 | struct { |
62 | u32 prob_drop; /* Early probability drops */ | 62 | u32 prob_drop; /* Early probability drops */ |
63 | u32 prob_mark; /* Early probability marks */ | 63 | u32 prob_mark; /* Early probability marks */ |
@@ -193,9 +193,11 @@ static bool choke_classify(struct sk_buff *skb, | |||
193 | { | 193 | { |
194 | struct choke_sched_data *q = qdisc_priv(sch); | 194 | struct choke_sched_data *q = qdisc_priv(sch); |
195 | struct tcf_result res; | 195 | struct tcf_result res; |
196 | struct tcf_proto *fl; | ||
196 | int result; | 197 | int result; |
197 | 198 | ||
198 | result = tc_classify(skb, q->filter_list, &res); | 199 | fl = rcu_dereference_bh(q->filter_list); |
200 | result = tc_classify(skb, fl, &res); | ||
199 | if (result >= 0) { | 201 | if (result >= 0) { |
200 | #ifdef CONFIG_NET_CLS_ACT | 202 | #ifdef CONFIG_NET_CLS_ACT |
201 | switch (result) { | 203 | switch (result) { |
@@ -249,7 +251,7 @@ static bool choke_match_random(const struct choke_sched_data *q, | |||
249 | return false; | 251 | return false; |
250 | 252 | ||
251 | oskb = choke_peek_random(q, pidx); | 253 | oskb = choke_peek_random(q, pidx); |
252 | if (q->filter_list) | 254 | if (rcu_access_pointer(q->filter_list)) |
253 | return choke_get_classid(nskb) == choke_get_classid(oskb); | 255 | return choke_get_classid(nskb) == choke_get_classid(oskb); |
254 | 256 | ||
255 | return choke_match_flow(oskb, nskb); | 257 | return choke_match_flow(oskb, nskb); |
@@ -257,11 +259,11 @@ static bool choke_match_random(const struct choke_sched_data *q, | |||
257 | 259 | ||
258 | static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch) | 260 | static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
259 | { | 261 | { |
262 | int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | ||
260 | struct choke_sched_data *q = qdisc_priv(sch); | 263 | struct choke_sched_data *q = qdisc_priv(sch); |
261 | const struct red_parms *p = &q->parms; | 264 | const struct red_parms *p = &q->parms; |
262 | int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | ||
263 | 265 | ||
264 | if (q->filter_list) { | 266 | if (rcu_access_pointer(q->filter_list)) { |
265 | /* If using external classifiers, get result and record it. */ | 267 | /* If using external classifiers, get result and record it. */ |
266 | if (!choke_classify(skb, sch, &ret)) | 268 | if (!choke_classify(skb, sch, &ret)) |
267 | goto other_drop; /* Packet was eaten by filter */ | 269 | goto other_drop; /* Packet was eaten by filter */ |
@@ -554,7 +556,8 @@ static unsigned long choke_bind(struct Qdisc *sch, unsigned long parent, | |||
554 | return 0; | 556 | return 0; |
555 | } | 557 | } |
556 | 558 | ||
557 | static struct tcf_proto **choke_find_tcf(struct Qdisc *sch, unsigned long cl) | 559 | static struct tcf_proto __rcu **choke_find_tcf(struct Qdisc *sch, |
560 | unsigned long cl) | ||
558 | { | 561 | { |
559 | struct choke_sched_data *q = qdisc_priv(sch); | 562 | struct choke_sched_data *q = qdisc_priv(sch); |
560 | 563 | ||