act_api.c 36.2 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9 10 11
/*
 * net/sched/act_api.c	Packet action API.
 *
 * Author:	Jamal Hadi Salim
 */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
12
#include <linux/slab.h>
L
Linus Torvalds 已提交
13 14 15
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/kmod.h>
16
#include <linux/err.h>
17
#include <linux/module.h>
18 19
#include <net/net_namespace.h>
#include <net/sock.h>
L
Linus Torvalds 已提交
20
#include <net/sch_generic.h>
21
#include <net/pkt_cls.h>
L
Linus Torvalds 已提交
22
#include <net/act_api.h>
23
#include <net/netlink.h>
L
Linus Torvalds 已提交
24

25 26 27
static void tcf_action_goto_chain_exec(const struct tc_action *a,
				       struct tcf_result *res)
{
28
	const struct tcf_chain *chain = rcu_dereference_bh(a->goto_chain);
29 30 31 32

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

33 34 35 36 37 38 39 40 41 42 43 44 45
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;

46
	old = xchg((__force struct tc_cookie **)old_cookie, new_cookie);
47 48 49 50
	if (old)
		call_rcu(&old->rcu, tcf_free_cookie_rcu);
}

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
int tcf_action_check_ctrlact(int action, struct tcf_proto *tp,
			     struct tcf_chain **newchain,
			     struct netlink_ext_ack *extack)
{
	int opcode = TC_ACT_EXT_OPCODE(action), ret = -EINVAL;
	u32 chain_index;

	if (!opcode)
		ret = action > TC_ACT_VALUE_MAX ? -EINVAL : 0;
	else if (opcode <= TC_ACT_EXT_OPCODE_MAX || action == TC_ACT_UNSPEC)
		ret = 0;
	if (ret) {
		NL_SET_ERR_MSG(extack, "invalid control action");
		goto end;
	}

	if (TC_ACT_EXT_CMP(action, TC_ACT_GOTO_CHAIN)) {
		chain_index = action & TC_ACT_EXT_VAL_MASK;
		if (!tp || !newchain) {
			ret = -EINVAL;
			NL_SET_ERR_MSG(extack,
				       "can't goto NULL proto/chain");
			goto end;
		}
		*newchain = tcf_chain_get_by_act(tp->chain->block, chain_index);
		if (!*newchain) {
			ret = -ENOMEM;
			NL_SET_ERR_MSG(extack,
				       "can't allocate goto_chain");
		}
	}
end:
	return ret;
}
EXPORT_SYMBOL(tcf_action_check_ctrlact);

struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
88
					 struct tcf_chain *goto_chain)
89 90
{
	a->tcfa_action = action;
91 92
	rcu_swap_protected(a->goto_chain, goto_chain, 1);
	return goto_chain;
93 94 95
}
EXPORT_SYMBOL(tcf_action_set_ctrlact);

C
Cong Wang 已提交
96 97 98 99 100 101
/* 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)
102
{
103
	struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
104

105
	free_percpu(p->cpu_bstats);
106
	free_percpu(p->cpu_bstats_hw);
107
	free_percpu(p->cpu_qstats);
108

109
	tcf_set_action_cookie(&p->act_cookie, NULL);
110 111
	if (chain)
		tcf_chain_put_by_act(chain);
112

113 114 115
	kfree(p);
}

116
static void tcf_action_cleanup(struct tc_action *p)
117
{
118 119 120
	if (p->ops->cleanup)
		p->ops->cleanup(p);

121
	gen_kill_estimator(&p->tcfa_rate_est);
C
Cong Wang 已提交
122
	free_tcf(p);
123 124
}

125 126 127 128
static int __tcf_action_put(struct tc_action *p, bool bind)
{
	struct tcf_idrinfo *idrinfo = p->idrinfo;

129
	if (refcount_dec_and_mutex_lock(&p->tcfa_refcnt, &idrinfo->lock)) {
130 131 132
		if (bind)
			atomic_dec(&p->tcfa_bindcnt);
		idr_remove(&idrinfo->action_idr, p->tcfa_index);
133
		mutex_unlock(&idrinfo->lock);
134 135 136 137 138 139 140 141 142 143 144

		tcf_action_cleanup(p);
		return 1;
	}

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

	return 0;
}

145
int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
146 147 148
{
	int ret = 0;

149 150 151 152 153 154 155 156 157 158 159 160
	/* 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.
	 */
161
	if (p) {
162
		if (!bind && strict && atomic_read(&p->tcfa_bindcnt) > 0)
163
			return -EPERM;
164

165
		if (__tcf_action_put(p, bind))
166
			ret = ACT_P_DELETED;
167
	}
168

169 170
	return ret;
}
171
EXPORT_SYMBOL(__tcf_idr_release);
172

173 174
static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
{
175
	struct tc_cookie *act_cookie;
176 177
	u32 cookie_len = 0;

178 179 180 181 182 183
	rcu_read_lock();
	act_cookie = rcu_dereference(act->act_cookie);

	if (act_cookie)
		cookie_len = nla_total_size(act_cookie->len);
	rcu_read_unlock();
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213

	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;
}

214
static int tcf_dump_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
215
			   struct netlink_callback *cb)
