act_api.c 40.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * net/sched/act_api.c	Packet action API.
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 *
 * Author:	Jamal Hadi Salim
 *
 *
 */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
18
#include <linux/slab.h>
L
Linus Torvalds 已提交
19 20 21
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/kmod.h>
22
#include <linux/err.h>
23
#include <linux/module.h>
24 25
#include <linux/rhashtable.h>
#include <linux/list.h>
26 27
#include <net/net_namespace.h>
#include <net/sock.h>
L
Linus Torvalds 已提交
28
#include <net/sch_generic.h>
29
#include <net/pkt_cls.h>
L
Linus Torvalds 已提交
30
#include <net/act_api.h>
31
#include <net/netlink.h>
L
Linus Torvalds 已提交
32

33 34 35 36 37 38
static int tcf_action_goto_chain_init(struct tc_action *a, struct tcf_proto *tp)
{
	u32 chain_index = a->tcfa_action & TC_ACT_EXT_VAL_MASK;

	if (!tp)
		return -EINVAL;
39
	a->goto_chain = tcf_chain_get_by_act(tp->chain->block, chain_index);
40 41 42 43 44 45 46
	if (!a->goto_chain)
		return -ENOMEM;
	return 0;
}

static void tcf_action_goto_chain_fini(struct tc_action *a)
{
47
	tcf_chain_put_by_act(a->goto_chain);
48 49 50 51 52 53 54 55 56 57
}

static void tcf_action_goto_chain_exec(const struct tc_action *a,
				       struct tcf_result *res)
{
	const struct tcf_chain *chain = a->goto_chain;

	res->goto_tp = rcu_dereference_bh(chain->filter_chain);
}

58 59 60 61 62 63 64 65 66 67 68 69 70
static void tcf_free_cookie_rcu(struct rcu_head *p)
{
	struct tc_cookie *cookie = container_of(p, struct tc_cookie, rcu);

	kfree(cookie->data);
	kfree(cookie);
}

static void tcf_set_action_cookie(struct tc_cookie __rcu **old_cookie,
				  struct tc_cookie *new_cookie)
{
	struct tc_cookie *old;

71
	old = xchg((__force struct tc_cookie **)old_cookie, new_cookie);
72 73 74 75
	if (old)
		call_rcu(&old->rcu, tcf_free_cookie_rcu);
}

C
Cong Wang 已提交
76 77 78 79 80 81
/* XXX: For standalone actions, we don't need a RCU grace period either, because
 * actions are always connected to filters and filters are already destroyed in
 * RCU callbacks, so after a RCU grace period actions are already disconnected
 * from filters. Readers later can not find us.
 */
static void free_tcf(struct tc_action *p)
82 83
{
	free_percpu(p->cpu_bstats);
84
	free_percpu(p->cpu_bstats_hw);
85
	free_percpu(p->cpu_qstats);
86

87
	tcf_set_action_cookie(&p->act_cookie, NULL);
88 89
	if (p->goto_chain)
		tcf_action_goto_chain_fini(p);
90

91 92 93
	kfree(p);
}

94
static void tcf_action_cleanup(struct tc_action *p)
95
{
96 97 98
	if (p->ops->cleanup)
		p->ops->cleanup(p);

99
	gen_kill_estimator(&p->tcfa_rate_est);
C
Cong Wang 已提交
100
	free_tcf(p);
101 102
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
static int __tcf_action_put(struct tc_action *p, bool bind)
{
	struct tcf_idrinfo *idrinfo = p->idrinfo;

	if (refcount_dec_and_lock(&p->tcfa_refcnt, &idrinfo->lock)) {
		if (bind)
			atomic_dec(&p->tcfa_bindcnt);
		idr_remove(&idrinfo->action_idr, p->tcfa_index);
		spin_unlock(&idrinfo->lock);

		tcf_action_cleanup(p);
		return 1;
	}

	if (bind)
		atomic_dec(&p->tcfa_bindcnt);

	return 0;
}

123
int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
124 125 126
{
	int ret = 0;

127 128 129 130 131 132 133 134 135 136 137 138
	/* Release with strict==1 and bind==0 is only called through act API
	 * interface (classifiers always bind). Only case when action with
	 * positive reference count and zero bind count can exist is when it was
	 * also created with act API (unbinding last classifier will destroy the
	 * action if it was created by classifier). So only case when bind count
	 * can be changed after initial check is when unbound action is
	 * destroyed by act API while classifier binds to action with same id
	 * concurrently. This result either creation of new action(same behavior
	 * as before), or reusing existing action if concurrent process
	 * increments reference count before action is deleted. Both scenarios
	 * are acceptable.
	 */
139
	if (p) {
140
		if (!bind && strict && atomic_read(&p->tcfa_bindcnt) > 0)
141
			return -EPERM;
142

143
		if (__tcf_action_put(p, bind))
144
			ret = ACT_P_DELETED;
145
	}
146

147 148
	return ret;
}
149
EXPORT_SYMBOL(__tcf_idr_release);
150

151 152
static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
{
153
	struct tc_cookie *act_cookie;
154 155
	u32 cookie_len = 0;

156 157 158 159 160 161
	rcu_read_lock();
	act_cookie = rcu_dereference(act->act_cookie);

	if (act_cookie)
		cookie_len = nla_total_size(act_cookie->len);
	rcu_read_unlock();
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

	return  nla_total_size(0) /* action number nested */
		+ nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */
		+ cookie_len /* TCA_ACT_COOKIE */
		+ nla_total_size(0) /* TCA_ACT_STATS nested */
		/* TCA_STATS_BASIC */
		+ nla_total_size_64bit(sizeof(struct gnet_stats_basic))
		/* TCA_STATS_QUEUE */
		+ nla_total_size_64bit(sizeof(struct gnet_stats_queue))
		+ nla_total_size(0) /* TCA_OPTIONS nested */
		+ nla_total_size(sizeof(struct tcf_t)); /* TCA_GACT_TM */
}

static size_t tcf_action_full_attrs_size(size_t sz)
{
	return NLMSG_HDRLEN                     /* struct nlmsghdr */
		+ sizeof(struct tcamsg)
		+ nla_total_size(0)             /* TCA_ACT_TAB nested */
		+ sz;
}

static size_t tcf_action_fill_size(const struct tc_action *act)
{
	size_t sz = tcf_action_shared_attrs_size(act);

	if (act->ops->get_fill_size)
		return act->ops->get_fill_size(act) + sz;
	return sz;
}

192
static int tcf_dump_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
193
			   struct netlink_callback *cb)
194
{
195
	int err = 0, index = -1, s_i = 0, n_i = 0;
196
	u32 act_flags = cb->args[2];
197
	unsigned long jiffy_since = cb->args[3];
198
	struct nlattr *nest;
199 200 201
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	unsigned long id = 1;
202

203
	spin_lock(&idrinfo->lock);
204 205 206

	s_i = cb->args[0];

207
	idr_for_each_entry_ul(idr, p, id) {
208 209 210 211 212 213 214 215 216 217
		index++;
		if (index < s_i)
			continue;

		if (jiffy_since &&
		    time_after(jiffy_since,
			       (unsigned long)p->tcfa_tm.lastuse))
			continue;

		nest = nla_nest_start(skb, n_i);
218 219
		if (!nest) {
			index--;
220
			goto nla_put_failure;
221
		}
222 223 224 225 226
		err = tcf_action_dump_1(skb, p, 0, 0);
		if (err < 0) {
			index--;
			nlmsg_trim(skb, nest);
			goto done;
227
		}
228 229 230 231 232
		nla_nest_end(skb, nest);
		n_i++;
		if (!(act_flags & TCA_FLAG_LARGE_DUMP_ON) &&
		    n_i >= TCA_ACT_MAX_PRIO)
			goto done;
233 234
	}
done:
235 236 237
	if (index >= 0)
		cb->args[0] = index + 1;

238
	spin_unlock(&idrinfo->lock);
239 240 241 242
	if (n_i) {
		if (act_flags & TCA_FLAG_LARGE_DUMP_ON)
			cb->args[1] = n_i;
	}
243 244
	return n_i;

245
nla_put_failure:
246
	nla_nest_cancel(skb, nest);
247 248 249
	goto done;
}

