act_api.c 36.4 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 <net/net_namespace.h>
#include <net/sock.h>
L
Linus Torvalds 已提交
26
#include <net/sch_generic.h>
27
#include <net/pkt_cls.h>
L
Linus Torvalds 已提交
28
#include <net/act_api.h>
29
#include <net/netlink.h>
L
Linus Torvalds 已提交
30

31 32 33
static void tcf_action_goto_chain_exec(const struct tc_action *a,
				       struct tcf_result *res)
{
34
	const struct tcf_chain *chain = rcu_dereference_bh(a->goto_chain);
35 36 37 38

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

39 40 41 42 43 44 45 46 47 48 49 50 51
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;

52
	old = xchg((__force struct tc_cookie **)old_cookie, new_cookie);
53 54 55 56
	if (old)
		call_rcu(&old->rcu, tcf_free_cookie_rcu);
}

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 88 89 90 91 92 93
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,
94
					 struct tcf_chain *goto_chain)
95 96
{
	a->tcfa_action = action;
97 98
	rcu_swap_protected(a->goto_chain, goto_chain, 1);
	return goto_chain;
99 100 101
}
EXPORT_SYMBOL(tcf_action_set_ctrlact);

C
Cong Wang 已提交
102 103 104 105 106 107
/* 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)
108
{
109
	struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
110

111
	free_percpu(p->cpu_bstats);
112
	free_percpu(p->cpu_bstats_hw);
113
	free_percpu(p->cpu_qstats);
114

115
	tcf_set_action_cookie(&p->act_cookie, NULL);
116 117
	if (chain)
		tcf_chain_put_by_act(chain);
118

119 120 121
	kfree(p);
}

122
static void tcf_action_cleanup(struct tc_action *p)
123
{
124 125 126
	if (p->ops->cleanup)
		p->ops->cleanup(p);

127
	gen_kill_estimator(&p->tcfa_rate_est);
C
Cong Wang 已提交
128
	free_tcf(p);
129 130
}

131 132 133 134
static int __tcf_action_put(struct tc_action *p, bool bind)
{
	struct tcf_idrinfo *idrinfo = p->idrinfo;

135
	if (refcount_dec_and_mutex_lock(&p->tcfa_refcnt, &idrinfo->lock)) {
136 137 138
		if (bind)
			atomic_dec(&p->tcfa_bindcnt);
		idr_remove(&idrinfo->action_idr, p->tcfa_index);
139
		mutex_unlock(&idrinfo->lock);
140 141 142 143 144 145 146 147 148 149 150

		tcf_action_cleanup(p);
		return 1;
	}

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

	return 0;
}

151
int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
152 153 154
{
	int ret = 0;

155 156 157 158 159 160 161 162 163 164 165 166
	/* 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.
	 */
167
	if (p) {
168
		if (!bind && strict && atomic_read(&p->tcfa_bindcnt) > 0)
169
			return -EPERM;
170

171
		if (__tcf_action_put(p, bind))
172
			ret = ACT_P_DELETED;
173
	}
174

175 176
	return ret;
}
177
EXPORT_SYMBOL(__tcf_idr_release);
178

179 180
static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
{
181
	struct tc_cookie *act_cookie;
182 183
	u32 cookie_len = 0;

184 185 186 187 188 189
	rcu_read_lock();
	act_cookie = rcu_dereference(act->act_cookie);

	if (act_cookie)
		cookie_len = nla_total_size(act_cookie->len);
	rcu_read_unlock();
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

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

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

231
	mutex_lock(&idrinfo->lock);
232 233 234

	s_i = cb->args[0];

235
	idr_for_each_entry_ul(idr, p, id) {
236 237 238 239 240 241 242 243 244
		index++;
		if (index < s_i)
			continue;

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

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

266
	mutex_unlock(&idrinfo->lock);
267 268 269 270
	if (n_i) {
		if (act_flags & TCA_FLAG_LARGE_DUMP_ON)
			cb->args[1] = n_i;
	}
271 272
	return n_i;

273
nla_put_failure:
274
	nla_nest_cancel(skb, nest);
275 276 277
	goto done;
}

278 279 280 281 282 283 284 285 286 287 288 289 290 291
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;
}

292
static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
293
			  const struct tc_action_ops *ops)