216
{
217
	int err = 0, index = -1, s_i = 0, n_i = 0;
218
	u32 act_flags = cb->args[2];
219
	unsigned long jiffy_since = cb->args[3];
220
	struct nlattr *nest;
221 222 223
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	unsigned long id = 1;
224

225
	mutex_lock(&idrinfo->lock);
226 227 228

	s_i = cb->args[0];

229
	idr_for_each_entry_ul(idr, p, id) {
230 231 232 233 234 235 236 237 238
		index++;
		if (index < s_i)
			continue;

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

239
		nest = nla_nest_start_noflag(skb, n_i);
240 241
		if (!nest) {
			index--;
242
			goto nla_put_failure;
243
		}
244 245 246 247 248
		err = tcf_action_dump_1(skb, p, 0, 0);
		if (err < 0) {
			index--;
			nlmsg_trim(skb, nest);
			goto done;
249
		}
250 251 252 253 254
		nla_nest_end(skb, nest);
		n_i++;
		if (!(act_flags & TCA_FLAG_LARGE_DUMP_ON) &&
		    n_i >= TCA_ACT_MAX_PRIO)
			goto done;
255 256
	}
done:
257 258 259
	if (index >= 0)
		cb->args[0] = index + 1;

260
	mutex_unlock(&idrinfo->lock);
261 262 263 264
	if (n_i) {
		if (act_flags & TCA_FLAG_LARGE_DUMP_ON)
			cb->args[1] = n_i;
	}
265 266
	return n_i;

267
nla_put_failure:
268
	nla_nest_cancel(skb, nest);
269 270 271
	goto done;
}

272 273 274 275 276 277 278 279 280 281 282 283 284 285
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;
}

286
static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
287
			  const struct tc_action_ops *ops)
288
{
289
	struct nlattr *nest;
290
	int n_i = 0;
291
	int ret = -EINVAL;
292 293 294
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	unsigned long id = 1;
295

296
	nest = nla_nest_start_noflag(skb, 0);
297 298
	if (nest == NULL)
		goto nla_put_failure;
299
	if (nla_put_string(skb, TCA_KIND, ops->kind))
300
		goto nla_put_failure;
301

302
	mutex_lock(&idrinfo->lock);
303
	idr_for_each_entry_ul(idr, p, id) {
304
		ret = tcf_idr_release_unsafe(p);
305
		if (ret == ACT_P_DELETED) {
306
			module_put(ops->owner);
307 308
			n_i++;
		} else if (ret < 0) {
309
			mutex_unlock(&idrinfo->lock);
310
			goto nla_put_failure;
311 312
		}
	}
313
	mutex_unlock(&idrinfo->lock);
314

315 316
	if (nla_put_u32(skb, TCA_FCNT, n_i))
		goto nla_put_failure;
317
	nla_nest_end(skb, nest);
318 319

	return n_i;
320
nla_put_failure:
321
	nla_nest_cancel(skb, nest);
322
	return ret;
323 324
}

325 326
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
		       struct netlink_callback *cb, int type,
327 328
		       const struct tc_action_ops *ops,
		       struct netlink_ext_ack *extack)
329
{
330
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
331

332
	if (type == RTM_DELACTION) {
333
		return tcf_del_walker(idrinfo, skb, ops);
334
	} else if (type == RTM_GETACTION) {
335
		return tcf_dump_walker(idrinfo, skb, cb);
336
	} else {
337 338
		WARN(1, "tcf_generic_walker: unknown command %d\n", type);
		NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown command");
339 340 341
		return -EINVAL;
	}
}
342
EXPORT_SYMBOL(tcf_generic_walker);
343

344
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
345
{
346 347
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
	struct tc_action *p;
348

349
	mutex_lock(&idrinfo->lock);
350
	p = idr_find(&idrinfo->action_idr, index);
351
	if (IS_ERR(p))
352
		p = NULL;
353
	else if (p)
354
		refcount_inc(&p->tcfa_refcnt);
355
	mutex_unlock(&idrinfo->lock);
356

357 358 359 360 361
	if (p) {
		*a = p;
		return true;
	}
	return false;
362
}
363
EXPORT_SYMBOL(tcf_idr_search);
364

365
static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index)
366 367 368 369
{
	struct tc_action *p;
	int ret = 0;

370
	mutex_lock(&idrinfo->lock);
371 372
	p = idr_find(&idrinfo->action_idr, index);
	if (!p) {
373
		mutex_unlock(&idrinfo->lock);
374 375 376 377 378 379 380 381 382
		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));
383
			mutex_unlock(&idrinfo->lock);
384

385
			tcf_action_cleanup(p);
386 387 388 389 390 391 392 393
			module_put(owner);
			return 0;
		}
		ret = 0;
	} else {
		ret = -EPERM;
	}

394
	mutex_unlock(&idrinfo->lock);
395 396 397
	return ret;
}

398 399 400
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)
401
{
402
	struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
403
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
404
	int err = -ENOMEM;
405 406

	if (unlikely(!p))
407
		return -ENOMEM;
408
	refcount_set(&p->tcfa_refcnt, 1);
409
	if (bind)
410
		atomic_set(&p->tcfa_bindcnt, 1);
411

412 413
	if (cpustats) {
		p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
414
		if (!p->cpu_bstats)
415
			goto err1;
416 417 418
		p->cpu_bstats_hw = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
		if (!p->cpu_bstats_hw)
			goto err2;
419 420
		p->cpu_qstats = alloc_percpu(struct gnet_stats_queue);
		if (!p->cpu_qstats)
421
			goto err3;
422
	}
423
	spin_lock_init(&p->tcfa_lock);
424
	p->tcfa_index = index;
425 426 427
	p->tcfa_tm.install = jiffies;
	p->tcfa_tm.lastuse = jiffies;
	p->tcfa_tm.firstuse = 0;
428
	if (est) {
429 430 431
		err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
					&p->tcfa_rate_est,
					&p->tcfa_lock, NULL, est);
432
		if (err)
433
			goto err4;
434 435
	}

436
	p->idrinfo = idrinfo;
437 438
	p->ops = ops;
	*a = p;
439
	return 0;
440
err4:
441
	free_percpu(p->cpu_qstats);
442 443
err3:
	free_percpu(p->cpu_bstats_hw);
444 445 446 447 448
err2:
	free_percpu(p->cpu_bstats);
err1:
	kfree(p);
	return err;
449
}
450
EXPORT_SYMBOL(tcf_idr_create);
451

