aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2015-08-03 10:21:57 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-03 19:05:56 -0400
commita5c90b29e5ccdb90922b808fd4831cfbaa63006c (patch)
tree79a517306a12e5004f8347195d0ec24486135a2b /net/sched
parent24751e29fe313105c9dd5f9d1f27028c553381f6 (diff)
act_bpf: properly support late binding of bpf action to a classifier
Since the introduction of the BPF action in d23b8ad8ab23 ("tc: add BPF based action"), late binding was not working as expected. I.e. setting the action part for a classifier only via 'bpf index <num>', where <num> is the index of an existing action, is being rejected by the kernel due to other missing parameters. It doesn't make sense to require these parameters such as BPF opcodes etc, as they are not going to be used anyway: in this case, they're just allocated/parsed and then freed again w/o doing anything meaningful. Instead, parse and verify the remaining parameters *after* the test on tcf_hash_check(), when we really know that we're dealing with creation of a new action or replacement of an existing one and where late binding is thus irrelevant. After patch, test case is now working: FOO="1,6 0 0 4294967295," tc actions add action bpf bytecode "$FOO" tc filter add dev foo parent 1: bpf bytecode "$FOO" flowid 1:1 action bpf index 1 tc actions show action bpf action order 0: bpf bytecode '1,6 0 0 4294967295' default-action pipe index 1 ref 2 bind 1 tc filter show dev foo filter protocol all pref 49152 bpf filter protocol all pref 49152 bpf handle 0x1 flowid 1:1 bytecode '1,6 0 0 4294967295' action order 1: bpf bytecode '1,6 0 0 4294967295' default-action pipe index 1 ref 2 bind 1 Late binding of a BPF action can be useful for preloading maps (e.g. before they hit traffic) in case of eBPF programs, or to share a single eBPF action with multiple classifiers. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/act_bpf.c51
1 files changed, 27 insertions, 24 deletions
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index aaae8e83bf18..1b97dabc621a 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -278,7 +278,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
278 struct tc_act_bpf *parm; 278 struct tc_act_bpf *parm;
279 struct tcf_bpf *prog; 279 struct tcf_bpf *prog;
280 bool is_bpf, is_ebpf; 280 bool is_bpf, is_ebpf;
281 int ret; 281 int ret, res = 0;
282 282
283 if (!nla) 283 if (!nla)
284 return -EINVAL; 284 return -EINVAL;
@@ -287,41 +287,43 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
287 if (ret < 0) 287 if (ret < 0)
288 return ret; 288 return ret;
289 289
290 is_bpf = tb[TCA_ACT_BPF_OPS_LEN] && tb[TCA_ACT_BPF_OPS]; 290 if (!tb[TCA_ACT_BPF_PARMS])
291 is_ebpf = tb[TCA_ACT_BPF_FD];
292
293 if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf) ||
294 !tb[TCA_ACT_BPF_PARMS])
295 return -EINVAL; 291 return -EINVAL;
296 292
297 parm = nla_data(tb[TCA_ACT_BPF_PARMS]); 293 parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
298 294
299 memset(&cfg, 0, sizeof(cfg));
300
301 ret = is_bpf ? tcf_bpf_init_from_ops(tb, &cfg) :
302 tcf_bpf_init_from_efd(tb, &cfg);
303 if (ret < 0)
304 return ret;
305
306 if (!tcf_hash_check(parm->index, act, bind)) { 295 if (!tcf_hash_check(parm->index, act, bind)) {
307 ret = tcf_hash_create(parm->index, est, act, 296 ret = tcf_hash_create(parm->index, est, act,
308 sizeof(*prog), bind, false); 297 sizeof(*prog), bind, false);
309 if (ret < 0) 298 if (ret < 0)
310 goto destroy_fp; 299 return ret;
311 300
312 ret = ACT_P_CREATED; 301 res = ACT_P_CREATED;
313 } else { 302 } else {
314 /* Don't override defaults. */ 303 /* Don't override defaults. */
315 if (bind) 304 if (bind)
316 goto destroy_fp; 305 return 0;
317 306
318 tcf_hash_release(act, bind); 307 tcf_hash_release(act, bind);
319 if (!replace) { 308 if (!replace)
320 ret = -EEXIST; 309 return -EEXIST;
321 goto destroy_fp;
322 }
323 } 310 }
324 311
312 is_bpf = tb[TCA_ACT_BPF_OPS_LEN] && tb[TCA_ACT_BPF_OPS];
313 is_ebpf = tb[TCA_ACT_BPF_FD];
314
315 if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) {
316 ret = -EINVAL;
317 goto out;
318 }
319
320 memset(&cfg, 0, sizeof(cfg));
321
322 ret = is_bpf ? tcf_bpf_init_from_ops(tb, &cfg) :
323 tcf_bpf_init_from_efd(tb, &cfg);
324 if (ret < 0)
325 goto out;
326
325 prog = to_bpf(act); 327 prog = to_bpf(act);
326 spin_lock_bh(&prog->tcf_lock); 328 spin_lock_bh(&prog->tcf_lock);
327 329
@@ -341,15 +343,16 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
341 343
342 spin_unlock_bh(&prog->tcf_lock); 344 spin_unlock_bh(&prog->tcf_lock);
343 345
344 if (ret == ACT_P_CREATED) 346 if (res == ACT_P_CREATED)
345 tcf_hash_insert(act); 347 tcf_hash_insert(act);
346 else 348 else
347 tcf_bpf_cfg_cleanup(&old); 349 tcf_bpf_cfg_cleanup(&old);
348 350
349 return ret; 351 return res;
352out:
353 if (res == ACT_P_CREATED)
354 tcf_hash_cleanup(act, est);
350 355
351destroy_fp:
352 tcf_bpf_cfg_cleanup(&cfg);
353 return ret; 356 return ret;
354} 357}
355 358