294
{
295
	struct nlattr *nest;
296
	int n_i = 0;
297
	int ret = -EINVAL;
298 299 300
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	unsigned long id = 1;
301

302
	nest = nla_nest_start_noflag(skb, 0);
303 304
	if (nest == NULL)
		goto nla_put_failure;
305
	if (nla_put_string(skb, TCA_KIND, ops->kind))
306
		goto nla_put_failure;
307

308
	mutex_lock(&idrinfo->lock);
309
	idr_for_each_entry_ul(idr, p, id) {
310
		ret = tcf_idr_release_unsafe(p);
311
		if (ret == ACT_P_DELETED) {
312
			module_put(ops->owner);
313 314
			n_i++;
		} else if (ret < 0) {
315
			mutex_unlock(&idrinfo->lock);
316
			goto nla_put_failure;
317 318
		}
	}
319
	mutex_unlock(&idrinfo->lock);
320

321 322
	if (nla_put_u32(skb, TCA_FCNT, n_i))
		goto nla_put_failure;
323
	nla_nest_end(skb, nest);
324 325

	return n_i;
326
nla_put_failure:
327
	nla_nest_cancel(skb, nest);
328
	return ret;
329 330
}

331 332
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
		       struct netlink_callback *cb, int type,
333 334
		       const struct tc_action_ops *ops,
		       struct netlink_ext_ack *extack)
335
{
336
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
337

338
	if (type == RTM_DELACTION) {
339
		return tcf_del_walker(idrinfo, skb, ops);
340
	} else if (type == RTM_GETACTION) {
341
		return tcf_dump_walker(idrinfo, skb, cb);
342
	} else {
343 344
		WARN(1, "tcf_generic_walker: unknown command %d\n", type);
		NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown command");
345 346 347
		return -EINVAL;
	}
}
348
EXPORT_SYMBOL(tcf_generic_walker);
349

350
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
351
{
352 353
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
	struct tc_action *p;
354

355
	mutex_lock(&idrinfo->lock);
356
	p = idr_find(&idrinfo->action_idr, index);
357
	if (IS_ERR(p))
358
		p = NULL;
359
	else if (p)
360
		refcount_inc(&p->tcfa_refcnt);
361
	mutex_unlock(&idrinfo->lock);
362

363 364 365 366 367
	if (p) {
		*a = p;
		return true;
	}
	return false;
368
}
369
EXPORT_SYMBOL(tcf_idr_search);
370

371
static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index)
372 373 374 375
{
	struct tc_action *p;
	int ret = 0;

376
	mutex_lock(&idrinfo->lock);
377 378
	p = idr_find(&idrinfo->action_idr, index);
	if (!p) {
379
		mutex_unlock(&idrinfo->lock);
380 381 382 383 384 385 386 387 388
		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));
389
			mutex_unlock(&idrinfo->lock);
390

391
			tcf_action_cleanup(p);
392 393 394 395 396 397 398 399
			module_put(owner);
			return 0;
		}
		ret = 0;
	} else {
		ret = -EPERM;
	}

400
	mutex_unlock(&idrinfo->lock);
401 402 403
	return ret;
}

404 405 406
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)
407
{
408
	struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
409
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
410
	int err = -ENOMEM;
411 412

	if (unlikely(!p))
413
		return -ENOMEM;
414
	refcount_set(&p->tcfa_refcnt, 1);
415
	if (bind)
416
		atomic_set(&p->tcfa_bindcnt, 1);
417

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

442
	p->idrinfo = idrinfo;
443 444
	p->ops = ops;
	*a = p;
445
	return 0;
446
err4:
447
	free_percpu(p->cpu_qstats);
448 449
err3:
	free_percpu(p->cpu_bstats_hw);
450 451 452 453 454
err2:
	free_percpu(p->cpu_bstats);
err1:
	kfree(p);
	return err;
455
}
456
EXPORT_SYMBOL(tcf_idr_create);
457