452
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
453
{
454
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
455

456
	mutex_lock(&idrinfo->lock);
457 458
	/* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
	WARN_ON(!IS_ERR(idr_replace(&idrinfo->action_idr, a, a->tcfa_index)));
459
	mutex_unlock(&idrinfo->lock);
460
}
461
EXPORT_SYMBOL(tcf_idr_insert);
L
Linus Torvalds 已提交
462

463 464 465 466 467 468
/* 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;

469
	mutex_lock(&idrinfo->lock);
470 471
	/* Remove ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
	WARN_ON(!IS_ERR(idr_remove(&idrinfo->action_idr, index)));
472
	mutex_unlock(&idrinfo->lock);
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
}
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:
490
	mutex_lock(&idrinfo->lock);
491 492 493 494 495 496
	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.
			 */
497
			mutex_unlock(&idrinfo->lock);
498 499 500 501 502 503 504 505 506 507 508 509
			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,
510
					    *index, GFP_KERNEL);
511 512 513 514 515 516 517 518
			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,
519
				    UINT_MAX, GFP_KERNEL);
520 521 522 523
		if (!ret)
			idr_replace(&idrinfo->action_idr, ERR_PTR(-EBUSY),
				    *index);
	}
524
	mutex_unlock(&idrinfo->lock);
525 526 527 528
	return ret;
}
EXPORT_SYMBOL(tcf_idr_check_alloc);

529 530
void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
			 struct tcf_idrinfo *idrinfo)
531
{
532 533 534 535
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	int ret;
	unsigned long id = 1;
536

537
	idr_for_each_entry_ul(idr, p, id) {
538 539 540 541 542
		ret = __tcf_idr_release(p, false, true);
		if (ret == ACT_P_DELETED)
			module_put(ops->owner);
		else if (ret < 0)
			return;
543
	}
544
	idr_destroy(&idrinfo->action_idr);
545
}
546
EXPORT_SYMBOL(tcf_idrinfo_destroy);
547

548
static LIST_HEAD(act_base);
L
Linus Torvalds 已提交
549 550
static DEFINE_RWLOCK(act_mod_lock);

551 552
int tcf_register_action(struct tc_action_ops *act,
			struct pernet_operations *ops)
L
Linus Torvalds 已提交
553
{
554
	struct tc_action_ops *a;
555
	int ret;
L
Linus Torvalds 已提交
556

557
	if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
558 559
		return -EINVAL;

560 561 562 563 564 565 566 567
	/* 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 已提交
568
	write_lock(&act_mod_lock);
569
	list_for_each_entry(a, &act_base, head) {
570
		if (act->id == a->id || (strcmp(act->kind, a->kind) == 0)) {
L
Linus Torvalds 已提交
571
			write_unlock(&act_mod_lock);
572
			unregister_pernet_subsys(ops);
L
Linus Torvalds 已提交
573 574 575
			return -EEXIST;
		}
	}
576
	list_add_tail(&act->head, &act_base);
L
Linus Torvalds 已提交
577
	write_unlock(&act_mod_lock);
578

L
Linus Torvalds 已提交
579 580
	return 0;
}
581
EXPORT_SYMBOL(tcf_register_action);
L
Linus Torvalds 已提交
582

583 584
int tcf_unregister_action(struct tc_action_ops *act,
			  struct pernet_operations *ops)
L
Linus Torvalds 已提交
585
{
586
	struct tc_action_ops *a;
L
Linus Torvalds 已提交
587 588 589
	int err = -ENOENT;

	write_lock(&act_mod_lock);
590 591 592 593
	list_for_each_entry(a, &act_base, head) {
		if (a == act) {
			list_del(&act->head);
			err = 0;
L
Linus Torvalds 已提交
594
			break;
595
		}
L
Linus Torvalds 已提交
596 597
	}
	write_unlock(&act_mod_lock);
598 599
	if (!err)
		unregister_pernet_subsys(ops);
L
Linus Torvalds 已提交
600 601
	return err;
}
602
EXPORT_SYMBOL(tcf_unregister_action);
L
Linus Torvalds 已提交
603 604 605 606

/* lookup by name */
static struct tc_action_ops *tc_lookup_action_n(char *kind)
{
607
	struct tc_action_ops *a, *res = NULL;
L
Linus Torvalds 已提交
608 609 610

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

623 624
/* lookup by nlattr */
static struct tc_action_ops *tc_lookup_action(struct nlattr *kind)
L
Linus Torvalds 已提交
625
{
626
	struct tc_action_ops *a, *res = NULL;
L
Linus Torvalds 已提交
627 628 629

	if (kind) {
		read_lock(&act_mod_lock);
630
		list_for_each_entry(a, &act_base, head) {
631
			if (nla_strcmp(kind, a->kind) == 0) {
632 633
				if (try_module_get(a->owner))
					res = a;
L
Linus Torvalds 已提交
634 635 636 637 638
				break;
			}
		}
		read_unlock(&act_mod_lock);
	}
639
	return res;
L
Linus Torvalds 已提交
640 641
}

642 643
/*TCA_ACT_MAX_PRIO is 32, there count upto 32 */
#define TCA_ACT_MAX_PRIO_MASK 0x1FF
644 645
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
		    int nr_actions, struct tcf_result *res)
L
Linus Torvalds 已提交
646
{
647 648
	u32 jmp_prgcnt = 0;
	u32 jmp_ttl = TCA_ACT_MAX_PRIO; /*matches actions per filter */
649 650
	int i;
	int ret = TC_ACT_OK;
L
Linus Torvalds 已提交
651

652 653 654
	if (skb_skip_tc_classify(skb))
		return TC_ACT_OK;

655
restart_act_graph:
656 657 658
	for (i = 0; i < nr_actions; i++) {
		const struct tc_action *a = actions[i];

659 660 661 662
		if (jmp_prgcnt > 0) {
			jmp_prgcnt -= 1;
			continue;
		}
L
Linus Torvalds 已提交
663
repeat:
664 665 666
		ret = a->ops->act(skb, a, res);
		if (ret == TC_ACT_REPEAT)
			goto repeat;	/* we need a ttl - JHS */
667

668
		if (TC_ACT_EXT_CMP(ret, TC_ACT_JUMP)) {
669 670 671 672 673 674 675 676 677 678 679
			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;
			}
680
		} else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) {
681 682 683 684
			if (unlikely(!rcu_access_pointer(a->goto_chain))) {
				net_warn_ratelimited("can't go to NULL chain!\n");
				return TC_ACT_SHOT;
			}
685
			tcf_action_goto_chain_exec(a, res);
686 687
		}

688
		if (ret != TC_ACT_PIPE)
689
			break;
L
Linus Torvalds 已提交
690
	}