250 251 252 253 254 255 256 257 258 259 260 261 262 263
static int tcf_idr_release_unsafe(struct tc_action *p)
{
	if (atomic_read(&p->tcfa_bindcnt) > 0)
		return -EPERM;

	if (refcount_dec_and_test(&p->tcfa_refcnt)) {
		idr_remove(&p->idrinfo->action_idr, p->tcfa_index);
		tcf_action_cleanup(p);
		return ACT_P_DELETED;
	}

	return 0;
}

264
static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
265
			  const struct tc_action_ops *ops)
266
{
267
	struct nlattr *nest;
268
	int n_i = 0;
269
	int ret = -EINVAL;
270 271 272
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	unsigned long id = 1;
273

274
	nest = nla_nest_start(skb, 0);
275 276
	if (nest == NULL)
		goto nla_put_failure;
277
	if (nla_put_string(skb, TCA_KIND, ops->kind))
278
		goto nla_put_failure;
279

280
	spin_lock(&idrinfo->lock);
281
	idr_for_each_entry_ul(idr, p, id) {
282
		ret = tcf_idr_release_unsafe(p);
283
		if (ret == ACT_P_DELETED) {
284
			module_put(ops->owner);
285 286
			n_i++;
		} else if (ret < 0) {
287
			spin_unlock(&idrinfo->lock);
288
			goto nla_put_failure;
289 290
		}
	}
291 292
	spin_unlock(&idrinfo->lock);

293 294
	if (nla_put_u32(skb, TCA_FCNT, n_i))
		goto nla_put_failure;
295
	nla_nest_end(skb, nest);
296 297

	return n_i;
298
nla_put_failure:
299
	nla_nest_cancel(skb, nest);
300
	return ret;
301 302
}

303 304
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
		       struct netlink_callback *cb, int type,
305 306
		       const struct tc_action_ops *ops,
		       struct netlink_ext_ack *extack)
307
{
308
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
309

310
	if (type == RTM_DELACTION) {
311
		return tcf_del_walker(idrinfo, skb, ops);
312
	} else if (type == RTM_GETACTION) {
313
		return tcf_dump_walker(idrinfo, skb, cb);
314
	} else {
315 316
		WARN(1, "tcf_generic_walker: unknown command %d\n", type);
		NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown command");
317 318 319
		return -EINVAL;
	}
}
320
EXPORT_SYMBOL(tcf_generic_walker);
321

322
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
323
{
324 325
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
	struct tc_action *p;
326

327
	spin_lock(&idrinfo->lock);
328
	p = idr_find(&idrinfo->action_idr, index);
329
	if (IS_ERR(p))
330
		p = NULL;
331
	else if (p)
332
		refcount_inc(&p->tcfa_refcnt);
333
	spin_unlock(&idrinfo->lock);
334

335 336 337 338 339
	if (p) {
		*a = p;
		return true;
	}
	return false;
340
}
341
EXPORT_SYMBOL(tcf_idr_search);
342

343
static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index)
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
{
	struct tc_action *p;
	int ret = 0;

	spin_lock(&idrinfo->lock);
	p = idr_find(&idrinfo->action_idr, index);
	if (!p) {
		spin_unlock(&idrinfo->lock);
		return -ENOENT;
	}

	if (!atomic_read(&p->tcfa_bindcnt)) {
		if (refcount_dec_and_test(&p->tcfa_refcnt)) {
			struct module *owner = p->ops->owner;

			WARN_ON(p != idr_remove(&idrinfo->action_idr,
						p->tcfa_index));
			spin_unlock(&idrinfo->lock);

363
			tcf_action_cleanup(p);
364 365 366 367 368 369 370 371 372 373 374 375
			module_put(owner);
			return 0;
		}
		ret = 0;
	} else {
		ret = -EPERM;
	}

	spin_unlock(&idrinfo->lock);
	return ret;
}

376 377 378
int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
		   struct tc_action **a, const struct tc_action_ops *ops,
		   int bind, bool cpustats)
379
{
380
	struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
381
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
382
	int err = -ENOMEM;
383 384

	if (unlikely(!p))
385
		return -ENOMEM;
386
	refcount_set(&p->tcfa_refcnt, 1);
387
	if (bind)
388
		atomic_set(&p->tcfa_bindcnt, 1);
389

390 391
	if (cpustats) {
		p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
392
		if (!p->cpu_bstats)
393
			goto err1;
394 395 396
		p->cpu_bstats_hw = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
		if (!p->cpu_bstats_hw)
			goto err2;
397 398
		p->cpu_qstats = alloc_percpu(struct gnet_stats_queue);
		if (!p->cpu_qstats)
399
			goto err3;
400
	}
401
	spin_lock_init(&p->tcfa_lock);
402
	p->tcfa_index = index;
403 404 405
	p->tcfa_tm.install = jiffies;
	p->tcfa_tm.lastuse = jiffies;
	p->tcfa_tm.firstuse = 0;
406
	if (est) {
407 408 409
		err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
					&p->tcfa_rate_est,
					&p->tcfa_lock, NULL, est);
410
		if (err)
411
			goto err4;
412 413
	}

414
	p->idrinfo = idrinfo;
415 416
	p->ops = ops;
	*a = p;
417
	return 0;
418
err4:
419
	free_percpu(p->cpu_qstats);
420 421
err3:
	free_percpu(p->cpu_bstats_hw);
422 423 424 425 426
err2:
	free_percpu(p->cpu_bstats);
err1:
	kfree(p);
	return err;
427
}
428
EXPORT_SYMBOL(tcf_idr_create);
429

430
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
431
{
432
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
433

434
	spin_lock(&idrinfo->lock);
435 436
	/* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
	WARN_ON(!IS_ERR(idr_replace(&idrinfo->action_idr, a, a->tcfa_index)));
437
	spin_unlock(&idrinfo->lock);
438
}
439
EXPORT_SYMBOL(tcf_idr_insert);
L
Linus Torvalds 已提交
440

441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
/* Cleanup idr index that was allocated but not initialized. */

void tcf_idr_cleanup(struct tc_action_net *tn, u32 index)
{
	struct tcf_idrinfo *idrinfo = tn->idrinfo;

	spin_lock(&idrinfo->lock);
	/* Remove ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
	WARN_ON(!IS_ERR(idr_remove(&idrinfo->action_idr, index)));
	spin_unlock(&idrinfo->lock);
}
EXPORT_SYMBOL(tcf_idr_cleanup);

/* Check if action with specified index exists. If actions is found, increments
 * its reference and bind counters, and return 1. Otherwise insert temporary
 * error pointer (to prevent concurrent users from inserting actions with same
 * index) and return 0.
 */

int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
			struct tc_action **a, int bind)
{
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
	struct tc_action *p;
	int ret;

again:
	spin_lock(&idrinfo->lock);
	if (*index) {
		p = idr_find(&idrinfo->action_idr, *index);
		if (IS_ERR(p)) {
			/* This means that another process allocated
			 * index but did not assign the pointer yet.
			 */
			spin_unlock(&idrinfo->lock);
			goto again;
		}

		if (p) {
			refcount_inc(&p->tcfa_refcnt);
			if (bind)
				atomic_inc(&p->tcfa_bindcnt);
			*a = p;
			ret = 1;
		} else {
			*a = NULL;
			ret = idr_alloc_u32(&idrinfo->action_idr, NULL, index,
					    *index, GFP_ATOMIC);
			if (!ret)
				idr_replace(&idrinfo->action_idr,
					    ERR_PTR(-EBUSY), *index);
		}
	} else {
		*index = 1;
		*a = NULL;
		ret = idr_alloc_u32(&idrinfo->action_idr, NULL, index,
				    UINT_MAX, GFP_ATOMIC);
		if (!ret)
			idr_replace(&idrinfo->action_idr, ERR_PTR(-EBUSY),
				    *index);
	}
	spin_unlock(&idrinfo->lock);
	return ret;
}
EXPORT_SYMBOL(tcf_idr_check_alloc);

507 508
void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
			 struct tcf_idrinfo *idrinfo)