458
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
459
{
460
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
461

462
	mutex_lock(&idrinfo->lock);
463 464
	/* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
	WARN_ON(!IS_ERR(idr_replace(&idrinfo->action_idr, a, a->tcfa_index)));
465
	mutex_unlock(&idrinfo->lock);
466
}
467
EXPORT_SYMBOL(tcf_idr_insert);
L
Linus Torvalds 已提交
468

469 470 471 472 473 474
/* 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;

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

535 536
void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
			 struct tcf_idrinfo *idrinfo)
537
{
538 539 540 541
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	int ret;
	unsigned long id = 1;
542

543
	idr_for_each_entry_ul(idr, p, id) {
544 545 546 547 548
		ret = __tcf_idr_release(p, false, true);
		if (ret == ACT_P_DELETED)
			module_put(ops->owner);
		else if (ret < 0)
			return;
549
	}
550
	idr_destroy(&idrinfo->action_idr);
551
}
552
EXPORT_SYMBOL(tcf_idrinfo_destroy);
553

554
static LIST_HEAD(act_base);
L
Linus Torvalds 已提交
555 556
static DEFINE_RWLOCK(act_mod_lock);

557 558
int tcf_register_action(struct tc_action_ops *act,
			struct pernet_operations *ops)
L
Linus Torvalds 已提交
559
{
560
	struct tc_action_ops *a;
561
	int ret;
L
Linus Torvalds 已提交
562

563
	if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
564 565
		return -EINVAL;

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

L
Linus Torvalds 已提交
585 586
	return 0;
}
587
EXPORT_SYMBOL(tcf_register_action);
L
Linus Torvalds 已提交
588

589 590
int tcf_unregister_action(struct tc_action_ops *act,
			  struct pernet_operations *ops)
L
Linus Torvalds 已提交
591
{
592
	struct tc_action_ops *a;
L
Linus Torvalds 已提交
593 594 595
	int err = -ENOENT;

	write_lock(&act_mod_lock);
596 597 598 599
	list_for_each_entry(a, &act_base, head) {
		if (a == act) {
			list_del(&act->head);
			err = 0;
L
Linus Torvalds 已提交
600
			break;
601
		}
L
Linus Torvalds 已提交
602 603
	}
	write_unlock(&act_mod_lock);
604 605
	if (!err)
		unregister_pernet_subsys(ops);
L
Linus Torvalds 已提交
606 607
	return err;
}
608
EXPORT_SYMBOL(tcf_unregister_action);
L
Linus Torvalds 已提交
609 610 611 612

/* lookup by name */
static struct tc_action_ops *tc_lookup_action_n(char *kind)
{
613
	struct tc_action_ops *a, *res = NULL;
L
Linus Torvalds 已提交
614 615 616

	if (kind) {
		read_lock(&act_mod_lock);
617
		list_for_each_entry(a, &act_base, head) {
L
Linus Torvalds 已提交
618
			if (strcmp(kind, a->kind) == 0) {
619 620
				if (try_module_get(a->owner))
					res = a;
L
Linus Torvalds 已提交
621 622 623 624 625
				break;
			}
		}
		read_unlock(&act_mod_lock);
	}
626
	return res;
L
Linus Torvalds 已提交
627 628
}

629 630
/* lookup by nlattr */
static struct tc_action_ops *tc_lookup_action(struct nlattr *kind)
L
Linus Torvalds 已提交
631
{
632
	struct tc_action_ops *a, *res = NULL;
L
Linus Torvalds 已提交
633 634 635

	if (kind) {
		read_lock(&act_mod_lock);
636
		list_for_each_entry(a, &act_base, head) {
637
			if (nla_strcmp(kind, a->kind) == 0) {
638 639
				if (try_module_get(a->owner))
					res = a;
L
Linus Torvalds 已提交
640 641 642 643 644
				break;
			}
		}
		read_unlock(&act_mod_lock);
	}
645
	return res;
L
Linus Torvalds 已提交
646 647
}

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

658 659 660
	if (skb_skip_tc_classify(skb))
		return TC_ACT_OK;

661
restart_act_graph:
662 663 664
	for (i = 0; i < nr_actions; i++) {
		const struct tc_action *a = actions[i];

665 666 667 668
		if (jmp_prgcnt > 0) {
			jmp_prgcnt -= 1;
			continue;
		}
L
Linus Torvalds 已提交
669
repeat:
670 671 672
		ret = a->ops->act(skb, a, res);
		if (ret == TC_ACT_REPEAT)
			goto repeat;	/* we need a ttl - JHS */
673

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

694
		if (ret != TC_ACT_PIPE)
695
			break;
L
Linus Torvalds 已提交
696
	}
697

L
Linus Torvalds 已提交
698 699
	return ret;
}
700
EXPORT_SYMBOL(tcf_action_exec);
L
Linus Torvalds 已提交
701

