cls_bpf.c 16.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Berkeley Packet Filter based traffic classifier
 *
 * Might be used to classify traffic through flexible, user-defined and
 * possibly JIT-ed BPF filters for traffic control as an alternative to
 * ematches.
 *
 * (C) 2013 Daniel Borkmann <dborkman@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/filter.h>
19
#include <linux/bpf.h>
20
#include <linux/idr.h>
21

22 23 24 25 26 27 28 29
#include <net/rtnetlink.h>
#include <net/pkt_cls.h>
#include <net/sock.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>");
MODULE_DESCRIPTION("TC BPF based classifier");

30
#define CLS_BPF_NAME_LEN	256
31
#define CLS_BPF_SUPPORTED_GEN_FLAGS		\
32
	(TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW)
33

34 35
struct cls_bpf_head {
	struct list_head plist;
36
	struct idr handle_idr;
J
John Fastabend 已提交
37
	struct rcu_head rcu;
38 39 40
};

struct cls_bpf_prog {
41
	struct bpf_prog *filter;
42
	struct list_head link;
43
	struct tcf_result res;
44
	bool exts_integrated;
45
	u32 gen_flags;
46
	unsigned int in_hw_count;
47
	struct tcf_exts exts;
48
	u32 handle;
49
	u16 bpf_num_ops;
50 51
	struct sock_filter *bpf_ops;
	const char *bpf_name;
J
John Fastabend 已提交
52
	struct tcf_proto *tp;
C
Cong Wang 已提交
53
	struct rcu_work rwork;
54 55 56 57
};

static const struct nla_policy bpf_policy[TCA_BPF_MAX + 1] = {
	[TCA_BPF_CLASSID]	= { .type = NLA_U32 },
58
	[TCA_BPF_FLAGS]		= { .type = NLA_U32 },
59
	[TCA_BPF_FLAGS_GEN]	= { .type = NLA_U32 },
60
	[TCA_BPF_FD]		= { .type = NLA_U32 },
J
Jamal Hadi Salim 已提交
61 62
	[TCA_BPF_NAME]		= { .type = NLA_NUL_STRING,
				    .len = CLS_BPF_NAME_LEN },
63 64 65 66 67
	[TCA_BPF_OPS_LEN]	= { .type = NLA_U16 },
	[TCA_BPF_OPS]		= { .type = NLA_BINARY,
				    .len = sizeof(struct sock_filter) * BPF_MAXINSNS },
};

68 69 70 71 72 73
static int cls_bpf_exec_opcode(int code)
{
	switch (code) {
	case TC_ACT_OK:
	case TC_ACT_SHOT:
	case TC_ACT_STOLEN:
74
	case TC_ACT_TRAP:
75
	case TC_ACT_REDIRECT:
76 77 78 79 80 81 82
	case TC_ACT_UNSPEC:
		return code;
	default:
		return TC_ACT_UNSPEC;
	}
}

83 84 85
static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
			    struct tcf_result *res)
{
86
	struct cls_bpf_head *head = rcu_dereference_bh(tp->root);
87
	bool at_ingress = skb_at_tc_ingress(skb);
88
	struct cls_bpf_prog *prog;
89
	int ret = -1;
90

91 92
	/* Needed here for accessing maps. */
	rcu_read_lock();
J
John Fastabend 已提交
93
	list_for_each_entry_rcu(prog, &head->plist, link) {
94 95
		int filter_res;

96 97
		qdisc_skb_cb(skb)->tc_classid = prog->res.classid;

98 99 100
		if (tc_skip_sw(prog->gen_flags)) {
			filter_res = prog->exts_integrated ? TC_ACT_UNSPEC : 0;
		} else if (at_ingress) {
101 102
			/* It is safe to push/pull even if skb_shared() */
			__skb_push(skb, skb->mac_len);
103
			bpf_compute_data_pointers(skb);
104 105 106
			filter_res = BPF_PROG_RUN(prog->filter, skb);
			__skb_pull(skb, skb->mac_len);
		} else {
107
			bpf_compute_data_pointers(skb);
108 109
			filter_res = BPF_PROG_RUN(prog->filter, skb);
		}
110

111
		if (prog->exts_integrated) {
112 113 114
			res->class   = 0;
			res->classid = TC_H_MAJ(prog->res.classid) |
				       qdisc_skb_cb(skb)->tc_classid;
115 116 117 118 119 120 121

			ret = cls_bpf_exec_opcode(filter_res);
			if (ret == TC_ACT_UNSPEC)
				continue;
			break;
		}

122 123
		if (filter_res == 0)
			continue;
124 125
		if (filter_res != -1) {
			res->class   = 0;
126
			res->classid = filter_res;
127 128 129
		} else {
			*res = prog->res;
		}
130 131 132 133 134

		ret = tcf_exts_exec(skb, &prog->exts, res);
		if (ret < 0)
			continue;

135
		break;
136
	}
137
	rcu_read_unlock();
138

139
	return ret;
140 141
}