509
{
510 511 512 513
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	int ret;
	unsigned long id = 1;
514

515
	idr_for_each_entry_ul(idr, p, id) {
516 517 518 519 520
		ret = __tcf_idr_release(p, false, true);
		if (ret == ACT_P_DELETED)
			module_put(ops->owner);
		else if (ret < 0)
			return;
521
	}
522
	idr_destroy(&idrinfo->action_idr);
523
}
524
EXPORT_SYMBOL(tcf_idrinfo_destroy);
525

526
static LIST_HEAD(act_base);
L
Linus Torvalds 已提交
527 528
static DEFINE_RWLOCK(act_mod_lock);

529 530
int tcf_register_action(struct tc_action_ops *act,
			struct pernet_operations *ops)
L
Linus Torvalds 已提交
531
{
532
	struct tc_action_ops *a;
533
	int ret;
L
Linus Torvalds 已提交
534

535
	if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
536 537
		return -EINVAL;

538 539 540 541 542 543 544 545
	/* We have to register pernet ops before making the action ops visible,
	 * otherwise tcf_action_init_1() could get a partially initialized
	 * netns.
	 */
	ret = register_pernet_subsys(ops);
	if (ret)
		return ret;

L
Linus Torvalds 已提交
546
	write_lock(&act_mod_lock);
547
	list_for_each_entry(a, &act_base, head) {
L
Linus Torvalds 已提交
548 549
		if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
			write_unlock(&act_mod_lock);
550
			unregister_pernet_subsys(ops);
L
Linus Torvalds 已提交
551 552 553
			return -EEXIST;
		}
	}
554
	list_add_tail(&act->head, &act_base);
L
Linus Torvalds 已提交
555
	write_unlock(&act_mod_lock);
556

L
Linus Torvalds 已提交
557 558
	return 0;
}
559
EXPORT_SYMBOL(tcf_register_action);
L
Linus Torvalds 已提交
560

561 562
int tcf_unregister_action(struct tc_action_ops *act,
			  struct pernet_operations *ops)
L
Linus Torvalds 已提交
563
{
564
	struct tc_action_ops *a;
L
Linus Torvalds 已提交
565 566 567
	int err = -ENOENT;

	write_lock(&act_mod_lock);
568 569 570 571
	list_for_each_entry(a, &act_base, head) {
		if (a == act) {
			list_del(&act->head);
			err = 0;
L
Linus Torvalds 已提交
572
			break;
573
		}
L
Linus Torvalds 已提交
574 575
	}
	write_unlock(&act_mod_lock);
576 577
	if (!err)
		unregister_pernet_subsys(ops);
L
Linus Torvalds 已提交
578 579
	return err;
}
580
EXPORT_SYMBOL(tcf_unregister_action);
L
Linus Torvalds 已提交
581 582 583 584

/* lookup by name */
static struct tc_action_ops *tc_lookup_action_n(char *kind)
{
585
	struct tc_action_ops *a, *res = NULL;
L
Linus Torvalds 已提交
586 587 588

	if (kind) {
		read_lock(&act_mod_lock);
589
		list_for_each_entry(a, &act_base, head) {
L
Linus Torvalds 已提交
590
			if (strcmp(kind, a->kind) == 0) {
591 592
				if (try_module_get(a->owner))
					res = a;
L
Linus Torvalds 已提交
593 594 595 596 597
				break;
			}
		}
		read_unlock(&act_mod_lock);
	}
598
	return res;
L
Linus Torvalds 已提交
599 600
}

601 602
/* lookup by nlattr */
static struct tc_action_ops *tc_lookup_action(struct nlattr *kind)
L
Linus Torvalds 已提交
603
{
604
	struct tc_action_ops *a, *res = NULL;
L
Linus Torvalds 已提交
605 606 607

	if (kind) {
		read_lock(&act_mod_lock);
608
		list_for_each_entry(a, &act_base, head) {
609
			if (nla_strcmp(kind, a->kind) == 0) {
610 611
				if (try_module_get(a->owner))
					res = a;
L
Linus Torvalds 已提交
612 613 614 615 616
				break;
			}
		}
		read_unlock(&act_mod_lock);
	}
617
	return res;
L
Linus Torvalds 已提交
618 619
}

620 621
/*TCA_ACT_MAX_PRIO is 32, there count upto 32 */
#define TCA_ACT_MAX_PRIO_MASK 0x1FF
622 623
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
		    int nr_actions, struct tcf_result *res)
L
Linus Torvalds 已提交
624
{
625 626
	u32 jmp_prgcnt = 0;
	u32 jmp_ttl = TCA_ACT_MAX_PRIO; /*matches actions per filter */
627 628
	int i;
	int ret = TC_ACT_OK;
L
Linus Torvalds 已提交
629

630 631 632
	if (skb_skip_tc_classify(skb))
		return TC_ACT_OK;

633
restart_act_graph:
634 635 636
	for (i = 0; i < nr_actions; i++) {
		const struct tc_action *a = actions[i];

637 638 639 640
		if (jmp_prgcnt > 0) {
			jmp_prgcnt -= 1;
			continue;
		}
L
Linus Torvalds 已提交
641
repeat:
642 643 644
		ret = a->ops->act(skb, a, res);
		if (ret == TC_ACT_REPEAT)
			goto repeat;	/* we need a ttl - JHS */
645

646
		if (TC_ACT_EXT_CMP(ret, TC_ACT_JUMP)) {
647 648 649 650 651 652 653 654 655 656 657
			jmp_prgcnt = ret & TCA_ACT_MAX_PRIO_MASK;
			if (!jmp_prgcnt || (jmp_prgcnt > nr_actions)) {
				/* faulty opcode, stop pipeline */
				return TC_ACT_OK;
			} else {
				jmp_ttl -= 1;
				if (jmp_ttl > 0)
					goto restart_act_graph;
				else /* faulty graph, stop pipeline */
					return TC_ACT_OK;
			}
658 659
		} else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) {
			tcf_action_goto_chain_exec(a, res);
660 661
		}

662
		if (ret != TC_ACT_PIPE)
663
			break;
L
Linus Torvalds 已提交
664
	}
665

L
Linus Torvalds 已提交
666 667
	return ret;
}
668
EXPORT_SYMBOL(tcf_action_exec);
L
Linus Torvalds 已提交
669