702
int tcf_action_destroy(struct tc_action *actions[], int bind)
L
Linus Torvalds 已提交
703
{
704
	const struct tc_action_ops *ops;
705 706
	struct tc_action *a;
	int ret = 0, i;
L
Linus Torvalds 已提交
707

708 709 710
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		a = actions[i];
		actions[i] = NULL;
711
		ops = a->ops;
712
		ret = __tcf_idr_release(a, bind, true);
713
		if (ret == ACT_P_DELETED)
714
			module_put(ops->owner);
715 716
		else if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
717
	}
718
	return ret;
L
Linus Torvalds 已提交
719 720
}

721 722 723 724 725 726 727
static int tcf_action_destroy_1(struct tc_action *a, int bind)
{
	struct tc_action *actions[] = { a, NULL };

	return tcf_action_destroy(actions, bind);
}

728 729 730 731 732
static int tcf_action_put(struct tc_action *p)
{
	return __tcf_action_put(p, false);
}

733
/* Put all actions in this array, skip those NULL's. */
734
static void tcf_action_put_many(struct tc_action *actions[])
735
{
736
	int i;
737

738
	for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
739
		struct tc_action *a = actions[i];
740
		const struct tc_action_ops *ops;
741

742 743 744
		if (!a)
			continue;
		ops = a->ops;
745 746 747 748 749
		if (tcf_action_put(a))
			module_put(ops->owner);
	}
}

L
Linus Torvalds 已提交
750 751 752 753 754 755 756 757 758 759
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;
760
	unsigned char *b = skb_tail_pointer(skb);
761
	struct nlattr *nest;
762
	struct tc_cookie *cookie;
L
Linus Torvalds 已提交
763

764 765
	if (nla_put_string(skb, TCA_KIND, a->ops->kind))
		goto nla_put_failure;
L
Linus Torvalds 已提交
766
	if (tcf_action_copy_stats(skb, a, 0))
767
		goto nla_put_failure;
768 769 770 771 772 773

	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();
774
			goto nla_put_failure;
775
		}
776
	}
777
	rcu_read_unlock();
778

779
	nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
780 781
	if (nest == NULL)
		goto nla_put_failure;
E
Eric Dumazet 已提交
782 783
	err = tcf_action_dump_old(skb, a, bind, ref);
	if (err > 0) {
784
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
785 786 787
		return err;
	}

788
nla_put_failure:
789
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
790 791
	return -1;
}
792
EXPORT_SYMBOL(tcf_action_dump_1);
L
Linus Torvalds 已提交
793

794
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[],
795
		    int bind, int ref)
L
Linus Torvalds 已提交
796 797
{
	struct tc_action *a;
798
	int err = -EINVAL, i;
799
	struct nlattr *nest;
L
Linus Torvalds 已提交
800

801 802
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		a = actions[i];
803
		nest = nla_nest_start_noflag(skb, a->order);
804 805
		if (nest == NULL)
			goto nla_put_failure;
L
Linus Torvalds 已提交
806 807
		err = tcf_action_dump_1(skb, a, bind, ref);
		if (err < 0)
808
			goto errout;
809
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
810 811 812 813
	}

	return 0;

814
nla_put_failure:
815 816
	err = -EINVAL;
errout:
817
	nla_nest_cancel(skb, nest);
818
	return err;
L
Linus Torvalds 已提交
819 820
}

821
static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
822
{
823 824 825 826 827 828 829 830
	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;
831
	}
832
	c->len = nla_len(tb[TCA_ACT_COOKIE]);
833

834
	return c;
835 836
}

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

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

869 870
			if (cklen > TC_COOKIE_MAX_SIZE) {
				NL_SET_ERR_MSG(extack, "TC cookie size above the maximum");
871
				goto err_out;
872
			}
873 874 875

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

	a_o = tc_lookup_action_n(act_name);
	if (a_o == NULL) {
891
#ifdef CONFIG_MODULES
892 893
		if (rtnl_held)
			rtnl_unlock();
894
		request_module("act_%s", act_name);
895 896
		if (rtnl_held)
			rtnl_lock();
L
Linus Torvalds 已提交
897 898 899 900 901 902 903 904 905 906

		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) {
907
			err = -EAGAIN;
L
Linus Torvalds 已提交
908 909 910
			goto err_mod;
		}
#endif
911
		NL_SET_ERR_MSG(extack, "Failed to load TC action module");
