act_api.c 36.4 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
	unsigned long tmp;
225

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

	s_i = cb->args[0];

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

396
	mutex_unlock(&idrinfo->lock);
397 398 399
	return ret;
}

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

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

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

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

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

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

465 466 467 468 469 470
/* 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;

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

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

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

551
static LIST_HEAD(act_base);
L
Linus Torvalds 已提交
552 553
static DEFINE_RWLOCK(act_mod_lock);

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

560
	if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
561 562
		return -EINVAL;

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

L
Linus Torvalds 已提交
582 583
	return 0;
}
584
EXPORT_SYMBOL(tcf_register_action);
L
Linus Torvalds 已提交
585

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

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

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

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

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

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

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

655 656 657
	if (skb_skip_tc_classify(skb))
		return TC_ACT_OK;

658
restart_act_graph:
659 660 661
	for (i = 0; i < nr_actions; i++) {
		const struct tc_action *a = actions[i];

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

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

691
		if (ret != TC_ACT_PIPE)
692
			break;
L
Linus Torvalds 已提交
693
	}
694

L
Linus Torvalds 已提交
695 696
	return ret;
}
697
EXPORT_SYMBOL(tcf_action_exec);
L
Linus Torvalds 已提交
698

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

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

718 719 720 721 722 723 724
static int tcf_action_destroy_1(struct tc_action *a, int bind)
{
	struct tc_action *actions[] = { a, NULL };

	return tcf_action_destroy(actions, bind);
}

725 726 727 728 729
static int tcf_action_put(struct tc_action *p)
{
	return __tcf_action_put(p, false);
}

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

735
	for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
736
		struct tc_action *a = actions[i];
737
		const struct tc_action_ops *ops;
738

739 740 741
		if (!a)
			continue;
		ops = a->ops;
742 743 744 745 746
		if (tcf_action_put(a))
			module_put(ops->owner);
	}
}

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

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

	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();
771
			goto nla_put_failure;
772
		}
773
	}
774
	rcu_read_unlock();
775

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

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

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

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

	return 0;

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

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

831
	return c;
832 833
}

834 835 836 837 838 839 840 841 842
static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = {
	[TCA_ACT_KIND]		= { .type = NLA_NUL_STRING,
				    .len = IFNAMSIZ - 1 },
	[TCA_ACT_INDEX]		= { .type = NLA_U32 },
	[TCA_ACT_COOKIE]	= { .type = NLA_BINARY,
				    .len = TC_COOKIE_MAX_SIZE },
	[TCA_ACT_OPTIONS]	= { .type = NLA_NESTED },
};

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

	if (name == NULL) {
858 859
		err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
						  tcf_action_policy, extack);
860
		if (err < 0)
L
Linus Torvalds 已提交
861
			goto err_out;
862
		err = -EINVAL;
863
		kind = tb[TCA_ACT_KIND];
864 865
		if (!kind) {
			NL_SET_ERR_MSG(extack, "TC action kind must be specified");
L
Linus Torvalds 已提交
866
			goto err_out;
867
		}
868
		nla_strlcpy(act_name, kind, IFNAMSIZ);
869

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

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

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

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

923 924
	if (!name && tb[TCA_ACT_COOKIE])
		tcf_set_action_cookie(&a->act_cookie, cookie);
925

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

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

L
Linus Torvalds 已提交
940 941 942 943 944
	return a;

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

952 953
/* Returns numbers of initialized actions or negative error. */

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

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

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

983
	*attr_size = tcf_action_full_attrs_size(sz);
984
	return i - 1;
L
Linus Torvalds 已提交
985 986

err:
987 988
	tcf_action_destroy(actions, bind);
	return err;
L
Linus Torvalds 已提交
989 990
}

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

997
	if (p == NULL)
L
Linus Torvalds 已提交
998 999 1000
		goto errout;

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

	if (err < 0)
		goto errout;

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

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

	return 0;

errout:
	return -1;
}

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

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

1054
	nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
1055
	if (!nest)
1056
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
1057

1058
	if (tcf_action_dump(skb, actions, bind, ref) < 0)
1059
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
1060

1061
	nla_nest_end(skb, nest);
1062

1063
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
L
Linus Torvalds 已提交
1064 1065
	return skb->len;

1066
out_nlmsg_trim:
1067
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1068 1069 1070 1071
	return -1;
}

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

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

1088
	return rtnl_unicast(skb, net, portid);
L
Linus Torvalds 已提交
1089 1090
}

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

1101 1102
	err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
					  tcf_action_policy, extack);
1103
	if (err < 0)
1104
		goto err_out;
L
Linus Torvalds 已提交
1105

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

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

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

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

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

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

1154
	b = skb_tail_pointer(skb);
L
Linus Torvalds 已提交
1155

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

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

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

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

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

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

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

	return err;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	attr_size = tcf_action_full_attrs_size(attr_size);
L
Linus Torvalds 已提交
1310 1311

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

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

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

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

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

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

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

1366
	return ret;
L
Linus Torvalds 已提交
1367 1368
}

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

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

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

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

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

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

	return ret;
}

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

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

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

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

1449
	return kind;
L
Linus Torvalds 已提交
1450 1451
}

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

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

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

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

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

1490 1491 1492 1493
	if (tb[TCA_ROOT_TIME_DELTA]) {
		msecs_since = nla_get_u32(tb[TCA_ROOT_TIME_DELTA]);
	}

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

1499 1500 1501
	if (msecs_since)
		jiffy_since = jiffies - msecs_to_jiffies(msecs_since);

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

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

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

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

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

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

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

	return 0;
}

subsys_initcall(tc_action_init);