670
int tcf_action_destroy(struct tc_action *actions[], int bind)
L
Linus Torvalds 已提交
671
{
672
	const struct tc_action_ops *ops;
673 674
	struct tc_action *a;
	int ret = 0, i;
L
Linus Torvalds 已提交
675

676 677 678
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		a = actions[i];
		actions[i] = NULL;
679
		ops = a->ops;
680
		ret = __tcf_idr_release(a, bind, true);
681
		if (ret == ACT_P_DELETED)
682
			module_put(ops->owner);
683 684
		else if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
685
	}
686
	return ret;
L
Linus Torvalds 已提交
687 688
}

689 690 691 692 693 694 695
static int tcf_action_destroy_1(struct tc_action *a, int bind)
{
	struct tc_action *actions[] = { a, NULL };

	return tcf_action_destroy(actions, bind);
}

696 697 698 699 700
static int tcf_action_put(struct tc_action *p)
{
	return __tcf_action_put(p, false);
}

701
/* Put all actions in this array, skip those NULL's. */
702
static void tcf_action_put_many(struct tc_action *actions[])
703
{
704
	int i;
705

706
	for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
707
		struct tc_action *a = actions[i];
708
		const struct tc_action_ops *ops;
709

710 711 712
		if (!a)
			continue;
		ops = a->ops;
713 714 715 716 717
		if (tcf_action_put(a))
			module_put(ops->owner);
	}
}

L
Linus Torvalds 已提交
718 719 720 721 722 723 724 725 726 727
int
tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
	return a->ops->dump(skb, a, bind, ref);
}

int
tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
	int err = -EINVAL;
728
	unsigned char *b = skb_tail_pointer(skb);
729
	struct nlattr *nest;
730
	struct tc_cookie *cookie;
L
Linus Torvalds 已提交
731

732 733
	if (nla_put_string(skb, TCA_KIND, a->ops->kind))
		goto nla_put_failure;
L
Linus Torvalds 已提交
734
	if (tcf_action_copy_stats(skb, a, 0))
735
		goto nla_put_failure;
736 737 738 739 740 741

	rcu_read_lock();
	cookie = rcu_dereference(a->act_cookie);
	if (cookie) {
		if (nla_put(skb, TCA_ACT_COOKIE, cookie->len, cookie->data)) {
			rcu_read_unlock();
742
			goto nla_put_failure;
743
		}
744
	}
745
	rcu_read_unlock();
746

747 748 749
	nest = nla_nest_start(skb, TCA_OPTIONS);
	if (nest == NULL)
		goto nla_put_failure;
E
Eric Dumazet 已提交
750 751
	err = tcf_action_dump_old(skb, a, bind, ref);
	if (err > 0) {
752
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
753 754 755
		return err;
	}

756
nla_put_failure:
757
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
758 759
	return -1;
}
760
EXPORT_SYMBOL(tcf_action_dump_1);
L
Linus Torvalds 已提交
761

762
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[],
763
		    int bind, int ref)
L
Linus Torvalds 已提交
764 765
{
	struct tc_action *a;
766
	int err = -EINVAL, i;
767
	struct nlattr *nest;
L
Linus Torvalds 已提交
768

769 770
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		a = actions[i];
771 772 773
		nest = nla_nest_start(skb, a->order);
		if (nest == NULL)
			goto nla_put_failure;
L
Linus Torvalds 已提交
774 775
		err = tcf_action_dump_1(skb, a, bind, ref);
		if (err < 0)
776
			goto errout;
777
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
778 779 780 781
	}

	return 0;

782
nla_put_failure:
783 784
	err = -EINVAL;
errout:
785
	nla_nest_cancel(skb, nest);
786
	return err;
L
Linus Torvalds 已提交
787 788
}

789
static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
790
{
791 792 793 794 795 796 797 798
	struct tc_cookie *c = kzalloc(sizeof(*c), GFP_KERNEL);
	if (!c)
		return NULL;

	c->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
	if (!c->data) {
		kfree(c);
		return NULL;
799
	}
800
	c->len = nla_len(tb[TCA_ACT_COOKIE]);
801

802
	return c;
803 804
}

805 806 807 808 809 810 811 812 813
static bool tcf_action_valid(int action)
{
	int opcode = TC_ACT_EXT_OPCODE(action);

	if (!opcode)
		return action <= TC_ACT_VALUE_MAX;
	return opcode <= TC_ACT_EXT_OPCODE_MAX || action == TC_ACT_UNSPEC;
}

814 815
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
				    struct nlattr *nla, struct nlattr *est,
816
				    char *name, int ovr, int bind,
817
				    bool rtnl_held,
818
				    struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
819 820 821
{
	struct tc_action *a;
	struct tc_action_ops *a_o;
822
	struct tc_cookie *cookie = NULL;
L
Linus Torvalds 已提交
823
	char act_name[IFNAMSIZ];
E
Eric Dumazet 已提交
824
	struct nlattr *tb[TCA_ACT_MAX + 1];
825
	struct nlattr *kind;
826
	int err;
L
Linus Torvalds 已提交
827 828

	if (name == NULL) {
829
		err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
830
		if (err < 0)
L
Linus Torvalds 已提交
831
			goto err_out;
832
		err = -EINVAL;
833
		kind = tb[TCA_ACT_KIND];
834 835
		if (!kind) {
			NL_SET_ERR_MSG(extack, "TC action kind must be specified");
L
Linus Torvalds 已提交
836
			goto err_out;
837 838 839
		}
		if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
			NL_SET_ERR_MSG(extack, "TC action name too long");
L
Linus Torvalds 已提交
840
			goto err_out;
841
		}
842 843 844
		if (tb[TCA_ACT_COOKIE]) {
			int cklen = nla_len(tb[TCA_ACT_COOKIE]);

845 846
			if (cklen > TC_COOKIE_MAX_SIZE) {
				NL_SET_ERR_MSG(extack, "TC cookie size above the maximum");
847
				goto err_out;
848
			}
849 850 851

			cookie = nla_memdup_cookie(tb);
			if (!cookie) {
852
				NL_SET_ERR_MSG(extack, "No memory to generate TC cookie");
853 854 855 856
				err = -ENOMEM;
				goto err_out;
			}
		}
L
Linus Torvalds 已提交
857
	} else {
858 859 860
		if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
			NL_SET_ERR_MSG(extack, "TC action name too long");
			err = -EINVAL;
L
Linus Torvalds 已提交
861
			goto err_out;
862
		}
L
Linus Torvalds 已提交
863 864 865 866
	}

	a_o = tc_lookup_action_n(act_name);
	if (a_o == NULL) {
867
#ifdef CONFIG_MODULES
868 869
		if (rtnl_held)
			rtnl_unlock();
870
		request_module("act_%s", act_name);
871 872
		if (rtnl_held)
			rtnl_lock();
L
Linus Torvalds 已提交
873 874 875 876 877 878 879 880 881 882

		a_o = tc_lookup_action_n(act_name);

		/* We dropped the RTNL semaphore in order to
		 * perform the module load.  So, even if we
		 * succeeded in loading the module we have to
		 * tell the caller to replay the request.  We
		 * indicate this using -EAGAIN.
		 */
		if (a_o != NULL) {
883
			err = -EAGAIN;
L
Linus Torvalds 已提交
884 885 886
			goto err_mod;
		}
#endif
887
		NL_SET_ERR_MSG(extack, "Failed to load TC action module");
888
		err = -ENOENT;
L
Linus Torvalds 已提交
889 890 891 892 893
		goto err_out;
	}

	/* backward compatibility for policer */
	if (name == NULL)
894
		err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind,
895
				rtnl_held, extack);
L
Linus Torvalds 已提交
896
	else
897 898
		err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held,
				extack);
899
	if (err < 0)
900
		goto err_mod;
L
Linus Torvalds 已提交
901