912
		err = -ENOENT;
L
Linus Torvalds 已提交
913 914 915 916 917
		goto err_out;
	}

	/* backward compatibility for policer */
	if (name == NULL)
918
		err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind,
919
				rtnl_held, tp, extack);
L
Linus Torvalds 已提交
920
	else
921
		err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held,
922
				tp, extack);
923
	if (err < 0)
924
		goto err_mod;
L
Linus Torvalds 已提交
925

926 927
	if (!name && tb[TCA_ACT_COOKIE])
		tcf_set_action_cookie(&a->act_cookie, cookie);
928

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

936
	if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN) &&
937
	    !rcu_access_pointer(a->goto_chain)) {
938
		tcf_action_destroy_1(a, bind);
939
		NL_SET_ERR_MSG(extack, "can't use goto chain with NULL chain");
940
		return ERR_PTR(-EINVAL);
941 942
	}

L
Linus Torvalds 已提交
943 944 945 946 947
	return a;

err_mod:
	module_put(a_o->owner);
err_out:
948 949 950 951
	if (cookie) {
		kfree(cookie->data);
		kfree(cookie);
	}
952
	return ERR_PTR(err);
L
Linus Torvalds 已提交
953 954
}

955 956
/* Returns numbers of initialized actions or negative error. */

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

968 969
	err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX_PRIO, nla, NULL,
					  extack);
970
	if (err < 0)
971
		return err;
L
Linus Torvalds 已提交
972

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

986
	*attr_size = tcf_action_full_attrs_size(sz);
987
	return i - 1;
L
Linus Torvalds 已提交
988 989

err:
990 991
	tcf_action_destroy(actions, bind);
	return err;
L
Linus Torvalds 已提交
992 993
}

994
int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
L
Linus Torvalds 已提交
995 996 997 998
			  int compat_mode)
{
	int err = 0;
	struct gnet_dump d;
999

1000
	if (p == NULL)
L
Linus Torvalds 已提交
1001 1002 1003
		goto errout;

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

	if (err < 0)
		goto errout;

1022
	if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
1023 1024
	    gnet_stats_copy_basic_hw(NULL, &d, p->cpu_bstats_hw,
				     &p->tcfa_bstats_hw) < 0 ||
1025
	    gnet_stats_copy_rate_est(&d, &p->tcfa_rate_est) < 0 ||
1026
	    gnet_stats_copy_queue(&d, p->cpu_qstats,
1027 1028
				  &p->tcfa_qstats,
				  p->tcfa_qstats.qlen) < 0)
L
Linus Torvalds 已提交
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
		goto errout;

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

	return 0;

errout:
	return -1;
}

1040
static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[],
1041 1042
			u32 portid, u32 seq, u16 flags, int event, int bind,
			int ref)
L
Linus Torvalds 已提交
1043 1044 1045
{
	struct tcamsg *t;
	struct nlmsghdr *nlh;
1046
	unsigned char *b = skb_tail_pointer(skb);
1047
	struct nlattr *nest;
L
Linus Torvalds 已提交
1048

1049
	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*t), flags);
1050 1051 1052
	if (!nlh)
		goto out_nlmsg_trim;
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1053
	t->tca_family = AF_UNSPEC;
1054 1055
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
1056

1057
	nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
1058
	if (!nest)
1059
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
1060

1061
	if (tcf_action_dump(skb, actions, bind, ref) < 0)
1062
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
1063

1064
	nla_nest_end(skb, nest);
1065

1066
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
L
Linus Torvalds 已提交
1067 1068
	return skb->len;

1069
out_nlmsg_trim:
1070
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1071 1072 1073 1074
	return -1;
}

static int
1075
tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
1076
	       struct tc_action *actions[], int event,
1077
	       struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1078 1079 1080 1081 1082 1083
{
	struct sk_buff *skb;

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
	if (!skb)
		return -ENOBUFS;
1084
	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
1085
			 0, 1) <= 0) {
1086
		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
L
Linus Torvalds 已提交
1087 1088 1089
		kfree_skb(skb);
		return -EINVAL;
	}
1090

1091
	return rtnl_unicast(skb, net, portid);
L
Linus Torvalds 已提交
1092 1093
}