691

L
Linus Torvalds 已提交
692 693
	return ret;
}
694
EXPORT_SYMBOL(tcf_action_exec);
L
Linus Torvalds 已提交
695

696
int tcf_action_destroy(struct tc_action *actions[], int bind)
L
Linus Torvalds 已提交
697
{
698
	const struct tc_action_ops *ops;
699 700
	struct tc_action *a;
	int ret = 0, i;
L
Linus Torvalds 已提交
701

702 703 704
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		a = actions[i];
		actions[i] = NULL;
705
		ops = a->ops;
706
		ret = __tcf_idr_release(a, bind, true);
707
		if (ret == ACT_P_DELETED)
708
			module_put(ops->owner);
709 710
		else if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
711
	}
712
	return ret;
L
Linus Torvalds 已提交
713 714
}

715 716 717 718 719 720 721
static int tcf_action_destroy_1(struct tc_action *a, int bind)
{
	struct tc_action *actions[] = { a, NULL };

	return tcf_action_destroy(actions, bind);
}

722 723 724 725 726
static int tcf_action_put(struct tc_action *p)
{
	return __tcf_action_put(p, false);
}

727
/* Put all actions in this array, skip those NULL's. */
728
static void tcf_action_put_many(struct tc_action *actions[])
729
{
730
	int i;
731

732
	for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
733
		struct tc_action *a = actions[i];
734
		const struct tc_action_ops *ops;
735

736 737 738
		if (!a)
			continue;
		ops = a->ops;
739 740 741 742 743
		if (tcf_action_put(a))
			module_put(ops->owner);
	}
}

L
Linus Torvalds 已提交
744 745 746 747 748 749 750 751 752 753
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;
754
	unsigned char *b = skb_tail_pointer(skb);
755
	struct nlattr *nest;
756
	struct tc_cookie *cookie;
L
Linus Torvalds 已提交
757

758 759
	if (nla_put_string(skb, TCA_KIND, a->ops->kind))
		goto nla_put_failure;
L
Linus Torvalds 已提交
760
	if (tcf_action_copy_stats(skb, a, 0))
761
		goto nla_put_failure;
762 763 764 765 766 767

	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();
768
			goto nla_put_failure;
769
		}
770
	}
771
	rcu_read_unlock();
772

773
	nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
774 775
	if (nest == NULL)
		goto nla_put_failure;
E
Eric Dumazet 已提交
776 777
	err = tcf_action_dump_old(skb, a, bind, ref);
	if (err > 0) {
778
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
779 780 781
		return err;
	}

782
nla_put_failure:
783
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
784 785
	return -1;
}
786
EXPORT_SYMBOL(tcf_action_dump_1);
L
Linus Torvalds 已提交
787

788
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[],
789
		    int bind, int ref)
L
Linus Torvalds 已提交
790 791
{
	struct tc_action *a;
792
	int err = -EINVAL, i;
793
	struct nlattr *nest;
L
Linus Torvalds 已提交
794

795 796
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		a = actions[i];
797
		nest = nla_nest_start_noflag(skb, i + 1);
798 799
		if (nest == NULL)
			goto nla_put_failure;
L
Linus Torvalds 已提交
800 801
		err = tcf_action_dump_1(skb, a, bind, ref);
		if (err < 0)
802
			goto errout;
803
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
804 805 806 807
	}

	return 0;

808
nla_put_failure:
809 810
	err = -EINVAL;
errout:
811
	nla_nest_cancel(skb, nest);
812
	return err;
L
Linus Torvalds 已提交
813 814
}

815
static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
816
{
817 818 819 820 821 822 823 824
	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;
825
	}
826
	c->len = nla_len(tb[TCA_ACT_COOKIE]);
827

828
	return c;
829 830
}

831 832
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
				    struct nlattr *nla, struct nlattr *est,
833
				    char *name, int ovr, int bind,
834
				    bool rtnl_held,
835
				    struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
836 837 838
{
	struct tc_action *a;
	struct tc_action_ops *a_o;
839
	struct tc_cookie *cookie = NULL;
L
Linus Torvalds 已提交
840
	char act_name[IFNAMSIZ];
E
Eric Dumazet 已提交
841
	struct nlattr *tb[TCA_ACT_MAX + 1];
842
	struct nlattr *kind;
843
	int err;
L
Linus Torvalds 已提交
844 845

	if (name == NULL) {
846 847
		err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, NULL,
						  extack);
848
		if (err < 0)
L
Linus Torvalds 已提交
849
			goto err_out;
850
		err = -EINVAL;
851
		kind = tb[TCA_ACT_KIND];
852 853
		if (!kind) {
			NL_SET_ERR_MSG(extack, "TC action kind must be specified");
L
Linus Torvalds 已提交
854
			goto err_out;
855 856 857
		}
		if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
			NL_SET_ERR_MSG(extack, "TC action name too long");
L
Linus Torvalds 已提交
858
			goto err_out;
859
		}