902 903
	if (!name && tb[TCA_ACT_COOKIE])
		tcf_set_action_cookie(&a->act_cookie, cookie);
904

L
Linus Torvalds 已提交
905
	/* module count goes up only when brand new policy is created
E
Eric Dumazet 已提交
906 907 908
	 * if it exists and is only bound to in a_o->init() then
	 * ACT_P_CREATED is not returned (a zero is).
	 */
909
	if (err != ACT_P_CREATED)
L
Linus Torvalds 已提交
910 911
		module_put(a_o->owner);

912 913 914
	if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN)) {
		err = tcf_action_goto_chain_init(a, tp);
		if (err) {
915
			tcf_action_destroy_1(a, bind);
916
			NL_SET_ERR_MSG(extack, "Failed to init TC action chain");
917 918 919 920
			return ERR_PTR(err);
		}
	}

921
	if (!tcf_action_valid(a->tcfa_action)) {
922 923 924
		tcf_action_destroy_1(a, bind);
		NL_SET_ERR_MSG(extack, "Invalid control action value");
		return ERR_PTR(-EINVAL);
925 926
	}

L
Linus Torvalds 已提交
927 928 929 930 931
	return a;

err_mod:
	module_put(a_o->owner);
err_out:
932 933 934 935
	if (cookie) {
		kfree(cookie->data);
		kfree(cookie);
	}
936
	return ERR_PTR(err);
L
Linus Torvalds 已提交
937 938
}

939 940
/* Returns numbers of initialized actions or negative error. */

941 942
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
		    struct nlattr *est, char *name, int ovr, int bind,
943
		    struct tc_action *actions[], size_t *attr_size,
944
		    bool rtnl_held, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
945
{
E
Eric Dumazet 已提交
946
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
947
	struct tc_action *act;
948
	size_t sz = 0;
949
	int err;
L
Linus Torvalds 已提交
950 951
	int i;

952
	err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
953
	if (err < 0)
954
		return err;
L
Linus Torvalds 已提交
955

956
	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
957
		act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
958
					rtnl_held, extack);
959 960
		if (IS_ERR(act)) {
			err = PTR_ERR(act);
L
Linus Torvalds 已提交
961
			goto err;
962
		}
963
		act->order = i;
964
		sz += tcf_action_fill_size(act);
965 966
		/* Start from index 0 */
		actions[i - 1] = act;
L
Linus Torvalds 已提交
967
	}
968

969
	*attr_size = tcf_action_full_attrs_size(sz);
970
	return i - 1;
L
Linus Torvalds 已提交
971 972

err:
973 974
	tcf_action_destroy(actions, bind);
	return err;
L
Linus Torvalds 已提交
975 976
}

977
int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
L
Linus Torvalds 已提交
978 979 980 981
			  int compat_mode)
{
	int err = 0;
	struct gnet_dump d;
982

983
	if (p == NULL)
L
Linus Torvalds 已提交
984 985 986
		goto errout;

	/* compat_mode being true specifies a call that is supposed
987
	 * to add additional backward compatibility statistic TLVs.
L
Linus Torvalds 已提交
988 989
	 */
	if (compat_mode) {
990
		if (p->type == TCA_OLD_COMPAT)
L
Linus Torvalds 已提交
991
			err = gnet_stats_start_copy_compat(skb, 0,
992 993
							   TCA_STATS,
							   TCA_XSTATS,
994
							   &p->tcfa_lock, &d,
995
							   TCA_PAD);
L
Linus Torvalds 已提交
996 997 998 999
		else
			return 0;
	} else
		err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
1000
					    &p->tcfa_lock, &d, TCA_ACT_PAD);
L
Linus Torvalds 已提交
1001 1002 1003 1004

	if (err < 0)
		goto errout;

1005
	if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
1006 1007
	    gnet_stats_copy_basic_hw(NULL, &d, p->cpu_bstats_hw,
				     &p->tcfa_bstats_hw) < 0 ||
1008
	    gnet_stats_copy_rate_est(&d, &p->tcfa_rate_est) < 0 ||
1009
	    gnet_stats_copy_queue(&d, p->cpu_qstats,
1010 1011
				  &p->tcfa_qstats,
				  p->tcfa_qstats.qlen) < 0)
L
Linus Torvalds 已提交
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
		goto errout;

	if (gnet_stats_finish_copy(&d) < 0)
		goto errout;

	return 0;

errout:
	return -1;
}

1023
static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[],
1024 1025
			u32 portid, u32 seq, u16 flags, int event, int bind,
			int ref)
L
Linus Torvalds 已提交
1026 1027 1028
{
	struct tcamsg *t;
	struct nlmsghdr *nlh;
1029
	unsigned char *b = skb_tail_pointer(skb);
1030
	struct nlattr *nest;
L
Linus Torvalds 已提交
1031

1032
	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*t), flags);
1033 1034 1035
	if (!nlh)
		goto out_nlmsg_trim;
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1036
	t->tca_family = AF_UNSPEC;
1037 1038
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
1039

1040
	nest = nla_nest_start(skb, TCA_ACT_TAB);
1041
	if (!nest)
1042
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
1043

1044
	if (tcf_action_dump(skb, actions, bind, ref) < 0)
1045
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
1046

1047
	nla_nest_end(skb, nest);
1048

1049
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
L
Linus Torvalds 已提交
1050 1051
	return skb->len;

1052
out_nlmsg_trim:
1053
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1054 1055 1056 1057
	return -1;
}

static int
1058
tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
1059
	       struct tc_action *actions[], int event,
1060
	       struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1061 1062 1063 1064 1065 1066
{
	struct sk_buff *skb;

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
	if (!skb)
		return -ENOBUFS;
1067
	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
1068
			 0, 1) <= 0) {
1069
		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
L
Linus Torvalds 已提交
1070 1071 1072
		kfree_skb(skb);
		return -EINVAL;
	}
1073

1074
	return rtnl_unicast(skb, net, portid);
L
Linus Torvalds 已提交
1075 1076
}

1077
static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
1078 1079
					  struct nlmsghdr *n, u32 portid,
					  struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1080
{
E
Eric Dumazet 已提交
1081
	struct nlattr *tb[TCA_ACT_MAX + 1];
1082
	const struct tc_action_ops *ops;
L
Linus Torvalds 已提交
1083 1084
	struct tc_action *a;
	int index;
1085
	int err;
L
Linus Torvalds 已提交
1086

1087
	err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
1088
	if (err < 0)
1089
		goto err_out;
L
Linus Torvalds 已提交
1090

1091
	err = -EINVAL;
1092
	if (tb[TCA_ACT_INDEX] == NULL ||
1093 1094
	    nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) {
		NL_SET_ERR_MSG(extack, "Invalid TC action index value");
1095
		goto err_out;
1096
	}
1097
	index = nla_get_u32(tb[TCA_ACT_INDEX]);
L
Linus Torvalds 已提交
1098

1099
	err = -EINVAL;
1100
	ops = tc_lookup_action(tb[TCA_ACT_KIND]);
1101
	if (!ops) { /* could happen in batch of actions */
1102
		NL_SET_ERR_MSG(extack, "Specified TC action kind not found");
1103
		goto err_out;
1104
	}
1105
	err = -ENOENT;
1106 1107
	if (ops->lookup(net, &a, index) == 0) {
		NL_SET_ERR_MSG(extack, "TC action with specified index not found");
L
Linus Torvalds 已提交
1108
		goto err_mod;
1109
	}
L
Linus Torvalds 已提交
1110

1111
	module_put(ops->owner);
L
Linus Torvalds 已提交
1112
	return a;
1113

L
Linus Torvalds 已提交
1114
err_mod:
1115
	module_put(ops->owner);
1116 1117
err_out:
	return ERR_PTR(err);
L
Linus Torvalds 已提交
1118 1119
}