142 143 144 145 146
static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog)
{
	return !prog->bpf_ops;
}

147
static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
148 149
			       struct cls_bpf_prog *oldprog,
			       struct netlink_ext_ack *extack)
150
{
151
	struct tcf_block *block = tp->chain->block;
152
	struct tc_cls_bpf_offload cls_bpf = {};
153 154
	struct cls_bpf_prog *obj;
	bool skip_sw;
155
	int err;
156

157 158 159
	skip_sw = prog && tc_skip_sw(prog->gen_flags);
	obj = prog ?: oldprog;

160 161
	tc_cls_common_offload_init(&cls_bpf.common, tp, obj->gen_flags,
				   extack);
162 163 164 165 166 167
	cls_bpf.command = TC_CLSBPF_OFFLOAD;
	cls_bpf.exts = &obj->exts;
	cls_bpf.prog = prog ? prog->filter : NULL;
	cls_bpf.oldprog = oldprog ? oldprog->filter : NULL;
	cls_bpf.name = obj->bpf_name;
	cls_bpf.exts_integrated = obj->exts_integrated;
168

169 170 171
	if (oldprog)
		tcf_block_offload_dec(block, &oldprog->gen_flags);

172
	err = tc_setup_cb_call(block, TC_SETUP_CLSBPF, &cls_bpf, skip_sw);
173
	if (prog) {
174
		if (err < 0) {
175
			cls_bpf_offload_cmd(tp, oldprog, prog, extack);
176 177
			return err;
		} else if (err > 0) {
178
			prog->in_hw_count = err;
179
			tcf_block_offload_inc(block, &prog->gen_flags);
180 181 182
		}
	}

183
	if (prog && skip_sw && !(prog->gen_flags & TCA_CLS_FLAGS_IN_HW))
184
		return -EINVAL;
185

186
	return 0;
187 188
}

189 190 191 192 193
static u32 cls_bpf_flags(u32 flags)
{
	return flags & CLS_BPF_SUPPORTED_GEN_FLAGS;
}

194
static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
195 196
			   struct cls_bpf_prog *oldprog,
			   struct netlink_ext_ack *extack)
197
{
198 199 200
	if (prog && oldprog &&
	    cls_bpf_flags(prog->gen_flags) !=
	    cls_bpf_flags(oldprog->gen_flags))
201
		return -EINVAL;
202

203 204 205 206 207 208
	if (prog && tc_skip_hw(prog->gen_flags))
		prog = NULL;
	if (oldprog && tc_skip_hw(oldprog->gen_flags))
		oldprog = NULL;
	if (!prog && !oldprog)
		return 0;
209

210
	return cls_bpf_offload_cmd(tp, prog, oldprog, extack);
211 212 213
}

static void cls_bpf_stop_offload(struct tcf_proto *tp,
214 215
				 struct cls_bpf_prog *prog,
				 struct netlink_ext_ack *extack)
216 217 218
{
	int err;

219
	err = cls_bpf_offload_cmd(tp, NULL, prog, extack);
220
	if (err)
221 222 223
		pr_err("Stopping hardware offload failed: %d\n", err);
}

224 225 226
static void cls_bpf_offload_update_stats(struct tcf_proto *tp,
					 struct cls_bpf_prog *prog)
{
227 228 229
	struct tcf_block *block = tp->chain->block;
	struct tc_cls_bpf_offload cls_bpf = {};

230
	tc_cls_common_offload_init(&cls_bpf.common, tp, prog->gen_flags, NULL);
231 232 233 234 235
	cls_bpf.command = TC_CLSBPF_STATS;
	cls_bpf.exts = &prog->exts;
	cls_bpf.prog = prog->filter;
	cls_bpf.name = prog->bpf_name;
	cls_bpf.exts_integrated = prog->exts_integrated;
236

237
	tc_setup_cb_call(block, TC_SETUP_CLSBPF, &cls_bpf, false);
238 239
}