860 861 862
		if (tb[TCA_ACT_COOKIE]) {
			int cklen = nla_len(tb[TCA_ACT_COOKIE]);

863 864
			if (cklen > TC_COOKIE_MAX_SIZE) {
				NL_SET_ERR_MSG(extack, "TC cookie size above the maximum");
865
				goto err_out;
866
			}
867 868 869

			cookie = nla_memdup_cookie(tb);
			if (!cookie) {
870
				NL_SET_ERR_MSG(extack, "No memory to generate TC cookie");
871 872 873 874
				err = -ENOMEM;
				goto err_out;
			}
		}
L
Linus Torvalds 已提交
875
	} else {
876 877 878
		if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
			NL_SET_ERR_MSG(extack, "TC action name too long");
			err = -EINVAL;
L
Linus Torvalds 已提交
879
			goto err_out;
880
		}
L
Linus Torvalds 已提交
881 882 883 884
	}

	a_o = tc_lookup_action_n(act_name);
	if (a_o == NULL) {
885
#ifdef CONFIG_MODULES
886 887
		if (rtnl_held)
			rtnl_unlock();
888
		request_module("act_%s", act_name);
889 890
		if (rtnl_held)
			rtnl_lock();
L
Linus Torvalds 已提交
891 892 893 894 895 896 897 898 899 900

		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) {
901
			err = -EAGAIN;
L
Linus Torvalds 已提交
902 903 904
			goto err_mod;
		}
#endif
905
		NL_SET_ERR_MSG(extack, "Failed to load TC action module");
906
		err = -ENOENT;
L
Linus Torvalds 已提交
907 908 909 910 911
		goto err_out;
	}

	/* backward compatibility for policer */
	if (name == NULL)
912
		err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind,
913
				rtnl_held, tp, extack);
L
Linus Torvalds 已提交
914
	else
915
		err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held,
916
				tp, extack);
917
	if (err < 0)
918
		goto err_mod;
L
Linus Torvalds 已提交
919

920 921
	if (!name && tb[TCA_ACT_COOKIE])
		tcf_set_action_cookie(&a->act_cookie, cookie);
922

L
Linus Torvalds 已提交
923
	/* module count goes up only when brand new policy is created
E
Eric Dumazet 已提交
924 925 926
	 * if it exists and is only bound to in a_o->init() then
	 * ACT_P_CREATED is not returned (a zero is).
	 */
927
	if (err != ACT_P_CREATED)
L
Linus Torvalds 已提交
928 929
		module_put(a_o->owner);

930
	if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN) &&
931
	    !rcu_access_pointer(a->goto_chain)) {
932
		tcf_action_destroy_1(a, bind);
933
		NL_SET_ERR_MSG(extack, "can't use goto chain with NULL chain");
934
		return ERR_PTR(-EINVAL);
935 936
	}

L
Linus Torvalds 已提交
937 938 939 940 941
	return a;

err_mod:
	module_put(a_o->owner);
err_out:
942 943 944 945
	if (cookie) {
		kfree(cookie->data);
		kfree(cookie);
	}
946
	return ERR_PTR(err);
L
Linus Torvalds 已提交
947 948
}

949 950
/* Returns numbers of initialized actions or negative error. */

951 952
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
		    struct nlattr *est, char *name, int ovr, int bind,
953
		    struct tc_action *actions[], size_t *attr_size,
954
		    bool rtnl_held, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
955
{
E
Eric Dumazet 已提交
956
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
957
	struct tc_action *act;
958
	size_t sz = 0;
959
	int err;
L
Linus Torvalds 已提交
960 961
	int i;

962 963
	err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX_PRIO, nla, NULL,
					  extack);
964
	if (err < 0)
965
		return err;
L
Linus Torvalds 已提交
966

967
	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
968
		act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
969
					rtnl_held, extack);
970 971
		if (IS_ERR(act)) {
			err = PTR_ERR(act);
L
Linus Torvalds 已提交
972
			goto err;
973
		}
974
		act->order = i;
975
		sz += tcf_action_fill_size(act);
976 977
		/* Start from index 0 */
		actions[i - 1] = act;
L
Linus Torvalds 已提交
978
	}
979

980
	*attr_size = tcf_action_full_attrs_size(sz);
981
	return i - 1;
L
Linus Torvalds 已提交
982 983

err:
984 985
	tcf_action_destroy(actions, bind);
	return err;
L
Linus Torvalds 已提交
986 987
}

988
int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
L
Linus Torvalds 已提交
989 990 991 992
			  int compat_mode)
{
	int err = 0;
	struct gnet_dump d;
993

994
	if (p == NULL)
L
Linus Torvalds 已提交
995 996 997
		goto errout;

	/* compat_mode being true specifies a call that is supposed
998
	 * to add additional backward compatibility statistic TLVs.
L
Linus Torvalds 已提交
999 1000
	 */
	if (compat_mode) {
1001
		if (p->type == TCA_OLD_COMPAT)
L
Linus Torvalds 已提交
1002
			err = gnet_stats_start_copy_compat(skb, 0,
1003 1004
							   TCA_STATS,
							   TCA_XSTATS,
1005
							   &p->tcfa_lock, &d,
1006
							   TCA_PAD);
L
Linus Torvalds 已提交
1007 1008 1009 1010
		else
			return 0;
	} else
		err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
1011
					    &p->tcfa_lock, &d, TCA_ACT_PAD);
L
Linus Torvalds 已提交
1012 1013 1014 1015

	if (err < 0)
		goto errout;

1016
	if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
1017 1018
	    gnet_stats_copy_basic_hw(NULL, &d, p->cpu_bstats_hw,
				     &p->tcfa_bstats_hw) < 0 ||
1019
	    gnet_stats_copy_rate_est(&d, &p->tcfa_rate_est) < 0 ||