1120
static int tca_action_flush(struct net *net, struct nlattr *nla,
1121 1122
			    struct nlmsghdr *n, u32 portid,
			    struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1123 1124 1125 1126 1127 1128
{
	struct sk_buff *skb;
	unsigned char *b;
	struct nlmsghdr *nlh;
	struct tcamsg *t;
	struct netlink_callback dcb;
1129
	struct nlattr *nest;
E
Eric Dumazet 已提交
1130
	struct nlattr *tb[TCA_ACT_MAX + 1];
1131
	const struct tc_action_ops *ops;
1132
	struct nlattr *kind;
1133
	int err = -ENOMEM;
L
Linus Torvalds 已提交
1134 1135

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1136
	if (!skb)
1137
		return err;
L
Linus Torvalds 已提交
1138

1139
	b = skb_tail_pointer(skb);
L
Linus Torvalds 已提交
1140

1141
	err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
1142
	if (err < 0)
L
Linus Torvalds 已提交
1143 1144
		goto err_out;

1145
	err = -EINVAL;
1146
	kind = tb[TCA_ACT_KIND];
1147
	ops = tc_lookup_action(kind);
1148 1149
	if (!ops) { /*some idjot trying to flush unknown action */
		NL_SET_ERR_MSG(extack, "Cannot flush unknown TC action");
L
Linus Torvalds 已提交
1150
		goto err_out;
1151
	}
L
Linus Torvalds 已提交
1152

1153 1154
	nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
			sizeof(*t), 0);
1155 1156
	if (!nlh) {
		NL_SET_ERR_MSG(extack, "Failed to create TC action flush notification");
1157
		goto out_module_put;
1158
	}
1159
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1160
	t->tca_family = AF_UNSPEC;
1161 1162
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
L
Linus Torvalds 已提交
1163

1164
	nest = nla_nest_start(skb, TCA_ACT_TAB);
1165 1166
	if (!nest) {
		NL_SET_ERR_MSG(extack, "Failed to add new netlink message");
1167
		goto out_module_put;
1168
	}
L
Linus Torvalds 已提交
1169

1170
	err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops, extack);
1171 1172
	if (err <= 0) {
		nla_nest_cancel(skb, nest);
1173
		goto out_module_put;
1174
	}
L
Linus Torvalds 已提交
1175

1176
	nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
1177

1178
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
L
Linus Torvalds 已提交
1179
	nlh->nlmsg_flags |= NLM_F_ROOT;
1180
	module_put(ops->owner);
1181
	err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
E
Eric Dumazet 已提交
1182
			     n->nlmsg_flags & NLM_F_ECHO);
L
Linus Torvalds 已提交
1183 1184
	if (err > 0)
		return 0;
1185 1186
	if (err < 0)
		NL_SET_ERR_MSG(extack, "Failed to send TC action flush notification");
L
Linus Torvalds 已提交
1187 1188 1189

	return err;

1190
out_module_put:
1191
	module_put(ops->owner);
L
Linus Torvalds 已提交
1192 1193 1194 1195 1196
err_out:
	kfree_skb(skb);
	return err;
}

1197
static int tcf_action_delete(struct net *net, struct tc_action *actions[])
1198
{
1199
	int i;
1200

1201 1202
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		struct tc_action *a = actions[i];
1203 1204 1205 1206
		const struct tc_action_ops *ops = a->ops;
		/* Actions can be deleted concurrently so we must save their
		 * type and id to search again after reference is released.
		 */
1207 1208
		struct tcf_idrinfo *idrinfo = a->idrinfo;
		u32 act_index = a->tcfa_index;
1209

1210
		actions[i] = NULL;
1211 1212 1213 1214
		if (tcf_action_put(a)) {
			/* last reference, action was deleted concurrently */
			module_put(ops->owner);
		} else  {
1215 1216
			int ret;

1217
			/* now do the delete */
1218
			ret = tcf_idr_delete_index(idrinfo, act_index);
1219
			if (ret < 0)
1220 1221 1222 1223 1224 1225
				return ret;
		}
	}
	return 0;
}

1226
static int
1227
tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
1228
	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
1229 1230 1231 1232
{
	int ret;
	struct sk_buff *skb;

1233 1234
	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
			GFP_KERNEL);
1235 1236 1237 1238
	if (!skb)
		return -ENOBUFS;

	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
1239
			 0, 2) <= 0) {
1240
		NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
1241 1242 1243 1244 1245
		kfree_skb(skb);
		return -EINVAL;
	}

	/* now do the delete */
1246
	ret = tcf_action_delete(net, actions);
1247
	if (ret < 0) {
1248
		NL_SET_ERR_MSG(extack, "Failed to delete TC action");
1249 1250 1251
		kfree_skb(skb);
		return ret;
	}
1252 1253 1254 1255 1256 1257 1258 1259

	ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
			     n->nlmsg_flags & NLM_F_ECHO);
	if (ret > 0)
		return 0;
	return ret;
}

L
Linus Torvalds 已提交
1260
static int
1261
tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
1262
	      u32 portid, int event, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1263
{
1264
	int i, ret;
E
Eric Dumazet 已提交
1265
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
1266
	struct tc_action *act;
1267
	size_t attr_size = 0;
1268
	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
L
Linus Torvalds 已提交
1269

1270
	ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
1271 1272
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
1273

E
Eric Dumazet 已提交
1274
	if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
1275
		if (tb[1])
1276
			return tca_action_flush(net, tb[1], n, portid, extack);
1277

1278
		NL_SET_ERR_MSG(extack, "Invalid netlink attributes while flushing TC action");
1279
		return -EINVAL;
L
Linus Torvalds 已提交
1280 1281
	}

1282
	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
1283
		act = tcf_action_get_1(net, tb[i], n, portid, extack);
1284 1285
		if (IS_ERR(act)) {
			ret = PTR_ERR(act);
L
Linus Torvalds 已提交
1286
			goto err;
1287
		}
1288
		act->order = i;
1289
		attr_size += tcf_action_fill_size(act);
1290
		actions[i - 1] = act;
L
Linus Torvalds 已提交
1291
	}
1292 1293

	attr_size = tcf_action_full_attrs_size(attr_size);
L
Linus Torvalds 已提交
1294 1295

	if (event == RTM_GETACTION)
1296
		ret = tcf_get_notify(net, portid, n, actions, event, extack);
L
Linus Torvalds 已提交
1297
	else { /* delete */
1298
		ret = tcf_del_notify(net, n, actions, portid, attr_size, extack);
1299
		if (ret)
L
Linus Torvalds 已提交
1300
			goto err;
1301
		return 0;
L
Linus Torvalds 已提交
1302 1303
	}
err:
1304
	tcf_action_put_many(actions);
L
Linus Torvalds 已提交
1305 1306 1307
	return ret;
}

1308
static int
1309
tcf_add_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
1310
	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1311 1312 1313 1314
{
	struct sk_buff *skb;
	int err = 0;

1315 1316
	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
			GFP_KERNEL);
L
Linus Torvalds 已提交
1317 1318 1319
	if (!skb)
		return -ENOBUFS;

1320 1321
	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
			 RTM_NEWACTION, 0, 0) <= 0) {
1322
		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
1323 1324 1325
		kfree_skb(skb);
		return -EINVAL;
	}
1326

1327 1328
	err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
			     n->nlmsg_flags & NLM_F_ECHO);
L
Linus Torvalds 已提交
1329 1330 1331 1332 1333
	if (err > 0)
		err = 0;
	return err;
}