240 241 242 243 244 245 246 247
static int cls_bpf_init(struct tcf_proto *tp)
{
	struct cls_bpf_head *head;

	head = kzalloc(sizeof(*head), GFP_KERNEL);
	if (head == NULL)
		return -ENOBUFS;

J
John Fastabend 已提交
248
	INIT_LIST_HEAD_RCU(&head->plist);
249
	idr_init(&head->handle_idr);
J
John Fastabend 已提交
250
	rcu_assign_pointer(tp->root, head);
251 252 253 254

	return 0;
}

255
static void cls_bpf_free_parms(struct cls_bpf_prog *prog)
256
{
257 258 259 260
	if (cls_bpf_is_ebpf(prog))
		bpf_prog_put(prog->filter);
	else
		bpf_prog_destroy(prog->filter);
261

262
	kfree(prog->bpf_name);
263
	kfree(prog->bpf_ops);
264 265 266 267 268 269 270 271
}

static void __cls_bpf_delete_prog(struct cls_bpf_prog *prog)
{
	tcf_exts_destroy(&prog->exts);
	tcf_exts_put_net(&prog->exts);

	cls_bpf_free_parms(prog);
272 273 274
	kfree(prog);
}

275 276
static void cls_bpf_delete_prog_work(struct work_struct *work)
{
C
Cong Wang 已提交
277 278 279
	struct cls_bpf_prog *prog = container_of(to_rcu_work(work),
						 struct cls_bpf_prog,
						 rwork);
280 281 282 283 284
	rtnl_lock();
	__cls_bpf_delete_prog(prog);
	rtnl_unlock();
}

285 286
static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog,
			     struct netlink_ext_ack *extack)
287
{
288 289
	struct cls_bpf_head *head = rtnl_dereference(tp->root);

290
	idr_remove(&head->handle_idr, prog->handle);
291
	cls_bpf_stop_offload(tp, prog, extack);
292 293
	list_del_rcu(&prog->link);
	tcf_unbind_filter(tp, &prog->res);
294
	if (tcf_exts_get_net(&prog->exts))
C
Cong Wang 已提交
295
		tcf_queue_work(&prog->rwork, cls_bpf_delete_prog_work);
296 297
	else
		__cls_bpf_delete_prog(prog);
298
}
299

300
static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
301
			  bool rtnl_held, struct netlink_ext_ack *extack)
302
{
303 304
	struct cls_bpf_head *head = rtnl_dereference(tp->root);

305
	__cls_bpf_delete(tp, arg, extack);
306
	*last = list_empty(&head->plist);
307
	return 0;
308 309
}

310
static void cls_bpf_destroy(struct tcf_proto *tp, bool rtnl_held,
311
			    struct netlink_ext_ack *extack)
312
{
J
John Fastabend 已提交
313
	struct cls_bpf_head *head = rtnl_dereference(tp->root);
314 315
	struct cls_bpf_prog *prog, *tmp;

316
	list_for_each_entry_safe(prog, tmp, &head->plist, link)
317
		__cls_bpf_delete(tp, prog, extack);
318

319
	idr_destroy(&head->handle_idr);
J
John Fastabend 已提交
320
	kfree_rcu(head, rcu);
321 322
}

323
static void *cls_bpf_get(struct tcf_proto *tp, u32 handle)
324
{
J
John Fastabend 已提交
325
	struct cls_bpf_head *head = rtnl_dereference(tp->root);
326 327
	struct cls_bpf_prog *prog;

328
	list_for_each_entry(prog, &head->plist, link) {
329 330
		if (prog->handle == handle)
			return prog;
331 332
	}

333
	return NULL;
334 335
}