1020
	    gnet_stats_copy_queue(&d, p->cpu_qstats,
1021 1022
				  &p->tcfa_qstats,
				  p->tcfa_qstats.qlen) < 0)
L
Linus Torvalds 已提交
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
		goto errout;

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

	return 0;

errout:
	return -1;
}

1034
static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[],
1035 1036
			u32 portid, u32 seq, u16 flags, int event, int bind,
			int ref)
L
Linus Torvalds 已提交
1037 1038 1039
{
	struct tcamsg *t;
	struct nlmsghdr *nlh;
1040
	unsigned char *b = skb_tail_pointer(skb);
1041
	struct nlattr *nest;
L
Linus Torvalds 已提交
1042

1043
	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*t), flags);
1044 1045 1046
	if (!nlh)
		goto out_nlmsg_trim;
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1047
	t->tca_family = AF_UNSPEC;
1048 1049
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
1050

1051
	nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
1052
	if (!nest)
1053
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
1054

1055
	if (tcf_action_dump(skb, actions, bind, ref) < 0)
1056
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
1057

1058
	nla_nest_end(skb, nest);
1059

1060
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
L
Linus Torvalds 已提交
1061 1062
	return skb->len;

1063
out_nlmsg_trim:
1064
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1065 1066 1067 1068
	return -1;
}

static int
1069
tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
1070
	       struct tc_action *actions[], int event,
1071
	       struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1072 1073 1074 1075 1076 1077
{
	struct sk_buff *skb;

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
	if (!skb)
		return -ENOBUFS;
1078
	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
1079
			 0, 1) <= 0) {
1080
		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
L
Linus Torvalds 已提交
1081 1082 1083
		kfree_skb(skb);
		return -EINVAL;
	}
1084

1085
	return rtnl_unicast(skb, net, portid);
L
Linus Torvalds 已提交
1086 1087
}

1088
static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
1089 1090
					  struct nlmsghdr *n, u32 portid,
					  struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1091
{
E
Eric Dumazet 已提交
1092
	struct nlattr *tb[TCA_ACT_MAX + 1];
1093
	const struct tc_action_ops *ops;
L
Linus Torvalds 已提交
1094 1095
	struct tc_action *a;
	int index;
1096
	int err;
L
Linus Torvalds 已提交
1097

1098
	err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, NULL, extack);
1099
	if (err < 0)
1100
		goto err_out;
L
Linus Torvalds 已提交
1101

1102
	err = -EINVAL;
1103
	if (tb[TCA_ACT_INDEX] == NULL ||
1104 1105
	    nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) {
		NL_SET_ERR_MSG(extack, "Invalid TC action index value");
1106
		goto err_out;
1107
	}
1108
	index = nla_get_u32(tb[TCA_ACT_INDEX]);
L
Linus Torvalds 已提交
1109

1110
	err = -EINVAL;
1111
	ops = tc_lookup_action(tb[TCA_ACT_KIND]);
1112
	if (!ops) { /* could happen in batch of actions */
1113
		NL_SET_ERR_MSG(extack, "Specified TC action kind not found");
1114
		goto err_out;
1115
	}
1116
	err = -ENOENT;
1117 1118
	if (ops->lookup(net, &a, index) == 0) {
		NL_SET_ERR_MSG(extack, "TC action with specified index not found");
L
Linus Torvalds 已提交
1119
		goto err_mod;
1120
	}
L
Linus Torvalds 已提交
1121

1122
	module_put(ops->owner);
L
Linus Torvalds 已提交
1123
	return a;
1124

L
Linus Torvalds 已提交
1125
err_mod:
1126
	module_put(ops->owner);
1127 1128
err_out:
	return ERR_PTR(err);
L
Linus Torvalds 已提交
1129 1130
}

1131
static int tca_action_flush(struct net *net, struct nlattr *nla,
1132 1133
			    struct nlmsghdr *n, u32 portid,
			    struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1134 1135 1136 1137 1138 1139
{
	struct sk_buff *skb;
	unsigned char *b;
	struct nlmsghdr *nlh;
	struct tcamsg *t;
	struct netlink_callback dcb;
1140
	struct nlattr *nest;
E
Eric Dumazet 已提交
1141
	struct nlattr *tb[TCA_ACT_MAX + 1];
1142
	const struct tc_action_ops *ops;
1143
	struct nlattr *kind;
1144
	int err = -ENOMEM;
L
Linus Torvalds 已提交
1145 1146

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1147
	if (!skb)
1148
		return err;
L
Linus Torvalds 已提交
1149

1150
	b = skb_tail_pointer(skb);
L
Linus Torvalds 已提交
1151

1152
	err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, NULL, extack);
1153
	if (err < 0)
L
Linus Torvalds 已提交
1154 1155
		goto err_out;

1156
	err = -EINVAL;
1157
	kind = tb[TCA_ACT_KIND];
1158
	ops = tc_lookup_action(kind);
1159 1160
	if (!ops) { /*some idjot trying to flush unknown action */
		NL_SET_ERR_MSG(extack, "Cannot flush unknown TC action");
L
Linus Torvalds 已提交
1161
		goto err_out;
1162
	}
L
Linus Torvalds 已提交
1163

1164 1165
	nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
			sizeof(*t), 0);
1166 1167
	if (!nlh) {
		NL_SET_ERR_MSG(extack, "Failed to create TC action flush notification");
1168
		goto out_module_put;
1169
	}
1170
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1171
	t->tca_family = AF_UNSPEC;
1172 1173
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
L
Linus Torvalds 已提交
1174

1175
	nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
1176 1177
	if (!nest) {
		NL_SET_ERR_MSG(extack, "Failed to add new netlink message");
1178
		goto out_module_put;
1179
	}
L
Linus Torvalds 已提交
1180

1181
	err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops, extack);