1094
static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
1095 1096
					  struct nlmsghdr *n, u32 portid,
					  struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1097
{
E
Eric Dumazet 已提交
1098
	struct nlattr *tb[TCA_ACT_MAX + 1];
1099
	const struct tc_action_ops *ops;
L
Linus Torvalds 已提交
1100 1101
	struct tc_action *a;
	int index;
1102
	int err;
L
Linus Torvalds 已提交
1103

1104
	err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, NULL, extack);
1105
	if (err < 0)
1106
		goto err_out;
L
Linus Torvalds 已提交
1107

1108
	err = -EINVAL;
1109
	if (tb[TCA_ACT_INDEX] == NULL ||
1110 1111
	    nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) {
		NL_SET_ERR_MSG(extack, "Invalid TC action index value");
1112
		goto err_out;
1113
	}
1114
	index = nla_get_u32(tb[TCA_ACT_INDEX]);
L
Linus Torvalds 已提交
1115

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

1128
	module_put(ops->owner);
L
Linus Torvalds 已提交
1129
	return a;
1130

L
Linus Torvalds 已提交
1131
err_mod:
1132
	module_put(ops->owner);
1133 1134
err_out:
	return ERR_PTR(err);
L
Linus Torvalds 已提交
1135 1136
}

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

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1153
	if (!skb)
1154
		return err;
L
Linus Torvalds 已提交
1155

1156
	b = skb_tail_pointer(skb);
L
Linus Torvalds 已提交
1157

1158
	err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, NULL, extack);
1159
	if (err < 0)
L
Linus Torvalds 已提交
1160 1161
		goto err_out;

1162
	err = -EINVAL;
1163
	kind = tb[TCA_ACT_KIND];
1164
	ops = tc_lookup_action(kind);
1165 1166
	if (!ops) { /*some idjot trying to flush unknown action */
		NL_SET_ERR_MSG(extack, "Cannot flush unknown TC action");
L
Linus Torvalds 已提交
1167
		goto err_out;
1168
	}
L
Linus Torvalds 已提交
1169

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

1181
	nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
1182 1183
	if (!nest) {
		NL_SET_ERR_MSG(extack, "Failed to add new netlink message");
1184
		goto out_module_put;
1185
	}
L
Linus Torvalds 已提交
1186

1187
	err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops, extack);
1188 1189
	if (err <= 0) {
		nla_nest_cancel(skb, nest);
1190
		goto out_module_put;
1191
	}
L
Linus Torvalds 已提交
1192

1193
	nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
1194

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

	return err;

1207
out_module_put:
1208
	module_put(ops->owner);
L
Linus Torvalds 已提交
1209 1210 1211 1212 1213
err_out:
	kfree_skb(skb);
	return err;
}

1214
static int tcf_action_delete(struct net *net, struct tc_action *actions[])
1215
{
1216
	int i;
1217

1218 1219
	for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
		struct tc_action *a = actions[i];
1220 1221 1222 1223
		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.
		 */
1224 1225
		struct tcf_idrinfo *idrinfo = a->idrinfo;
		u32 act_index = a->tcfa_index;
1226

1227
		actions[i] = NULL;
1228 1229 1230 1231
		if (tcf_action_put(a)) {
			/* last reference, action was deleted concurrently */
			module_put(ops->owner);
		} else  {
1232 1233
			int ret;

1234
			/* now do the delete */
1235
			ret = tcf_idr_delete_index(idrinfo, act_index);
1236
			if (ret < 0)
1237 1238 1239 1240 1241 1242
				return ret;
		}
	}
	return 0;
}

1243
static int
1244
tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
1245
	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
1246 1247 1248 1249
{
	int ret;
	struct sk_buff *skb;

1250 1251
	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
			GFP_KERNEL);
1252 1253 1254 1255
	if (!skb)
		return -ENOBUFS;

	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
1256
			 0, 2) <= 0) {
1257
		NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
1258 1259 1260 1261 1262
		kfree_skb(skb);
		return -EINVAL;
	}

	/* now do the delete */
1263
	ret = tcf_action_delete(net, actions);
1264
	if (ret < 0) {
1265
		NL_SET_ERR_MSG(extack, "Failed to delete TC action");
1266 1267 1268
		kfree_skb(skb);
		return ret;
	}
1269 1270 1271 1272 1273 1274 1275 1276

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

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

1287 1288
	ret = nla_parse_nested_deprecated(tb, TCA_ACT_MAX_PRIO, nla, NULL,
					  extack);