336
static int cls_bpf_prog_from_ops(struct nlattr **tb, struct cls_bpf_prog *prog)
337
{
J
John Fastabend 已提交
338
	struct sock_filter *bpf_ops;
339
	struct sock_fprog_kern fprog_tmp;
J
John Fastabend 已提交
340
	struct bpf_prog *fp;
341
	u16 bpf_size, bpf_num_ops;
342 343
	int ret;

344
	bpf_num_ops = nla_get_u16(tb[TCA_BPF_OPS_LEN]);
345 346
	if (bpf_num_ops > BPF_MAXINSNS || bpf_num_ops == 0)
		return -EINVAL;
347

348
	bpf_size = bpf_num_ops * sizeof(*bpf_ops);
349 350
	if (bpf_size != nla_len(tb[TCA_BPF_OPS]))
		return -EINVAL;
351

352
	bpf_ops = kmemdup(nla_data(tb[TCA_BPF_OPS]), bpf_size, GFP_KERNEL);
353 354
	if (bpf_ops == NULL)
		return -ENOMEM;
355

356 357
	fprog_tmp.len = bpf_num_ops;
	fprog_tmp.filter = bpf_ops;
358

359 360 361 362 363
	ret = bpf_prog_create(&fp, &fprog_tmp);
	if (ret < 0) {
		kfree(bpf_ops);
		return ret;
	}
364 365

	prog->bpf_ops = bpf_ops;
366 367
	prog->bpf_num_ops = bpf_num_ops;
	prog->bpf_name = NULL;
368 369
	prog->filter = fp;

370 371 372
	return 0;
}

373
static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
374
				 u32 gen_flags, const struct tcf_proto *tp)
375 376 377
{
	struct bpf_prog *fp;
	char *name = NULL;
378
	bool skip_sw;
379 380 381
	u32 bpf_fd;

	bpf_fd = nla_get_u32(tb[TCA_BPF_FD]);
382
	skip_sw = gen_flags & TCA_CLS_FLAGS_SKIP_SW;
383

384
	fp = bpf_prog_get_type_dev(bpf_fd, BPF_PROG_TYPE_SCHED_CLS, skip_sw);
385 386 387 388
	if (IS_ERR(fp))
		return PTR_ERR(fp);

	if (tb[TCA_BPF_NAME]) {
389
		name = nla_memdup(tb[TCA_BPF_NAME], GFP_KERNEL);
390 391 392 393 394 395 396 397 398 399
		if (!name) {
			bpf_prog_put(fp);
			return -ENOMEM;
		}
	}

	prog->bpf_ops = NULL;
	prog->bpf_name = name;
	prog->filter = fp;

400 401
	if (fp->dst_needed)
		tcf_block_netif_keep_dst(tp->chain->block);
402

403 404 405
	return 0;
}

406 407
static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
			     struct cls_bpf_prog *prog, unsigned long base,
408 409
			     struct nlattr **tb, struct nlattr *est, bool ovr,
			     struct netlink_ext_ack *extack)
410
{
411
	bool is_bpf, is_ebpf, have_exts = false;
412
	u32 gen_flags = 0;
413 414 415 416
	int ret;

	is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS];
	is_ebpf = tb[TCA_BPF_FD];
417
	if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
418 419
		return -EINVAL;

420 421
	ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, ovr, true,
				extack);
422 423 424
	if (ret < 0)
		return ret;

425 426 427
	if (tb[TCA_BPF_FLAGS]) {
		u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);

428 429
		if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT)
			return -EINVAL;
430 431 432

		have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
	}
433 434 435
	if (tb[TCA_BPF_FLAGS_GEN]) {
		gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
		if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
436 437
		    !tc_flags_valid(gen_flags))
			return -EINVAL;
438
	}
439 440

	prog->exts_integrated = have_exts;
441
	prog->gen_flags = gen_flags;
442

443
	ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
444
		       cls_bpf_prog_from_efd(tb, prog, gen_flags, tp);
445
	if (ret < 0)
446
		return ret;
447

448 449 450 451
	if (tb[TCA_BPF_CLASSID]) {
		prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
		tcf_bind_filter(tp, &prog->res, base);
	}
452 453 454 455 456 457 458

	return 0;
}

static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
			  struct tcf_proto *tp, unsigned long base,
			  u32 handle, struct nlattr **tca,
459 460
			  void **arg, bool ovr, bool rtnl_held,
			  struct netlink_ext_ack *extack)