1182 1183
	if (err <= 0) {
		nla_nest_cancel(skb, nest);
1184
		goto out_module_put;
1185
	}
L
Linus Torvalds 已提交
1186

1187
	nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
1188

1189
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
L
Linus Torvalds 已提交
1190
	nlh->nlmsg_flags |= NLM_F_ROOT;
1191
	module_put(ops->owner);
1192
	err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
E
Eric Dumazet 已提交
1193
			     n->nlmsg_flags & NLM_F_ECHO);
L
Linus Torvalds 已提交
1194 1195
	if (err > 0)
		return 0;
1196 1197
	if (err < 0)
		NL_SET_ERR_MSG(extack, "Failed to send TC action flush notification");
L
Linus Torvalds 已提交
1198 1199 1200

	return err;

1201
out_module_put:
1202
	module_put(ops->owner);
L
Linus Torvalds 已提交
1203 1204 1205 1206 1207
err_out:
	kfree_skb(skb);
	return err;
}

1208
static int tcf_action_delete(struct net *net, struct tc_action *actions[])
1209
{
1210
	int i;
1211

1212 1213
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		struct tc_action *a = actions[i];
1214 1215 1216 1217
		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.
		 */
1218 1219
		struct tcf_idrinfo *idrinfo = a->idrinfo;
		u32 act_index = a->tcfa_index;
1220

1221
		actions[i] = NULL;
1222 1223 1224 1225
		if (tcf_action_put(a)) {
			/* last reference, action was deleted concurrently */
			module_put(ops->owner);
		} else  {
1226 1227
			int ret;

1228
			/* now do the delete */
1229
			ret = tcf_idr_delete_index(idrinfo, act_index);
1230
			if (ret < 0)
1231 1232 1233 1234 1235 1236
				return ret;
		}
	}
	return 0;
}

1237
static int
1238
tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
1239
	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
1240 1241 1242 1243
{
	int ret;
	struct sk_buff *skb;

1244 1245
	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
			GFP_KERNEL);
1246 1247 1248 1249
	if (!skb)
		return -ENOBUFS;

	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
1250
			 0, 2) <= 0) {
1251
		NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
1252 1253 1254 1255 1256
		kfree_skb(skb);
		return -EINVAL;
	}

	/* now do the delete */
1257
	ret = tcf_action_delete(net, actions);
1258
	if (ret < 0) {
1259
		NL_SET_ERR_MSG(extack, "Failed to delete TC action");
1260 1261 1262
		kfree_skb(skb);
		return ret;
	}
1263 1264 1265 1266 1267 1268 1269 1270

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

L
Linus Torvalds 已提交
1271
static int
1272
tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
1273
	      u32 portid, int event, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1274
{
1275
	int i, ret;
E
Eric Dumazet 已提交
1276
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
1277
	struct tc_action *act;
1278
	size_t attr_size = 0;
1279
	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
L
Linus Torvalds 已提交
1280

1281 1282
	ret = nla_parse_nested_deprecated(tb, TCA_ACT_MAX_PRIO, nla, NULL,
					  extack);
1283 1284
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
1285

E
Eric Dumazet 已提交
1286
	if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
1287
		if (tb[1])
1288
			return tca_action_flush(net, tb[1], n, portid, extack);
1289

1290
		NL_SET_ERR_MSG(extack, "Invalid netlink attributes while flushing TC action");
1291
		return -EINVAL;
L
Linus Torvalds 已提交
1292 1293
	}

1294
	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
1295
		act = tcf_action_get_1(net, tb[i], n, portid, extack);
1296 1297
		if (IS_ERR(act)) {
			ret = PTR_ERR(act);
L
Linus Torvalds 已提交
1298
			goto err;
1299
		}
1300
		attr_size += tcf_action_fill_size(act);
1301
		actions[i - 1] = act;
L
Linus Torvalds 已提交
1302
	}
1303 1304

	attr_size = tcf_action_full_attrs_size(attr_size);
L
Linus Torvalds 已提交
1305 1306

	if (event == RTM_GETACTION)
1307
		ret = tcf_get_notify(net, portid, n, actions, event, extack);
L
Linus Torvalds 已提交
1308
	else { /* delete */
1309
		ret = tcf_del_notify(net, n, actions, portid, attr_size, extack);
1310
		if (ret)
L
Linus Torvalds 已提交
1311
			goto err;
1312
		return 0;
L
Linus Torvalds 已提交
1313 1314
	}
err:
1315
	tcf_action_put_many(actions);
L
Linus Torvalds 已提交
1316 1317 1318
	return ret;
}

1319
static int
1320
tcf_add_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
1321
	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1322 1323 1324 1325
{
	struct sk_buff *skb;
	int err = 0;

1326 1327
	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
			GFP_KERNEL);
L
Linus Torvalds 已提交
1328 1329 1330
	if (!skb)
		return -ENOBUFS;

1331 1332
	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
			 RTM_NEWACTION, 0, 0) <= 0) {
1333
		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
1334 1335 1336
		kfree_skb(skb);
		return -EINVAL;
	}
1337

1338 1339
	err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
			     n->nlmsg_flags & NLM_F_ECHO);
L
Linus Torvalds 已提交
1340 1341 1342 1343 1344
	if (err > 0)
		err = 0;
	return err;
}

J
Jamal Hadi Salim 已提交
1345
static int tcf_action_add(struct net *net, struct nlattr *nla,
1346 1347
			  struct nlmsghdr *n, u32 portid, int ovr,
			  struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1348
{
1349
	size_t attr_size = 0;
L
Linus Torvalds 已提交
1350
	int ret = 0;
1351
	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
L
Linus Torvalds 已提交
1352

1353
	ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, actions,
1354
			      &attr_size, true, extack);
1355
	if (ret < 0)
1356
		return ret;
1357
	ret = tcf_add_notify(net, n, actions, portid, attr_size, extack);
1358
	if (ovr)
1359
		tcf_action_put_many(actions);
L
Linus Torvalds 已提交
1360

1361
	return ret;
L
Linus Torvalds 已提交
1362 1363
}