J
Jamal Hadi Salim 已提交
1334
static int tcf_action_add(struct net *net, struct nlattr *nla,
1335 1336
			  struct nlmsghdr *n, u32 portid, int ovr,
			  struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1337
{
1338
	size_t attr_size = 0;
L
Linus Torvalds 已提交
1339
	int ret = 0;
1340
	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
L
Linus Torvalds 已提交
1341

1342
	ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, actions,
1343
			      &attr_size, true, extack);
1344
	if (ret < 0)
1345
		return ret;
1346
	ret = tcf_add_notify(net, n, actions, portid, attr_size, extack);
1347
	if (ovr)
1348
		tcf_action_put_many(actions);
L
Linus Torvalds 已提交
1349

1350
	return ret;
L
Linus Torvalds 已提交
1351 1352
}

1353 1354 1355 1356
static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;
static const struct nla_policy tcaa_policy[TCA_ROOT_MAX + 1] = {
	[TCA_ROOT_FLAGS] = { .type = NLA_BITFIELD32,
			     .validation_data = &tcaa_root_flags_allowed },
1357
	[TCA_ROOT_TIME_DELTA]      = { .type = NLA_U32 },
1358 1359
};

1360 1361
static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
			 struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1362
{
1363
	struct net *net = sock_net(skb->sk);
1364
	struct nlattr *tca[TCA_ROOT_MAX + 1];
1365
	u32 portid = skb ? NETLINK_CB(skb).portid : 0;
L
Linus Torvalds 已提交
1366 1367
	int ret = 0, ovr = 0;

1368 1369
	if ((n->nlmsg_type != RTM_GETACTION) &&
	    !netlink_capable(skb, CAP_NET_ADMIN))
1370 1371
		return -EPERM;

1372
	ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ROOT_MAX, NULL,
1373
			  extack);
1374 1375 1376 1377
	if (ret < 0)
		return ret;

	if (tca[TCA_ACT_TAB] == NULL) {
1378
		NL_SET_ERR_MSG(extack, "Netlink action attributes missing");
L
Linus Torvalds 已提交
1379 1380 1381
		return -EINVAL;
	}

E
Eric Dumazet 已提交
1382
	/* n->nlmsg_flags & NLM_F_CREATE */
L
Linus Torvalds 已提交
1383 1384 1385
	switch (n->nlmsg_type) {
	case RTM_NEWACTION:
		/* we are going to assume all other flags
L
Lucas De Marchi 已提交
1386
		 * imply create only if it doesn't exist
L
Linus Torvalds 已提交
1387 1388 1389 1390
		 * Note that CREATE | EXCL implies that
		 * but since we want avoid ambiguity (eg when flags
		 * is zero) then just set this
		 */
E
Eric Dumazet 已提交
1391
		if (n->nlmsg_flags & NLM_F_REPLACE)
L
Linus Torvalds 已提交
1392 1393
			ovr = 1;
replay:
1394 1395
		ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr,
				     extack);
L
Linus Torvalds 已提交
1396 1397 1398 1399
		if (ret == -EAGAIN)
			goto replay;
		break;
	case RTM_DELACTION:
1400
		ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
1401
				    portid, RTM_DELACTION, extack);
L
Linus Torvalds 已提交
1402 1403
		break;
	case RTM_GETACTION:
1404
		ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
1405
				    portid, RTM_GETACTION, extack);
L
Linus Torvalds 已提交
1406 1407 1408 1409 1410 1411 1412 1413
		break;
	default:
		BUG();
	}

	return ret;
}

1414
static struct nlattr *find_dump_kind(struct nlattr **nla)
L
Linus Torvalds 已提交
1415
{
E
Eric Dumazet 已提交
1416
	struct nlattr *tb1, *tb2[TCA_ACT_MAX + 1];
1417 1418
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
	struct nlattr *kind;
L
Linus Torvalds 已提交
1419

1420
	tb1 = nla[TCA_ACT_TAB];
L
Linus Torvalds 已提交
1421 1422 1423
	if (tb1 == NULL)
		return NULL;

1424
	if (nla_parse(tb, TCA_ACT_MAX_PRIO, nla_data(tb1),
1425
		      NLMSG_ALIGN(nla_len(tb1)), NULL, NULL) < 0)
L
Linus Torvalds 已提交
1426 1427
		return NULL;

1428 1429
	if (tb[1] == NULL)
		return NULL;
1430
	if (nla_parse_nested(tb2, TCA_ACT_MAX, tb[1], NULL, NULL) < 0)
L
Linus Torvalds 已提交
1431
		return NULL;
1432
	kind = tb2[TCA_ACT_KIND];
L
Linus Torvalds 已提交
1433

1434
	return kind;
L
Linus Torvalds 已提交
1435 1436
}

J
Jamal Hadi Salim 已提交
1437
static int tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
L
Linus Torvalds 已提交
1438
{
1439
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
1440
	struct nlmsghdr *nlh;
1441
	unsigned char *b = skb_tail_pointer(skb);
1442
	struct nlattr *nest;
L
Linus Torvalds 已提交
1443 1444
	struct tc_action_ops *a_o;
	int ret = 0;
1445
	struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh);
1446 1447
	struct nlattr *tb[TCA_ROOT_MAX + 1];
	struct nlattr *count_attr = NULL;
1448
	unsigned long jiffy_since = 0;
1449 1450
	struct nlattr *kind = NULL;
	struct nla_bitfield32 bf;
1451
	u32 msecs_since = 0;
1452 1453 1454 1455 1456 1457
	u32 act_count = 0;

	ret = nlmsg_parse(cb->nlh, sizeof(struct tcamsg), tb, TCA_ROOT_MAX,
			  tcaa_policy, NULL);
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
1458

1459
	kind = find_dump_kind(tb);
L
Linus Torvalds 已提交
1460
	if (kind == NULL) {
1461
		pr_info("tc_dump_action: action bad kind\n");
L
Linus Torvalds 已提交
1462 1463 1464
		return 0;
	}

1465
	a_o = tc_lookup_action(kind);
E
Eric Dumazet 已提交
1466
	if (a_o == NULL)
L
Linus Torvalds 已提交
1467 1468
		return 0;

1469 1470 1471 1472 1473 1474
	cb->args[2] = 0;
	if (tb[TCA_ROOT_FLAGS]) {
		bf = nla_get_bitfield32(tb[TCA_ROOT_FLAGS]);
		cb->args[2] = bf.value;
	}

1475 1476 1477 1478
	if (tb[TCA_ROOT_TIME_DELTA]) {
		msecs_since = nla_get_u32(tb[TCA_ROOT_TIME_DELTA]);
	}

1479
	nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
1480 1481 1482
			cb->nlh->nlmsg_type, sizeof(*t), 0);
	if (!nlh)
		goto out_module_put;
1483

1484 1485 1486
	if (msecs_since)
		jiffy_since = jiffies - msecs_to_jiffies(msecs_since);

1487
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1488
	t->tca_family = AF_UNSPEC;
1489 1490
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
1491
	cb->args[3] = jiffy_since;
1492 1493 1494
	count_attr = nla_reserve(skb, TCA_ROOT_COUNT, sizeof(u32));
	if (!count_attr)
		goto out_module_put;
L
Linus Torvalds 已提交
1495

1496 1497
	nest = nla_nest_start(skb, TCA_ACT_TAB);
	if (nest == NULL)
1498
		goto out_module_put;
L
Linus Torvalds 已提交
1499

1500
	ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
L
Linus Torvalds 已提交
1501
	if (ret < 0)
1502
		goto out_module_put;