1289 1290
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
1291

E
Eric Dumazet 已提交
1292
	if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
1293
		if (tb[1])
1294
			return tca_action_flush(net, tb[1], n, portid, extack);
1295

1296
		NL_SET_ERR_MSG(extack, "Invalid netlink attributes while flushing TC action");
1297
		return -EINVAL;
L
Linus Torvalds 已提交
1298 1299
	}

1300
	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
1301
		act = tcf_action_get_1(net, tb[i], n, portid, extack);
1302 1303
		if (IS_ERR(act)) {
			ret = PTR_ERR(act);
L
Linus Torvalds 已提交
1304
			goto err;
1305
		}
1306
		act->order = i;
1307
		attr_size += tcf_action_fill_size(act);
1308
		actions[i - 1] = act;
L
Linus Torvalds 已提交
1309
	}
1310 1311

	attr_size = tcf_action_full_attrs_size(attr_size);
L
Linus Torvalds 已提交
1312 1313

	if (event == RTM_GETACTION)
1314
		ret = tcf_get_notify(net, portid, n, actions, event, extack);
L
Linus Torvalds 已提交
1315
	else { /* delete */
1316
		ret = tcf_del_notify(net, n, actions, portid, attr_size, extack);
1317
		if (ret)
L
Linus Torvalds 已提交
1318
			goto err;
1319
		return 0;
L
Linus Torvalds 已提交
1320 1321
	}
err:
1322
	tcf_action_put_many(actions);
L
Linus Torvalds 已提交
1323 1324 1325
	return ret;
}

1326
static int
1327
tcf_add_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
1328
	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1329 1330 1331 1332
{
	struct sk_buff *skb;
	int err = 0;

1333 1334
	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
			GFP_KERNEL);
L
Linus Torvalds 已提交
1335 1336 1337
	if (!skb)
		return -ENOBUFS;

1338 1339
	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
			 RTM_NEWACTION, 0, 0) <= 0) {
1340
		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
1341 1342 1343
		kfree_skb(skb);
		return -EINVAL;
	}
1344

1345 1346
	err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
			     n->nlmsg_flags & NLM_F_ECHO);
L
Linus Torvalds 已提交
1347 1348 1349 1350 1351
	if (err > 0)
		err = 0;
	return err;
}

J
Jamal Hadi Salim 已提交
1352
static int tcf_action_add(struct net *net, struct nlattr *nla,
1353 1354
			  struct nlmsghdr *n, u32 portid, int ovr,
			  struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1355
{
1356
	size_t attr_size = 0;
L
Linus Torvalds 已提交
1357
	int ret = 0;
1358
	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
L
Linus Torvalds 已提交
1359

1360
	ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, actions,
1361
			      &attr_size, true, extack);
1362
	if (ret < 0)
1363
		return ret;
1364
	ret = tcf_add_notify(net, n, actions, portid, attr_size, extack);
1365
	if (ovr)
1366
		tcf_action_put_many(actions);
L
Linus Torvalds 已提交
1367

1368
	return ret;
L
Linus Torvalds 已提交
1369 1370
}

1371 1372 1373 1374
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 },
1375
	[TCA_ROOT_TIME_DELTA]      = { .type = NLA_U32 },
1376 1377
};

1378 1379
static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
			 struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1380
{
1381
	struct net *net = sock_net(skb->sk);
1382
	struct nlattr *tca[TCA_ROOT_MAX + 1];
1383
	u32 portid = skb ? NETLINK_CB(skb).portid : 0;
L
Linus Torvalds 已提交
1384 1385
	int ret = 0, ovr = 0;

1386 1387
	if ((n->nlmsg_type != RTM_GETACTION) &&
	    !netlink_capable(skb, CAP_NET_ADMIN))
1388 1389
		return -EPERM;

1390 1391
	ret = nlmsg_parse_deprecated(n, sizeof(struct tcamsg), tca,
				     TCA_ROOT_MAX, NULL, extack);
1392 1393 1394 1395
	if (ret < 0)
		return ret;

	if (tca[TCA_ACT_TAB] == NULL) {
1396
		NL_SET_ERR_MSG(extack, "Netlink action attributes missing");
L
Linus Torvalds 已提交
1397 1398 1399
		return -EINVAL;
	}

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

	return ret;
}