1364 1365 1366 1367
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 },
1368
	[TCA_ROOT_TIME_DELTA]      = { .type = NLA_U32 },
1369 1370
};

1371 1372
static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
			 struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1373
{
1374
	struct net *net = sock_net(skb->sk);
1375
	struct nlattr *tca[TCA_ROOT_MAX + 1];
1376
	u32 portid = skb ? NETLINK_CB(skb).portid : 0;
L
Linus Torvalds 已提交
1377 1378
	int ret = 0, ovr = 0;

1379 1380
	if ((n->nlmsg_type != RTM_GETACTION) &&
	    !netlink_capable(skb, CAP_NET_ADMIN))
1381 1382
		return -EPERM;

1383 1384
	ret = nlmsg_parse_deprecated(n, sizeof(struct tcamsg), tca,
				     TCA_ROOT_MAX, NULL, extack);
1385 1386 1387 1388
	if (ret < 0)
		return ret;

	if (tca[TCA_ACT_TAB] == NULL) {
1389
		NL_SET_ERR_MSG(extack, "Netlink action attributes missing");
L
Linus Torvalds 已提交
1390 1391 1392
		return -EINVAL;
	}

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

	return ret;
}

1425
static struct nlattr *find_dump_kind(struct nlattr **nla)
L
Linus Torvalds 已提交
1426
{
E
Eric Dumazet 已提交
1427
	struct nlattr *tb1, *tb2[TCA_ACT_MAX + 1];
1428 1429
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
	struct nlattr *kind;
L
Linus Torvalds 已提交
1430

1431
	tb1 = nla[TCA_ACT_TAB];
L
Linus Torvalds 已提交
1432 1433 1434
	if (tb1 == NULL)
		return NULL;

1435
	if (nla_parse_deprecated(tb, TCA_ACT_MAX_PRIO, nla_data(tb1), NLMSG_ALIGN(nla_len(tb1)), NULL, NULL) < 0)
L
Linus Torvalds 已提交
1436 1437
		return NULL;

1438 1439
	if (tb[1] == NULL)
		return NULL;
1440
	if (nla_parse_nested_deprecated(tb2, TCA_ACT_MAX, tb[1], NULL, NULL) < 0)
L
Linus Torvalds 已提交
1441
		return NULL;
1442
	kind = tb2[TCA_ACT_KIND];
L
Linus Torvalds 已提交
1443

1444
	return kind;
L
Linus Torvalds 已提交
1445 1446
}

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

1464 1465
	ret = nlmsg_parse_deprecated(cb->nlh, sizeof(struct tcamsg), tb,
				     TCA_ROOT_MAX, tcaa_policy, cb->extack);
1466 1467
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
1468

1469
	kind = find_dump_kind(tb);
L
Linus Torvalds 已提交
1470
	if (kind == NULL) {
1471
		pr_info("tc_dump_action: action bad kind\n");
L
Linus Torvalds 已提交
1472 1473 1474
		return 0;
	}

1475
	a_o = tc_lookup_action(kind);
E
Eric Dumazet 已提交
1476
	if (a_o == NULL)
L
Linus Torvalds 已提交
1477 1478
		return 0;

1479 1480 1481 1482 1483 1484
	cb->args[2] = 0;
	if (tb[TCA_ROOT_FLAGS]) {
		bf = nla_get_bitfield32(tb[TCA_ROOT_FLAGS]);
		cb->args[2] = bf.value;
	}

1485 1486 1487 1488
	if (tb[TCA_ROOT_TIME_DELTA]) {
		msecs_since = nla_get_u32(tb[TCA_ROOT_TIME_DELTA]);
	}

1489
	nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
1490 1491 1492
			cb->nlh->nlmsg_type, sizeof(*t), 0);
	if (!nlh)
		goto out_module_put;
1493

1494 1495 1496
	if (msecs_since)
		jiffy_since = jiffies - msecs_to_jiffies(msecs_since);

1497
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1498
	t->tca_family = AF_UNSPEC;
1499 1500
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
1501
	cb->args[3] = jiffy_since;
1502 1503 1504
	count_attr = nla_reserve(skb, TCA_ROOT_COUNT, sizeof(u32));
	if (!count_attr)
		goto out_module_put;
L
Linus Torvalds 已提交
1505

1506
	nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
1507
	if (nest == NULL)
1508
		goto out_module_put;
L
Linus Torvalds 已提交
1509

1510
	ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
L
Linus Torvalds 已提交
1511
	if (ret < 0)
1512
		goto out_module_put;
L
Linus Torvalds 已提交
1513 1514

	if (ret > 0) {
1515
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
1516
		ret = skb->len;
1517 1518 1519
		act_count = cb->args[1];
		memcpy(nla_data(count_attr), &act_count, sizeof(u32));
		cb->args[1] = 0;
L
Linus Torvalds 已提交
1520
	} else
1521
		nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1522

1523
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
1524
	if (NETLINK_CB(cb->skb).portid && ret)
L
Linus Torvalds 已提交
1525 1526 1527 1528
		nlh->nlmsg_flags |= NLM_F_MULTI;
	module_put(a_o->owner);
	return skb->len;

1529
out_module_put:
L
Linus Torvalds 已提交
1530
	module_put(a_o->owner);
1531
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1532 1533 1534 1535 1536
	return skb->len;
}

static int __init tc_action_init(void)
{
1537 1538
	rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL, 0);
	rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL, 0);
1539
	rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,
1540
		      0);
L
Linus Torvalds 已提交
1541 1542 1543 1544 1545

	return 0;
}

subsys_initcall(tc_action_init);