461
{
J
John Fastabend 已提交
462
	struct cls_bpf_head *head = rtnl_dereference(tp->root);
463
	struct cls_bpf_prog *oldprog = *arg;
464
	struct nlattr *tb[TCA_BPF_MAX + 1];
J
John Fastabend 已提交
465
	struct cls_bpf_prog *prog;
466 467 468 469 470
	int ret;

	if (tca[TCA_OPTIONS] == NULL)
		return -EINVAL;

471 472
	ret = nla_parse_nested(tb, TCA_BPF_MAX, tca[TCA_OPTIONS], bpf_policy,
			       NULL);
473 474 475 476
	if (ret < 0)
		return ret;

	prog = kzalloc(sizeof(*prog), GFP_KERNEL);
J
John Fastabend 已提交
477
	if (!prog)
478 479
		return -ENOBUFS;

480 481 482
	ret = tcf_exts_init(&prog->exts, TCA_BPF_ACT, TCA_BPF_POLICE);
	if (ret < 0)
		goto errout;
J
John Fastabend 已提交
483 484 485 486 487 488 489 490

	if (oldprog) {
		if (handle && oldprog->handle != handle) {
			ret = -EINVAL;
			goto errout;
		}
	}

491
	if (handle == 0) {
492 493 494 495 496 497
		handle = 1;
		ret = idr_alloc_u32(&head->handle_idr, prog, &handle,
				    INT_MAX, GFP_KERNEL);
	} else if (!oldprog) {
		ret = idr_alloc_u32(&head->handle_idr, prog, &handle,
				    handle, GFP_KERNEL);
498 499
	}

500 501 502 503
	if (ret)
		goto errout;
	prog->handle = handle;

504 505
	ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr,
				extack);
506
	if (ret < 0)
507
		goto errout_idr;
508

509
	ret = cls_bpf_offload(tp, prog, oldprog, extack);
510 511
	if (ret)
		goto errout_parms;
512

513 514 515
	if (!tc_in_hw(prog->gen_flags))
		prog->gen_flags |= TCA_CLS_FLAGS_NOT_IN_HW;

J
John Fastabend 已提交
516
	if (oldprog) {
517
		idr_replace(&head->handle_idr, prog, handle);
518
		list_replace_rcu(&oldprog->link, &prog->link);
519
		tcf_unbind_filter(tp, &oldprog->res);
520
		tcf_exts_get_net(&oldprog->exts);
C
Cong Wang 已提交
521
		tcf_queue_work(&oldprog->rwork, cls_bpf_delete_prog_work);
J
John Fastabend 已提交
522 523 524
	} else {
		list_add_rcu(&prog->link, &head->plist);
	}
525

526
	*arg = prog;
527
	return 0;
528

529 530
errout_parms:
	cls_bpf_free_parms(prog);
531 532
errout_idr:
	if (!oldprog)
533
		idr_remove(&head->handle_idr, prog->handle);
534
errout:
535
	tcf_exts_destroy(&prog->exts);
J
John Fastabend 已提交
536
	kfree(prog);
537 538 539
	return ret;
}

540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
static int cls_bpf_dump_bpf_info(const struct cls_bpf_prog *prog,
				 struct sk_buff *skb)
{
	struct nlattr *nla;

	if (nla_put_u16(skb, TCA_BPF_OPS_LEN, prog->bpf_num_ops))
		return -EMSGSIZE;

	nla = nla_reserve(skb, TCA_BPF_OPS, prog->bpf_num_ops *
			  sizeof(struct sock_filter));
	if (nla == NULL)
		return -EMSGSIZE;

	memcpy(nla_data(nla), prog->bpf_ops, nla_len(nla));

	return 0;
}

static int cls_bpf_dump_ebpf_info(const struct cls_bpf_prog *prog,
				  struct sk_buff *skb)
{
561 562
	struct nlattr *nla;

563 564 565 566
	if (prog->bpf_name &&
	    nla_put_string(skb, TCA_BPF_NAME, prog->bpf_name))
		return -EMSGSIZE;

567 568 569
	if (nla_put_u32(skb, TCA_BPF_ID, prog->filter->aux->id))
		return -EMSGSIZE;

570
	nla = nla_reserve(skb, TCA_BPF_TAG, sizeof(prog->filter->tag));
571 572 573
	if (nla == NULL)
		return -EMSGSIZE;

574
	memcpy(nla_data(nla), prog->filter->tag, nla_len(nla));
575

576 577 578
	return 0;
}

579
static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, void *fh,
580
			struct sk_buff *skb, struct tcmsg *tm, bool rtnl_held)