L
Linus Torvalds 已提交
1503 1504

	if (ret > 0) {
1505
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
1506
		ret = skb->len;
1507 1508 1509
		act_count = cb->args[1];
		memcpy(nla_data(count_attr), &act_count, sizeof(u32));
		cb->args[1] = 0;
L
Linus Torvalds 已提交
1510
	} else
1511
		nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1512

1513
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
1514
	if (NETLINK_CB(cb->skb).portid && ret)
L
Linus Torvalds 已提交
1515 1516 1517 1518
		nlh->nlmsg_flags |= NLM_F_MULTI;
	module_put(a_o->owner);
	return skb->len;

1519
out_module_put:
L
Linus Torvalds 已提交
1520
	module_put(a_o->owner);
1521
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1522 1523 1524
	return skb->len;
}

1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573
struct tcf_action_net {
	struct rhashtable egdev_ht;
};

static unsigned int tcf_action_net_id;

struct tcf_action_egdev_cb {
	struct list_head list;
	tc_setup_cb_t *cb;
	void *cb_priv;
};

struct tcf_action_egdev {
	struct rhash_head ht_node;
	const struct net_device *dev;
	unsigned int refcnt;
	struct list_head cb_list;
};

static const struct rhashtable_params tcf_action_egdev_ht_params = {
	.key_offset = offsetof(struct tcf_action_egdev, dev),
	.head_offset = offsetof(struct tcf_action_egdev, ht_node),
	.key_len = sizeof(const struct net_device *),
};

static struct tcf_action_egdev *
tcf_action_egdev_lookup(const struct net_device *dev)
{
	struct net *net = dev_net(dev);
	struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);

	return rhashtable_lookup_fast(&tan->egdev_ht, &dev,
				      tcf_action_egdev_ht_params);
}

static struct tcf_action_egdev *
tcf_action_egdev_get(const struct net_device *dev)
{
	struct tcf_action_egdev *egdev;
	struct tcf_action_net *tan;

	egdev = tcf_action_egdev_lookup(dev);
	if (egdev)
		goto inc_ref;

	egdev = kzalloc(sizeof(*egdev), GFP_KERNEL);
	if (!egdev)
		return NULL;
	INIT_LIST_HEAD(&egdev->cb_list);
1574
	egdev->dev = dev;
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737
	tan = net_generic(dev_net(dev), tcf_action_net_id);
	rhashtable_insert_fast(&tan->egdev_ht, &egdev->ht_node,
			       tcf_action_egdev_ht_params);

inc_ref:
	egdev->refcnt++;
	return egdev;
}

static void tcf_action_egdev_put(struct tcf_action_egdev *egdev)
{
	struct tcf_action_net *tan;

	if (--egdev->refcnt)
		return;
	tan = net_generic(dev_net(egdev->dev), tcf_action_net_id);
	rhashtable_remove_fast(&tan->egdev_ht, &egdev->ht_node,
			       tcf_action_egdev_ht_params);
	kfree(egdev);
}

static struct tcf_action_egdev_cb *
tcf_action_egdev_cb_lookup(struct tcf_action_egdev *egdev,
			   tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev_cb *egdev_cb;

	list_for_each_entry(egdev_cb, &egdev->cb_list, list)
		if (egdev_cb->cb == cb && egdev_cb->cb_priv == cb_priv)
			return egdev_cb;
	return NULL;
}

static int tcf_action_egdev_cb_call(struct tcf_action_egdev *egdev,
				    enum tc_setup_type type,
				    void *type_data, bool err_stop)
{
	struct tcf_action_egdev_cb *egdev_cb;
	int ok_count = 0;
	int err;

	list_for_each_entry(egdev_cb, &egdev->cb_list, list) {
		err = egdev_cb->cb(type, type_data, egdev_cb->cb_priv);
		if (err) {
			if (err_stop)
				return err;
		} else {
			ok_count++;
		}
	}
	return ok_count;
}

static int tcf_action_egdev_cb_add(struct tcf_action_egdev *egdev,
				   tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev_cb *egdev_cb;

	egdev_cb = tcf_action_egdev_cb_lookup(egdev, cb, cb_priv);
	if (WARN_ON(egdev_cb))
		return -EEXIST;
	egdev_cb = kzalloc(sizeof(*egdev_cb), GFP_KERNEL);
	if (!egdev_cb)
		return -ENOMEM;
	egdev_cb->cb = cb;
	egdev_cb->cb_priv = cb_priv;
	list_add(&egdev_cb->list, &egdev->cb_list);
	return 0;
}

static void tcf_action_egdev_cb_del(struct tcf_action_egdev *egdev,
				    tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev_cb *egdev_cb;

	egdev_cb = tcf_action_egdev_cb_lookup(egdev, cb, cb_priv);
	if (WARN_ON(!egdev_cb))
		return;
	list_del(&egdev_cb->list);
	kfree(egdev_cb);
}

static int __tc_setup_cb_egdev_register(const struct net_device *dev,
					tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev *egdev = tcf_action_egdev_get(dev);
	int err;

	if (!egdev)
		return -ENOMEM;
	err = tcf_action_egdev_cb_add(egdev, cb, cb_priv);
	if (err)
		goto err_cb_add;
	return 0;

err_cb_add:
	tcf_action_egdev_put(egdev);
	return err;
}
int tc_setup_cb_egdev_register(const struct net_device *dev,
			       tc_setup_cb_t *cb, void *cb_priv)
{
	int err;

	rtnl_lock();
	err = __tc_setup_cb_egdev_register(dev, cb, cb_priv);
	rtnl_unlock();
	return err;
}
EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_register);

static void __tc_setup_cb_egdev_unregister(const struct net_device *dev,
					   tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev *egdev = tcf_action_egdev_lookup(dev);

	if (WARN_ON(!egdev))
		return;
	tcf_action_egdev_cb_del(egdev, cb, cb_priv);
	tcf_action_egdev_put(egdev);
}
void tc_setup_cb_egdev_unregister(const struct net_device *dev,
				  tc_setup_cb_t *cb, void *cb_priv)
{
	rtnl_lock();
	__tc_setup_cb_egdev_unregister(dev, cb, cb_priv);
	rtnl_unlock();
}
EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_unregister);

int tc_setup_cb_egdev_call(const struct net_device *dev,
			   enum tc_setup_type type, void *type_data,
			   bool err_stop)
{
	struct tcf_action_egdev *egdev = tcf_action_egdev_lookup(dev);

	if (!egdev)
		return 0;
	return tcf_action_egdev_cb_call(egdev, type, type_data, err_stop);
}
EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_call);

static __net_init int tcf_action_net_init(struct net *net)
{
	struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);

	return rhashtable_init(&tan->egdev_ht, &tcf_action_egdev_ht_params);
}

static void __net_exit tcf_action_net_exit(struct net *net)
{
	struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);

	rhashtable_destroy(&tan->egdev_ht);
}

static struct pernet_operations tcf_action_net_ops = {
	.init = tcf_action_net_init,
	.exit = tcf_action_net_exit,
	.id = &tcf_action_net_id,
	.size = sizeof(struct tcf_action_net),
};

L
Linus Torvalds 已提交
1738 1739
static int __init tc_action_init(void)
{
1740 1741 1742 1743 1744 1745
	int err;

	err = register_pernet_subsys(&tcf_action_net_ops);
	if (err)
		return err;

1746 1747
	rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL, 0);
	rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL, 0);
1748
	rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,
1749
		      0);
L
Linus Torvalds 已提交
1750 1751 1752 1753 1754

	return 0;
}

subsys_initcall(tc_action_init);