1432
static struct nlattr *find_dump_kind(struct nlattr **nla)
L
Linus Torvalds 已提交
1433
{
E
Eric Dumazet 已提交
1434
	struct nlattr *tb1, *tb2[TCA_ACT_MAX + 1];
1435 1436
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
	struct nlattr *kind;
L
Linus Torvalds 已提交
1437

1438
	tb1 = nla[TCA_ACT_TAB];
L
Linus Torvalds 已提交
1439 1440 1441
	if (tb1 == NULL)
		return NULL;

1442
	if (nla_parse_deprecated(tb, TCA_ACT_MAX_PRIO, nla_data(tb1), NLMSG_ALIGN(nla_len(tb1)), NULL, NULL) < 0)
L
Linus Torvalds 已提交
1443 1444
		return NULL;

1445 1446
	if (tb[1] == NULL)
		return NULL;
1447
	if (nla_parse_nested_deprecated(tb2, TCA_ACT_MAX, tb[1], NULL, NULL) < 0)
L
Linus Torvalds 已提交
1448
		return NULL;
1449
	kind = tb2[TCA_ACT_KIND];
L
Linus Torvalds 已提交
1450

1451
	return kind;
L
Linus Torvalds 已提交
1452 1453
}

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

1471 1472
	ret = nlmsg_parse_deprecated(cb->nlh, sizeof(struct tcamsg), tb,
				     TCA_ROOT_MAX, tcaa_policy, cb->extack);
1473 1474
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
1475

1476
	kind = find_dump_kind(tb);
L
Linus Torvalds 已提交
1477
	if (kind == NULL) {
1478
		pr_info("tc_dump_action: action bad kind\n");
L
Linus Torvalds 已提交
1479 1480 1481
		return 0;
	}

1482
	a_o = tc_lookup_action(kind);
E
Eric Dumazet 已提交
1483
	if (a_o == NULL)
L
Linus Torvalds 已提交
1484 1485
		return 0;

1486 1487 1488 1489 1490 1491
	cb->args[2] = 0;
	if (tb[TCA_ROOT_FLAGS]) {
		bf = nla_get_bitfield32(tb[TCA_ROOT_FLAGS]);
		cb->args[2] = bf.value;
	}

1492 1493 1494 1495
	if (tb[TCA_ROOT_TIME_DELTA]) {
		msecs_since = nla_get_u32(tb[TCA_ROOT_TIME_DELTA]);
	}

1496
	nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
1497 1498 1499
			cb->nlh->nlmsg_type, sizeof(*t), 0);
	if (!nlh)
		goto out_module_put;
1500

1501 1502 1503
	if (msecs_since)
		jiffy_since = jiffies - msecs_to_jiffies(msecs_since);

1504
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1505
	t->tca_family = AF_UNSPEC;
1506 1507
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
1508
	cb->args[3] = jiffy_since;
1509 1510 1511
	count_attr = nla_reserve(skb, TCA_ROOT_COUNT, sizeof(u32));
	if (!count_attr)
		goto out_module_put;
L
Linus Torvalds 已提交
1512

1513
	nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
1514
	if (nest == NULL)
1515
		goto out_module_put;
L
Linus Torvalds 已提交
1516

1517
	ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
L
Linus Torvalds 已提交
1518
	if (ret < 0)
1519
		goto out_module_put;
L
Linus Torvalds 已提交
1520 1521

	if (ret > 0) {
1522
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
1523
		ret = skb->len;
1524 1525 1526
		act_count = cb->args[1];
		memcpy(nla_data(count_attr), &act_count, sizeof(u32));
		cb->args[1] = 0;
L
Linus Torvalds 已提交
1527
	} else
1528
		nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1529

1530
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
1531
	if (NETLINK_CB(cb->skb).portid && ret)
L
Linus Torvalds 已提交
1532 1533 1534 1535
		nlh->nlmsg_flags |= NLM_F_MULTI;
	module_put(a_o->owner);
	return skb->len;

1536
out_module_put:
L
Linus Torvalds 已提交
1537
	module_put(a_o->owner);
1538
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1539 1540 1541 1542 1543
	return skb->len;
}

static int __init tc_action_init(void)
{
1544 1545
	rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL, 0);
	rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL, 0);
1546
	rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,
1547
		      0);
L
Linus Torvalds 已提交
1548 1549 1550 1551 1552

	return 0;
}

subsys_initcall(tc_action_init);