581
{
582
	struct cls_bpf_prog *prog = fh;
583
	struct nlattr *nest;
584
	u32 bpf_flags = 0;
585
	int ret;
586 587 588 589 590 591

	if (prog == NULL)
		return skb->len;

	tm->tcm_handle = prog->handle;

592 593
	cls_bpf_offload_update_stats(tp, prog);

594 595 596 597
	nest = nla_nest_start(skb, TCA_OPTIONS);
	if (nest == NULL)
		goto nla_put_failure;

598 599
	if (prog->res.classid &&
	    nla_put_u32(skb, TCA_BPF_CLASSID, prog->res.classid))
600 601
		goto nla_put_failure;

602 603 604 605 606
	if (cls_bpf_is_ebpf(prog))
		ret = cls_bpf_dump_ebpf_info(prog, skb);
	else
		ret = cls_bpf_dump_bpf_info(prog, skb);
	if (ret)
607 608
		goto nla_put_failure;

609
	if (tcf_exts_dump(skb, &prog->exts) < 0)
610 611
		goto nla_put_failure;

612 613 614 615
	if (prog->exts_integrated)
		bpf_flags |= TCA_BPF_FLAG_ACT_DIRECT;
	if (bpf_flags && nla_put_u32(skb, TCA_BPF_FLAGS, bpf_flags))
		goto nla_put_failure;
616 617 618
	if (prog->gen_flags &&
	    nla_put_u32(skb, TCA_BPF_FLAGS_GEN, prog->gen_flags))
		goto nla_put_failure;
619

620 621
	nla_nest_end(skb, nest);

622
	if (tcf_exts_dump_stats(skb, &prog->exts) < 0)
623 624 625 626 627 628 629 630 631
		goto nla_put_failure;

	return skb->len;

nla_put_failure:
	nla_nest_cancel(skb, nest);
	return -1;
}

632 633 634 635 636 637 638 639
static void cls_bpf_bind_class(void *fh, u32 classid, unsigned long cl)
{
	struct cls_bpf_prog *prog = fh;

	if (prog && prog->res.classid == classid)
		prog->res.class = cl;
}

640 641
static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg,
			 bool rtnl_held)
642
{
J
John Fastabend 已提交
643
	struct cls_bpf_head *head = rtnl_dereference(tp->root);
644 645
	struct cls_bpf_prog *prog;

646
	list_for_each_entry(prog, &head->plist, link) {
647 648
		if (arg->count < arg->skip)
			goto skip;
649
		if (arg->fn(tp, prog, arg) < 0) {
650 651 652 653 654 655 656 657
			arg->stop = 1;
			break;
		}
skip:
		arg->count++;
	}
}

658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
static int cls_bpf_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
			     void *cb_priv, struct netlink_ext_ack *extack)
{
	struct cls_bpf_head *head = rtnl_dereference(tp->root);
	struct tcf_block *block = tp->chain->block;
	struct tc_cls_bpf_offload cls_bpf = {};
	struct cls_bpf_prog *prog;
	int err;

	list_for_each_entry(prog, &head->plist, link) {
		if (tc_skip_hw(prog->gen_flags))
			continue;

		tc_cls_common_offload_init(&cls_bpf.common, tp, prog->gen_flags,
					   extack);
		cls_bpf.command = TC_CLSBPF_OFFLOAD;
		cls_bpf.exts = &prog->exts;
		cls_bpf.prog = add ? prog->filter : NULL;
		cls_bpf.oldprog = add ? NULL : prog->filter;
		cls_bpf.name = prog->bpf_name;
		cls_bpf.exts_integrated = prog->exts_integrated;

		err = cb(TC_SETUP_CLSBPF, &cls_bpf, cb_priv);
		if (err) {
			if (add && tc_skip_sw(prog->gen_flags))
				return err;
			continue;
		}

		tc_cls_offload_cnt_update(block, &prog->in_hw_count,
					  &prog->gen_flags, add);
	}

	return 0;
}

694 695 696 697 698 699 700 701 702 703
static struct tcf_proto_ops cls_bpf_ops __read_mostly = {
	.kind		=	"bpf",
	.owner		=	THIS_MODULE,
	.classify	=	cls_bpf_classify,
	.init		=	cls_bpf_init,
	.destroy	=	cls_bpf_destroy,
	.get		=	cls_bpf_get,
	.change		=	cls_bpf_change,
	.delete		=	cls_bpf_delete,
	.walk		=	cls_bpf_walk,
704
	.reoffload	=	cls_bpf_reoffload,
705
	.dump		=	cls_bpf_dump,
706
	.bind_class	=	cls_bpf_bind_class,
707 708 709 710 711 712 713 714 715 716 717 718 719 720
};

static int __init cls_bpf_init_mod(void)
{
	return register_tcf_proto_ops(&cls_bpf_ops);
}

static void __exit cls_bpf_exit_mod(void)
{
	unregister_tcf_proto_ops(&cls_bpf_ops);
}

module_init(cls_bpf_init_mod);
module_exit(cls_bpf_exit_mod);