cls_u32.c 31.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*
 * net/sched/cls_u32.c	Ugly (or Universal) 32bit key Packet Classifier.
 *
 *		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.
 *
 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 *
 *	The filters are packed to hash tables of key nodes
 *	with a set of 32bit key/mask pairs at every node.
 *	Nodes reference next level hash tables etc.
 *
 *	This scheme is the best universal classifier I managed to
 *	invent; it is not super-fast, but it is not slow (provided you
 *	program it correctly), and general enough.  And its relative
 *	speed grows as the number of rules becomes larger.
 *
 *	It seems that it represents the best middle point between
 *	speed and manageability both by human and by machine.
 *
 *	It is especially useful for link sharing combined with QoS;
 *	pure RSVP doesn't need such a general approach and can use
 *	much simpler (and faster) schemes, sort of cls_rsvp.c.
 *
 *	JHS: We should remove the CONFIG_NET_CLS_IND from here
 *	eventually when the meta match extension is made available
 *
 *	nfmark match added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro>
 */

#include <linux/module.h>
34
#include <linux/slab.h>
L
Linus Torvalds 已提交
35 36 37 38
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
39
#include <linux/percpu.h>
L
Linus Torvalds 已提交
40 41
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
42
#include <linux/bitmap.h>
43 44
#include <linux/netdevice.h>
#include <linux/hash.h>
45
#include <net/netlink.h>
L
Linus Torvalds 已提交
46 47
#include <net/act_api.h>
#include <net/pkt_cls.h>
48
#include <linux/idr.h>
L
Linus Torvalds 已提交
49

E
Eric Dumazet 已提交
50
struct tc_u_knode {
51
	struct tc_u_knode __rcu	*next;
L
Linus Torvalds 已提交
52
	u32			handle;
53
	struct tc_u_hnode __rcu	*ht_up;
L
Linus Torvalds 已提交
54 55
	struct tcf_exts		exts;
#ifdef CONFIG_NET_CLS_IND
56
	int			ifindex;
L
Linus Torvalds 已提交
57 58 59
#endif
	u8			fshift;
	struct tcf_result	res;
60
	struct tc_u_hnode __rcu	*ht_down;
L
Linus Torvalds 已提交
61
#ifdef CONFIG_CLS_U32_PERF
62
	struct tc_u32_pcnt __percpu *pf;
L
Linus Torvalds 已提交
63
#endif
64
	u32			flags;
L
Linus Torvalds 已提交
65
#ifdef CONFIG_CLS_U32_MARK
66 67 68
	u32			val;
	u32			mask;
	u32 __percpu		*pcpu_success;
L
Linus Torvalds 已提交
69
#endif
70
	struct tcf_proto	*tp;
71 72 73 74
	union {
		struct work_struct	work;
		struct rcu_head		rcu;
	};
75 76 77 78
	/* The 'sel' field MUST be the last field in structure to allow for
	 * tc_u32_keys allocated at end of structure.
	 */
	struct tc_u32_sel	sel;
L
Linus Torvalds 已提交
79 80
};

E
Eric Dumazet 已提交
81
struct tc_u_hnode {
82
	struct tc_u_hnode __rcu	*next;
L
Linus Torvalds 已提交
83 84 85 86
	u32			handle;
	u32			prio;
	struct tc_u_common	*tp_c;
	int			refcnt;
E
Eric Dumazet 已提交
87
	unsigned int		divisor;
88
	struct idr		handle_idr;
89
	struct rcu_head		rcu;
90 91 92 93
	/* The 'ht' field MUST be the last field in structure to allow for
	 * more entries allocated at end of structure.
	 */
	struct tc_u_knode __rcu	*ht[1];
L
Linus Torvalds 已提交
94 95
};

E
Eric Dumazet 已提交
96
struct tc_u_common {
97
	struct tc_u_hnode __rcu	*hlist;
98
	struct tcf_block	*block;
L
Linus Torvalds 已提交
99
	int			refcnt;
100
	struct idr		handle_idr;
101
	struct hlist_node	hnode;
102
	struct rcu_head		rcu;
L
Linus Torvalds 已提交
103 104
};

E
Eric Dumazet 已提交
105 106 107
static inline unsigned int u32_hash_fold(__be32 key,
					 const struct tc_u32_sel *sel,
					 u8 fshift)
L
Linus Torvalds 已提交
108
{
E
Eric Dumazet 已提交
109
	unsigned int h = ntohl(key & sel->hmask) >> fshift;
L
Linus Torvalds 已提交
110 111 112 113

	return h;
}

J
Jamal Hadi Salim 已提交
114 115
static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp,
			struct tcf_result *res)
L
Linus Torvalds 已提交
116 117 118
{
	struct {
		struct tc_u_knode *knode;
119
		unsigned int	  off;
L
Linus Torvalds 已提交
120 121
	} stack[TC_U32_MAXDEPTH];

122
	struct tc_u_hnode *ht = rcu_dereference_bh(tp->root);
123
	unsigned int off = skb_network_offset(skb);
L
Linus Torvalds 已提交
124 125 126 127 128 129 130 131 132 133
	struct tc_u_knode *n;
	int sdepth = 0;
	int off2 = 0;
	int sel = 0;
#ifdef CONFIG_CLS_U32_PERF
	int j;
#endif
	int i, r;

next_ht:
134
	n = rcu_dereference_bh(ht->ht[sel]);
L
Linus Torvalds 已提交
135 136 137 138 139 140

next_knode:
	if (n) {
		struct tc_u32_key *key = n->sel.keys;

#ifdef CONFIG_CLS_U32_PERF
141
		__this_cpu_inc(n->pf->rcnt);
L
Linus Torvalds 已提交
142 143 144
		j = 0;
#endif

145 146 147 148 149
		if (tc_skip_sw(n->flags)) {
			n = rcu_dereference_bh(n->next);
			goto next_knode;
		}

L
Linus Torvalds 已提交
150
#ifdef CONFIG_CLS_U32_MARK
151
		if ((skb->mark & n->mask) != n->val) {
152
			n = rcu_dereference_bh(n->next);
L
Linus Torvalds 已提交
153 154
			goto next_knode;
		} else {
155
			__this_cpu_inc(*n->pcpu_success);
L
Linus Torvalds 已提交
156 157 158
		}
#endif

E
Eric Dumazet 已提交
159
		for (i = n->sel.nkeys; i > 0; i--, key++) {
S
stephen hemminger 已提交
160
			int toff = off + key->off + (off2 & key->offmask);
S
stephen hemminger 已提交
161
			__be32 *data, hdata;
162

D
Dan Carpenter 已提交
163
			if (skb_headroom(skb) + toff > INT_MAX)
S
stephen hemminger 已提交
164 165
				goto out;

S
stephen hemminger 已提交
166
			data = skb_header_pointer(skb, toff, 4, &hdata);
167 168 169
			if (!data)
				goto out;
			if ((*data ^ key->val) & key->mask) {
170
				n = rcu_dereference_bh(n->next);
L
Linus Torvalds 已提交
171 172 173
				goto next_knode;
			}
#ifdef CONFIG_CLS_U32_PERF
174
			__this_cpu_inc(n->pf->kcnts[j]);
L
Linus Torvalds 已提交
175 176 177
			j++;
#endif
		}
178 179 180

		ht = rcu_dereference_bh(n->ht_down);
		if (!ht) {
L
Linus Torvalds 已提交
181
check_terminal:
E
Eric Dumazet 已提交
182
			if (n->sel.flags & TC_U32_TERMINAL) {
L
Linus Torvalds 已提交
183 184 185

				*res = n->res;
#ifdef CONFIG_NET_CLS_IND
186
				if (!tcf_match_indev(skb, n->ifindex)) {
187
					n = rcu_dereference_bh(n->next);
L
Linus Torvalds 已提交
188 189 190 191
					goto next_knode;
				}
#endif
#ifdef CONFIG_CLS_U32_PERF
192
				__this_cpu_inc(n->pf->rhit);
L
Linus Torvalds 已提交
193 194 195
#endif
				r = tcf_exts_exec(skb, &n->exts, res);
				if (r < 0) {
196
					n = rcu_dereference_bh(n->next);
L
Linus Torvalds 已提交
197 198 199 200 201
					goto next_knode;
				}

				return r;
			}
202
			n = rcu_dereference_bh(n->next);
L
Linus Torvalds 已提交
203 204 205 206 207 208 209
			goto next_knode;
		}

		/* PUSH */
		if (sdepth >= TC_U32_MAXDEPTH)
			goto deadloop;
		stack[sdepth].knode = n;
210
		stack[sdepth].off = off;
L
Linus Torvalds 已提交
211 212
		sdepth++;

213
		ht = rcu_dereference_bh(n->ht_down);
L
Linus Torvalds 已提交
214
		sel = 0;
215
		if (ht->divisor) {
S
stephen hemminger 已提交
216
			__be32 *data, hdata;
217 218

			data = skb_header_pointer(skb, off + n->sel.hoff, 4,
S
stephen hemminger 已提交
219
						  &hdata);
220 221 222 223 224
			if (!data)
				goto out;
			sel = ht->divisor & u32_hash_fold(*data, &n->sel,
							  n->fshift);
		}
E
Eric Dumazet 已提交
225
		if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT)))
L
Linus Torvalds 已提交
226 227
			goto next_ht;

E
Eric Dumazet 已提交
228
		if (n->sel.flags & (TC_U32_OFFSET | TC_U32_VAROFFSET)) {
L
Linus Torvalds 已提交
229
			off2 = n->sel.off + 3;
230
			if (n->sel.flags & TC_U32_VAROFFSET) {
S
stephen hemminger 已提交
231
				__be16 *data, hdata;
232 233 234

				data = skb_header_pointer(skb,
							  off + n->sel.offoff,
S
stephen hemminger 已提交
235
							  2, &hdata);
236 237 238 239 240
				if (!data)
					goto out;
				off2 += ntohs(n->sel.offmask & *data) >>
					n->sel.offshift;
			}
L
Linus Torvalds 已提交
241 242
			off2 &= ~3;
		}
E
Eric Dumazet 已提交
243
		if (n->sel.flags & TC_U32_EAT) {
244
			off += off2;
L
Linus Torvalds 已提交
245 246 247
			off2 = 0;
		}

248
		if (off < skb->len)
L
Linus Torvalds 已提交
249 250 251 252 253 254
			goto next_ht;
	}

	/* POP */
	if (sdepth--) {
		n = stack[sdepth].knode;
255
		ht = rcu_dereference_bh(n->ht_up);
256
		off = stack[sdepth].off;
L
Linus Torvalds 已提交
257 258
		goto check_terminal;
	}
259
out:
L
Linus Torvalds 已提交
260 261 262
	return -1;

deadloop:
263
	net_warn_ratelimited("cls_u32: dead loop\n");
L
Linus Torvalds 已提交
264 265 266
	return -1;
}

J
Jamal Hadi Salim 已提交
267
static struct tc_u_hnode *u32_lookup_ht(struct tc_u_common *tp_c, u32 handle)
L
Linus Torvalds 已提交
268 269 270
{
	struct tc_u_hnode *ht;

271 272 273
	for (ht = rtnl_dereference(tp_c->hlist);
	     ht;
	     ht = rtnl_dereference(ht->next))
L
Linus Torvalds 已提交
274 275 276 277 278 279
		if (ht->handle == handle)
			break;

	return ht;
}

J
Jamal Hadi Salim 已提交
280
static struct tc_u_knode *u32_lookup_key(struct tc_u_hnode *ht, u32 handle)
L
Linus Torvalds 已提交
281
{
E
Eric Dumazet 已提交
282
	unsigned int sel;
L
Linus Torvalds 已提交
283 284 285 286 287 288
	struct tc_u_knode *n = NULL;

	sel = TC_U32_HASH(handle);
	if (sel > ht->divisor)
		goto out;

289 290 291
	for (n = rtnl_dereference(ht->ht[sel]);
	     n;
	     n = rtnl_dereference(n->next))
L
Linus Torvalds 已提交
292 293 294 295 296 297 298
		if (n->handle == handle)
			break;
out:
	return n;
}


299
static void *u32_get(struct tcf_proto *tp, u32 handle)
L
Linus Torvalds 已提交
300 301 302 303 304
{
	struct tc_u_hnode *ht;
	struct tc_u_common *tp_c = tp->data;

	if (TC_U32_HTID(handle) == TC_U32_ROOT)
305
		ht = rtnl_dereference(tp->root);
L
Linus Torvalds 已提交
306 307 308 309
	else
		ht = u32_lookup_ht(tp_c, TC_U32_HTID(handle));

	if (!ht)
310
		return NULL;
L
Linus Torvalds 已提交
311 312

	if (TC_U32_KEY(handle) == 0)
313
		return ht;
L
Linus Torvalds 已提交
314

315
	return u32_lookup_key(ht, handle);
L
Linus Torvalds 已提交
316 317
}

318
static u32 gen_new_htid(struct tc_u_common *tp_c, struct tc_u_hnode *ptr)
L
Linus Torvalds 已提交
319
{
320 321
	unsigned long idr_index;
	int err;
L
Linus Torvalds 已提交
322

323
	/* This is only used inside rtnl lock it is safe to increment
324 325
	 * without read _copy_ update semantics
	 */
326 327 328 329 330
	err = idr_alloc_ext(&tp_c->handle_idr, ptr, &idr_index,
			    1, 0x7FF, GFP_KERNEL);
	if (err)
		return 0;
	return (u32)(idr_index | 0x800) << 20;
L
Linus Torvalds 已提交
331 332
}

333 334 335 336 337 338 339
static struct hlist_head *tc_u_common_hash;

#define U32_HASH_SHIFT 10
#define U32_HASH_SIZE (1 << U32_HASH_SHIFT)

static unsigned int tc_u_hash(const struct tcf_proto *tp)
{
340
	return hash_ptr(tp->chain->block, U32_HASH_SHIFT);
341 342 343 344 345 346 347 348 349
}

static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
{
	struct tc_u_common *tc;
	unsigned int h;

	h = tc_u_hash(tp);
	hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) {
350
		if (tc->block == tp->chain->block)
351 352 353 354 355
			return tc;
	}
	return NULL;
}

L
Linus Torvalds 已提交
356 357 358 359
static int u32_init(struct tcf_proto *tp)
{
	struct tc_u_hnode *root_ht;
	struct tc_u_common *tp_c;
360
	unsigned int h;
L
Linus Torvalds 已提交
361

362
	tp_c = tc_u_common_find(tp);
L
Linus Torvalds 已提交
363

364
	root_ht = kzalloc(sizeof(*root_ht), GFP_KERNEL);
L
Linus Torvalds 已提交
365 366 367 368
	if (root_ht == NULL)
		return -ENOBUFS;

	root_ht->refcnt++;
369
	root_ht->handle = tp_c ? gen_new_htid(tp_c, root_ht) : 0x80000000;
L
Linus Torvalds 已提交
370
	root_ht->prio = tp->prio;
371
	idr_init(&root_ht->handle_idr);
L
Linus Torvalds 已提交
372 373

	if (tp_c == NULL) {
374
		tp_c = kzalloc(sizeof(*tp_c), GFP_KERNEL);
L
Linus Torvalds 已提交
375 376 377 378
		if (tp_c == NULL) {
			kfree(root_ht);
			return -ENOBUFS;
		}
379
		tp_c->block = tp->chain->block;
380
		INIT_HLIST_NODE(&tp_c->hnode);
381
		idr_init(&tp_c->handle_idr);
382 383 384

		h = tc_u_hash(tp);
		hlist_add_head(&tp_c->hnode, &tc_u_common_hash[h]);
L
Linus Torvalds 已提交
385 386 387
	}

	tp_c->refcnt++;
388 389
	RCU_INIT_POINTER(root_ht->next, tp_c->hlist);
	rcu_assign_pointer(tp_c->hlist, root_ht);
L
Linus Torvalds 已提交
390 391
	root_ht->tp_c = tp_c;

392
	rcu_assign_pointer(tp->root, root_ht);
L
Linus Torvalds 已提交
393 394 395 396
	tp->data = tp_c;
	return 0;
}

J
Jamal Hadi Salim 已提交
397
static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n,
398
			   bool free_pf)
L
Linus Torvalds 已提交
399
{
400
	tcf_exts_destroy(&n->exts);
401
	tcf_exts_put_net(&n->exts);
L
Linus Torvalds 已提交
402 403 404
	if (n->ht_down)
		n->ht_down->refcnt--;
#ifdef CONFIG_CLS_U32_PERF
405 406
	if (free_pf)
		free_percpu(n->pf);
407 408
#endif
#ifdef CONFIG_CLS_U32_MARK
409 410
	if (free_pf)
		free_percpu(n->pcpu_success);
L
Linus Torvalds 已提交
411 412 413 414 415
#endif
	kfree(n);
	return 0;
}

416 417 418 419 420 421 422 423
/* u32_delete_key_rcu should be called when free'ing a copied
 * version of a tc_u_knode obtained from u32_init_knode(). When
 * copies are obtained from u32_init_knode() the statistics are
 * shared between the old and new copies to allow readers to
 * continue to update the statistics during the copy. To support
 * this the u32_delete_key_rcu variant does not free the percpu
 * statistics.
 */
424 425 426 427 428 429 430 431 432
static void u32_delete_key_work(struct work_struct *work)
{
	struct tc_u_knode *key = container_of(work, struct tc_u_knode, work);

	rtnl_lock();
	u32_destroy_key(key->tp, key, false);
	rtnl_unlock();
}

433 434 435 436
static void u32_delete_key_rcu(struct rcu_head *rcu)
{
	struct tc_u_knode *key = container_of(rcu, struct tc_u_knode, rcu);

437 438
	INIT_WORK(&key->work, u32_delete_key_work);
	tcf_queue_work(&key->work);
439 440 441 442 443 444 445 446 447
}

/* u32_delete_key_freepf_rcu is the rcu callback variant
 * that free's the entire structure including the statistics
 * percpu variables. Only use this if the key is not a copy
 * returned by u32_init_knode(). See u32_delete_key_rcu()
 * for the variant that should be used with keys return from
 * u32_init_knode()
 */
448 449 450 451 452 453 454 455 456
static void u32_delete_key_freepf_work(struct work_struct *work)
{
	struct tc_u_knode *key = container_of(work, struct tc_u_knode, work);

	rtnl_lock();
	u32_destroy_key(key->tp, key, true);
	rtnl_unlock();
}

457 458 459 460
static void u32_delete_key_freepf_rcu(struct rcu_head *rcu)
{
	struct tc_u_knode *key = container_of(rcu, struct tc_u_knode, rcu);

461 462
	INIT_WORK(&key->work, u32_delete_key_freepf_work);
	tcf_queue_work(&key->work);
463 464
}

465
static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
L
Linus Torvalds 已提交
466
{
467 468
	struct tc_u_knode __rcu **kp;
	struct tc_u_knode *pkp;
469
	struct tc_u_hnode *ht = rtnl_dereference(key->ht_up);
L
Linus Torvalds 已提交
470 471

	if (ht) {
472 473 474 475 476
		kp = &ht->ht[TC_U32_HASH(key->handle)];
		for (pkp = rtnl_dereference(*kp); pkp;
		     kp = &pkp->next, pkp = rtnl_dereference(*kp)) {
			if (pkp == key) {
				RCU_INIT_POINTER(*kp, key->next);
L
Linus Torvalds 已提交
477

478
				tcf_unbind_filter(tp, &key->res);
479
				tcf_exts_get_net(&key->exts);
480
				call_rcu(&key->rcu, u32_delete_key_freepf_rcu);
L
Linus Torvalds 已提交
481 482 483 484
				return 0;
			}
		}
	}
485
	WARN_ON(1);
L
Linus Torvalds 已提交
486 487 488
	return 0;
}

489
static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
490
{
491
	struct tcf_block *block = tp->chain->block;
492
	struct tc_cls_u32_offload cls_u32 = {};
493

494
	tc_cls_common_offload_init_deprecated(&cls_u32.common, tp, NULL);
495 496 497 498
	cls_u32.command = TC_CLSU32_DELETE_HNODE;
	cls_u32.hnode.divisor = h->divisor;
	cls_u32.hnode.handle = h->handle;
	cls_u32.hnode.prio = h->prio;
499

500
	tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, false);
501 502
}

J
Jamal Hadi Salim 已提交
503
static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
504
				u32 flags, struct netlink_ext_ack *extack)
505
{
506
	struct tcf_block *block = tp->chain->block;
507
	struct tc_cls_u32_offload cls_u32 = {};
508 509
	bool skip_sw = tc_skip_sw(flags);
	bool offloaded = false;
510
	int err;
511

512
	tc_cls_common_offload_init_deprecated(&cls_u32.common, tp, extack);
513 514 515 516
	cls_u32.command = TC_CLSU32_NEW_HNODE;
	cls_u32.hnode.divisor = h->divisor;
	cls_u32.hnode.handle = h->handle;
	cls_u32.hnode.prio = h->prio;
517

518 519 520
	err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
	if (err < 0) {
		u32_clear_hw_hnode(tp, h);
521
		return err;
522 523 524 525 526 527
	} else if (err > 0) {
		offloaded = true;
	}

	if (skip_sw && !offloaded)
		return -EINVAL;
528 529

	return 0;
530 531
}

532
static void u32_remove_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n)
533
{
534
	struct tcf_block *block = tp->chain->block;
535
	struct tc_cls_u32_offload cls_u32 = {};
536

537
	tc_cls_common_offload_init_deprecated(&cls_u32.common, tp, NULL);
538
	cls_u32.command = TC_CLSU32_DELETE_KNODE;
539
	cls_u32.knode.handle = n->handle;
540

541
	tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, false);
542
	tcf_block_offload_dec(block, &n->flags);
543 544
}

J
Jamal Hadi Salim 已提交
545
static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
546
				u32 flags, struct netlink_ext_ack *extack)
547
{
548
	struct tcf_block *block = tp->chain->block;
549
	struct tc_cls_u32_offload cls_u32 = {};
550
	bool skip_sw = tc_skip_sw(flags);
551
	int err;
552

553
	tc_cls_common_offload_init_deprecated(&cls_u32.common, tp, extack);
554 555 556
	cls_u32.command = TC_CLSU32_REPLACE_KNODE;
	cls_u32.knode.handle = n->handle;
	cls_u32.knode.fshift = n->fshift;
557
#ifdef CONFIG_CLS_U32_MARK
558 559
	cls_u32.knode.val = n->val;
	cls_u32.knode.mask = n->mask;
560
#else
561 562
	cls_u32.knode.val = 0;
	cls_u32.knode.mask = 0;
563
#endif
564 565
	cls_u32.knode.sel = &n->sel;
	cls_u32.knode.exts = &n->exts;
566
	if (n->ht_down)
567
		cls_u32.knode.link_handle = n->ht_down->handle;
568

569 570
	err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
	if (err < 0) {
571
		u32_remove_hw_knode(tp, n);
572
		return err;
573
	} else if (err > 0) {
574
		tcf_block_offload_inc(block, &n->flags);
575 576
	}

577
	if (skip_sw && !(n->flags & TCA_CLS_FLAGS_IN_HW))
578
		return -EINVAL;
579 580

	return 0;
581 582
}

583
static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
L
Linus Torvalds 已提交
584 585
{
	struct tc_u_knode *n;
E
Eric Dumazet 已提交
586
	unsigned int h;
L
Linus Torvalds 已提交
587

E
Eric Dumazet 已提交
588
	for (h = 0; h <= ht->divisor; h++) {
589 590 591
		while ((n = rtnl_dereference(ht->ht[h])) != NULL) {
			RCU_INIT_POINTER(ht->ht[h],
					 rtnl_dereference(n->next));
592
			tcf_unbind_filter(tp, &n->res);
593
			u32_remove_hw_knode(tp, n);
594
			idr_remove_ext(&ht->handle_idr, n->handle);
595 596 597 598
			if (tcf_exts_get_net(&n->exts))
				call_rcu(&n->rcu, u32_delete_key_freepf_rcu);
			else
				u32_destroy_key(n->tp, n, true);
L
Linus Torvalds 已提交
599 600 601 602 603 604 605
		}
	}
}

static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
{
	struct tc_u_common *tp_c = tp->data;
606 607
	struct tc_u_hnode __rcu **hn;
	struct tc_u_hnode *phn;
L
Linus Torvalds 已提交
608

609
	WARN_ON(ht->refcnt);
L
Linus Torvalds 已提交
610

611
	u32_clear_hnode(tp, ht);
L
Linus Torvalds 已提交
612

613 614 615 616 617
	hn = &tp_c->hlist;
	for (phn = rtnl_dereference(*hn);
	     phn;
	     hn = &phn->next, phn = rtnl_dereference(*hn)) {
		if (phn == ht) {
618
			u32_clear_hw_hnode(tp, ht);
619 620
			idr_destroy(&ht->handle_idr);
			idr_remove_ext(&tp_c->handle_idr, ht->handle);
621 622
			RCU_INIT_POINTER(*hn, ht->next);
			kfree_rcu(ht, rcu);
L
Linus Torvalds 已提交
623 624 625 626 627 628 629
			return 0;
		}
	}

	return -ENOENT;
}

630 631 632 633 634 635 636 637 638 639 640
static bool ht_empty(struct tc_u_hnode *ht)
{
	unsigned int h;

	for (h = 0; h <= ht->divisor; h++)
		if (rcu_access_pointer(ht->ht[h]))
			return false;

	return true;
}

641
static void u32_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
642 643
{
	struct tc_u_common *tp_c = tp->data;
644
	struct tc_u_hnode *root_ht = rtnl_dereference(tp->root);
L
Linus Torvalds 已提交
645

646
	WARN_ON(root_ht == NULL);
L
Linus Torvalds 已提交
647 648 649 650 651 652 653

	if (root_ht && --root_ht->refcnt == 0)
		u32_destroy_hnode(tp, root_ht);

	if (--tp_c->refcnt == 0) {
		struct tc_u_hnode *ht;

654
		hlist_del(&tp_c->hnode);
L
Linus Torvalds 已提交
655

656 657 658
		for (ht = rtnl_dereference(tp_c->hlist);
		     ht;
		     ht = rtnl_dereference(ht->next)) {
659
			ht->refcnt--;
660
			u32_clear_hnode(tp, ht);
661
		}
L
Linus Torvalds 已提交
662

663 664 665
		while ((ht = rtnl_dereference(tp_c->hlist)) != NULL) {
			RCU_INIT_POINTER(tp_c->hlist, ht->next);
			kfree_rcu(ht, rcu);
666
		}
L
Linus Torvalds 已提交
667

668
		idr_destroy(&tp_c->handle_idr);
L
Linus Torvalds 已提交
669 670 671 672 673 674
		kfree(tp_c);
	}

	tp->data = NULL;
}

675 676
static int u32_delete(struct tcf_proto *tp, void *arg, bool *last,
		      struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
677
{
678
	struct tc_u_hnode *ht = arg;
679
	struct tc_u_hnode *root_ht = rtnl_dereference(tp->root);
680 681
	struct tc_u_common *tp_c = tp->data;
	int ret = 0;
L
Linus Torvalds 已提交
682 683

	if (ht == NULL)
684
		goto out;
L
Linus Torvalds 已提交
685

686
	if (TC_U32_KEY(ht->handle)) {
687
		u32_remove_hw_knode(tp, (struct tc_u_knode *)ht);
688 689
		ret = u32_delete_key(tp, (struct tc_u_knode *)ht);
		goto out;
690
	}
L
Linus Torvalds 已提交
691

692 693
	if (root_ht == ht) {
		NL_SET_ERR_MSG_MOD(extack, "Not allowed to delete root node");
L
Linus Torvalds 已提交
694
		return -EINVAL;
695
	}
L
Linus Torvalds 已提交
696

697 698
	if (ht->refcnt == 1) {
		ht->refcnt--;
L
Linus Torvalds 已提交
699
		u32_destroy_hnode(tp, ht);
700
	} else {
701
		NL_SET_ERR_MSG_MOD(extack, "Can not delete in-use filter");
702 703
		return -EBUSY;
	}
L
Linus Torvalds 已提交
704

705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
out:
	*last = true;
	if (root_ht) {
		if (root_ht->refcnt > 1) {
			*last = false;
			goto ret;
		}
		if (root_ht->refcnt == 1) {
			if (!ht_empty(root_ht)) {
				*last = false;
				goto ret;
			}
		}
	}

	if (tp_c->refcnt > 1) {
		*last = false;
		goto ret;
	}

	if (tp_c->refcnt == 1) {
		struct tc_u_hnode *ht;

		for (ht = rtnl_dereference(tp_c->hlist);
		     ht;
		     ht = rtnl_dereference(ht->next))
			if (!ht_empty(ht)) {
				*last = false;
				break;
			}
	}

ret:
	return ret;
L
Linus Torvalds 已提交
739 740
}

741
static u32 gen_new_kid(struct tc_u_hnode *ht, u32 htid)
L
Linus Torvalds 已提交
742
{
743 744 745 746 747 748 749 750 751 752 753
	unsigned long idr_index;
	u32 start = htid | 0x800;
	u32 max = htid | 0xFFF;
	u32 min = htid;

	if (idr_alloc_ext(&ht->handle_idr, NULL, &idr_index,
			  start, max + 1, GFP_KERNEL)) {
		if (idr_alloc_ext(&ht->handle_idr, NULL, &idr_index,
				  min + 1, max + 1, GFP_KERNEL))
			return max;
	}
754

755
	return (u32)idr_index;
L
Linus Torvalds 已提交
756 757
}

758 759 760 761 762 763 764 765
static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
	[TCA_U32_CLASSID]	= { .type = NLA_U32 },
	[TCA_U32_HASH]		= { .type = NLA_U32 },
	[TCA_U32_LINK]		= { .type = NLA_U32 },
	[TCA_U32_DIVISOR]	= { .type = NLA_U32 },
	[TCA_U32_SEL]		= { .len = sizeof(struct tc_u32_sel) },
	[TCA_U32_INDEV]		= { .type = NLA_STRING, .len = IFNAMSIZ },
	[TCA_U32_MARK]		= { .len = sizeof(struct tc_u32_mark) },
766
	[TCA_U32_FLAGS]		= { .type = NLA_U32 },
767 768
};

769 770
static int u32_set_parms(struct net *net, struct tcf_proto *tp,
			 unsigned long base, struct tc_u_hnode *ht,
771
			 struct tc_u_knode *n, struct nlattr **tb,
772 773
			 struct nlattr *est, bool ovr,
			 struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
774
{
775
	int err;
L
Linus Torvalds 已提交
776

777
	err = tcf_exts_validate(net, tp, tb, est, &n->exts, ovr, extack);
L
Linus Torvalds 已提交
778 779 780
	if (err < 0)
		return err;

781
	if (tb[TCA_U32_LINK]) {
782
		u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
783
		struct tc_u_hnode *ht_down = NULL, *ht_old;
L
Linus Torvalds 已提交
784

785 786
		if (TC_U32_KEY(handle)) {
			NL_SET_ERR_MSG_MOD(extack, "u32 Link handle must be a hash table");
787
			return -EINVAL;
788
		}
L
Linus Torvalds 已提交
789 790 791 792

		if (handle) {
			ht_down = u32_lookup_ht(ht->tp_c, handle);

793 794
			if (!ht_down) {
				NL_SET_ERR_MSG_MOD(extack, "Link hash table not found");
795
				return -EINVAL;
796
			}
L
Linus Torvalds 已提交
797 798 799
			ht_down->refcnt++;
		}

800 801
		ht_old = rtnl_dereference(n->ht_down);
		rcu_assign_pointer(n->ht_down, ht_down);
L
Linus Torvalds 已提交
802

803 804
		if (ht_old)
			ht_old->refcnt--;
L
Linus Torvalds 已提交
805
	}
806
	if (tb[TCA_U32_CLASSID]) {
807
		n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
L
Linus Torvalds 已提交
808 809 810 811
		tcf_bind_filter(tp, &n->res, base);
	}

#ifdef CONFIG_NET_CLS_IND
812
	if (tb[TCA_U32_INDEV]) {
813
		int ret;
814
		ret = tcf_change_indev(net, tb[TCA_U32_INDEV], extack);
815
		if (ret < 0)
816
			return -EINVAL;
817
		n->ifindex = ret;
L
Linus Torvalds 已提交
818 819 820 821 822
	}
#endif
	return 0;
}

J
Jamal Hadi Salim 已提交
823
static void u32_replace_knode(struct tcf_proto *tp, struct tc_u_common *tp_c,
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
			      struct tc_u_knode *n)
{
	struct tc_u_knode __rcu **ins;
	struct tc_u_knode *pins;
	struct tc_u_hnode *ht;

	if (TC_U32_HTID(n->handle) == TC_U32_ROOT)
		ht = rtnl_dereference(tp->root);
	else
		ht = u32_lookup_ht(tp_c, TC_U32_HTID(n->handle));

	ins = &ht->ht[TC_U32_HASH(n->handle)];

	/* The node must always exist for it to be replaced if this is not the
	 * case then something went very wrong elsewhere.
	 */
	for (pins = rtnl_dereference(*ins); ;
	     ins = &pins->next, pins = rtnl_dereference(*ins))
		if (pins->handle == n->handle)
			break;

845
	idr_replace_ext(&ht->handle_idr, n, n->handle);
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
	RCU_INIT_POINTER(n->next, pins->next);
	rcu_assign_pointer(*ins, n);
}

static struct tc_u_knode *u32_init_knode(struct tcf_proto *tp,
					 struct tc_u_knode *n)
{
	struct tc_u_knode *new;
	struct tc_u32_sel *s = &n->sel;

	new = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key),
		      GFP_KERNEL);

	if (!new)
		return NULL;

	RCU_INIT_POINTER(new->next, n->next);
	new->handle = n->handle;
	RCU_INIT_POINTER(new->ht_up, n->ht_up);

#ifdef CONFIG_NET_CLS_IND
	new->ifindex = n->ifindex;
#endif
	new->fshift = n->fshift;
	new->res = n->res;
871
	new->flags = n->flags;
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
	RCU_INIT_POINTER(new->ht_down, n->ht_down);

	/* bump reference count as long as we hold pointer to structure */
	if (new->ht_down)
		new->ht_down->refcnt++;

#ifdef CONFIG_CLS_U32_PERF
	/* Statistics may be incremented by readers during update
	 * so we must keep them in tact. When the node is later destroyed
	 * a special destroy call must be made to not free the pf memory.
	 */
	new->pf = n->pf;
#endif

#ifdef CONFIG_CLS_U32_MARK
	new->val = n->val;
	new->mask = n->mask;
	/* Similarly success statistics must be moved as pointers */
	new->pcpu_success = n->pcpu_success;
#endif
	new->tp = tp;
	memcpy(&new->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));

895 896 897 898
	if (tcf_exts_init(&new->exts, TCA_U32_ACT, TCA_U32_POLICE)) {
		kfree(new);
		return NULL;
	}
899 900 901 902

	return new;
}

903
static int u32_change(struct net *net, struct sk_buff *in_skb,
904
		      struct tcf_proto *tp, unsigned long base, u32 handle,
905 906
		      struct nlattr **tca, void **arg, bool ovr,
		      struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
907 908 909 910 911
{
	struct tc_u_common *tp_c = tp->data;
	struct tc_u_hnode *ht;
	struct tc_u_knode *n;
	struct tc_u32_sel *s;
912 913
	struct nlattr *opt = tca[TCA_OPTIONS];
	struct nlattr *tb[TCA_U32_MAX + 1];
914
	u32 htid, flags = 0;
L
Linus Torvalds 已提交
915
	int err;
916 917 918
#ifdef CONFIG_CLS_U32_PERF
	size_t size;
#endif
L
Linus Torvalds 已提交
919

920 921 922 923 924 925 926 927
	if (!opt) {
		if (handle) {
			NL_SET_ERR_MSG_MOD(extack, "Filter handle requires options");
			return -EINVAL;
		} else {
			return 0;
		}
	}
L
Linus Torvalds 已提交
928

929
	err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, extack);
930 931
	if (err < 0)
		return err;
L
Linus Torvalds 已提交
932

933
	if (tb[TCA_U32_FLAGS]) {
934
		flags = nla_get_u32(tb[TCA_U32_FLAGS]);
935 936
		if (!tc_flags_valid(flags)) {
			NL_SET_ERR_MSG_MOD(extack, "Invalid filter flags");
937
			return -EINVAL;
938
		}
939
	}
940

941
	n = *arg;
E
Eric Dumazet 已提交
942
	if (n) {
943 944
		struct tc_u_knode *new;

945 946
		if (TC_U32_KEY(n->handle) == 0) {
			NL_SET_ERR_MSG_MOD(extack, "Key node id cannot be zero");
L
Linus Torvalds 已提交
947
			return -EINVAL;
948
		}
L
Linus Torvalds 已提交
949

950 951
		if (n->flags != flags) {
			NL_SET_ERR_MSG_MOD(extack, "Key node flags do not match passed flags");
952
			return -EINVAL;
953
		}
954

955 956 957 958 959 960
		new = u32_init_knode(tp, n);
		if (!new)
			return -ENOMEM;

		err = u32_set_parms(net, tp, base,
				    rtnl_dereference(n->ht_up), new, tb,
961
				    tca[TCA_RATE], ovr, extack);
962 963 964 965 966 967

		if (err) {
			u32_destroy_key(tp, new, false);
			return err;
		}

968
		err = u32_replace_hw_knode(tp, new, flags, extack);
969 970 971 972 973
		if (err) {
			u32_destroy_key(tp, new, false);
			return err;
		}

974 975 976
		if (!tc_in_hw(new->flags))
			new->flags |= TCA_CLS_FLAGS_NOT_IN_HW;

977
		u32_replace_knode(tp, tp_c, new);
978
		tcf_unbind_filter(tp, &n->res);
979
		tcf_exts_get_net(&n->exts);
980 981
		call_rcu(&n->rcu, u32_delete_key_rcu);
		return 0;
L
Linus Torvalds 已提交
982 983
	}

984
	if (tb[TCA_U32_DIVISOR]) {
E
Eric Dumazet 已提交
985
		unsigned int divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
L
Linus Torvalds 已提交
986

987 988
		if (--divisor > 0x100) {
			NL_SET_ERR_MSG_MOD(extack, "Exceeded maximum 256 hash buckets");
L
Linus Torvalds 已提交
989
			return -EINVAL;
990 991 992
		}
		if (TC_U32_KEY(handle)) {
			NL_SET_ERR_MSG_MOD(extack, "Divisor can only be used on a hash table");
L
Linus Torvalds 已提交
993
			return -EINVAL;
994
		}
E
Eric Dumazet 已提交
995
		ht = kzalloc(sizeof(*ht) + divisor*sizeof(void *), GFP_KERNEL);
L
Linus Torvalds 已提交
996 997
		if (ht == NULL)
			return -ENOBUFS;
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
		if (handle == 0) {
			handle = gen_new_htid(tp->data, ht);
			if (handle == 0) {
				kfree(ht);
				return -ENOMEM;
			}
		} else {
			err = idr_alloc_ext(&tp_c->handle_idr, ht, NULL,
					    handle, handle + 1, GFP_KERNEL);
			if (err) {
				kfree(ht);
				return err;
			}
		}
L
Linus Torvalds 已提交
1012
		ht->tp_c = tp_c;
1013
		ht->refcnt = 1;
L
Linus Torvalds 已提交
1014 1015 1016
		ht->divisor = divisor;
		ht->handle = handle;
		ht->prio = tp->prio;
1017
		idr_init(&ht->handle_idr);
1018

1019
		err = u32_replace_hw_hnode(tp, ht, flags, extack);
1020
		if (err) {
1021
			idr_remove_ext(&tp_c->handle_idr, handle);
1022 1023 1024 1025
			kfree(ht);
			return err;
		}

1026 1027
		RCU_INIT_POINTER(ht->next, tp_c->hlist);
		rcu_assign_pointer(tp_c->hlist, ht);
1028
		*arg = ht;
1029

L
Linus Torvalds 已提交
1030 1031 1032
		return 0;
	}

1033
	if (tb[TCA_U32_HASH]) {
1034
		htid = nla_get_u32(tb[TCA_U32_HASH]);
L
Linus Torvalds 已提交
1035
		if (TC_U32_HTID(htid) == TC_U32_ROOT) {
1036
			ht = rtnl_dereference(tp->root);
L
Linus Torvalds 已提交
1037 1038 1039
			htid = ht->handle;
		} else {
			ht = u32_lookup_ht(tp->data, TC_U32_HTID(htid));
1040 1041
			if (!ht) {
				NL_SET_ERR_MSG_MOD(extack, "Specified hash table not found");
L
Linus Torvalds 已提交
1042
				return -EINVAL;
1043
			}
L
Linus Torvalds 已提交
1044 1045
		}
	} else {
1046
		ht = rtnl_dereference(tp->root);
L
Linus Torvalds 已提交
1047 1048 1049
		htid = ht->handle;
	}

1050 1051
	if (ht->divisor < TC_U32_HASH(htid)) {
		NL_SET_ERR_MSG_MOD(extack, "Specified hash table buckets exceed configured value");
L
Linus Torvalds 已提交
1052
		return -EINVAL;
1053
	}
L
Linus Torvalds 已提交
1054 1055

	if (handle) {
1056 1057
		if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) {
			NL_SET_ERR_MSG_MOD(extack, "Handle specified hash table address mismatch");
L
Linus Torvalds 已提交
1058
			return -EINVAL;
1059
		}
L
Linus Torvalds 已提交
1060
		handle = htid | TC_U32_NODE(handle);
1061 1062 1063 1064 1065
		err = idr_alloc_ext(&ht->handle_idr, NULL, NULL,
				    handle, handle + 1,
				    GFP_KERNEL);
		if (err)
			return err;
L
Linus Torvalds 已提交
1066 1067 1068
	} else
		handle = gen_new_kid(ht, htid);

1069
	if (tb[TCA_U32_SEL] == NULL) {
1070
		NL_SET_ERR_MSG_MOD(extack, "Selector not specified");
1071 1072 1073
		err = -EINVAL;
		goto erridr;
	}
L
Linus Torvalds 已提交
1074

1075
	s = nla_data(tb[TCA_U32_SEL]);
L
Linus Torvalds 已提交
1076

1077
	n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
1078 1079 1080 1081
	if (n == NULL) {
		err = -ENOBUFS;
		goto erridr;
	}
L
Linus Torvalds 已提交
1082 1083

#ifdef CONFIG_CLS_U32_PERF
1084 1085 1086
	size = sizeof(struct tc_u32_pcnt) + s->nkeys * sizeof(u64);
	n->pf = __alloc_percpu(size, __alignof__(struct tc_u32_pcnt));
	if (!n->pf) {
1087 1088
		err = -ENOBUFS;
		goto errfree;
L
Linus Torvalds 已提交
1089 1090 1091 1092
	}
#endif

	memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
1093
	RCU_INIT_POINTER(n->ht_up, ht);
L
Linus Torvalds 已提交
1094
	n->handle = handle;
1095
	n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
1096
	n->flags = flags;
1097
	n->tp = tp;
L
Linus Torvalds 已提交
1098

1099 1100 1101 1102
	err = tcf_exts_init(&n->exts, TCA_U32_ACT, TCA_U32_POLICE);
	if (err < 0)
		goto errout;

L
Linus Torvalds 已提交
1103
#ifdef CONFIG_CLS_U32_MARK
1104
	n->pcpu_success = alloc_percpu(u32);
1105 1106 1107 1108
	if (!n->pcpu_success) {
		err = -ENOMEM;
		goto errout;
	}
1109

1110
	if (tb[TCA_U32_MARK]) {
L
Linus Torvalds 已提交
1111 1112
		struct tc_u32_mark *mark;

1113
		mark = nla_data(tb[TCA_U32_MARK]);
1114 1115
		n->val = mark->val;
		n->mask = mark->mask;
L
Linus Torvalds 已提交
1116 1117 1118
	}
#endif

1119 1120
	err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr,
			    extack);
L
Linus Torvalds 已提交
1121
	if (err == 0) {
1122 1123 1124
		struct tc_u_knode __rcu **ins;
		struct tc_u_knode *pins;

1125
		err = u32_replace_hw_knode(tp, n, flags, extack);
1126 1127 1128
		if (err)
			goto errhw;

1129 1130 1131
		if (!tc_in_hw(n->flags))
			n->flags |= TCA_CLS_FLAGS_NOT_IN_HW;

1132 1133 1134 1135
		ins = &ht->ht[TC_U32_HASH(handle)];
		for (pins = rtnl_dereference(*ins); pins;
		     ins = &pins->next, pins = rtnl_dereference(*ins))
			if (TC_U32_NODE(handle) < TC_U32_NODE(pins->handle))
L
Linus Torvalds 已提交
1136 1137
				break;

1138 1139
		RCU_INIT_POINTER(n->next, pins);
		rcu_assign_pointer(*ins, n);
1140
		*arg = n;
L
Linus Torvalds 已提交
1141 1142
		return 0;
	}
1143

1144
errhw:
1145 1146 1147 1148
#ifdef CONFIG_CLS_U32_MARK
	free_percpu(n->pcpu_success);
#endif

1149 1150
errout:
	tcf_exts_destroy(&n->exts);
L
Linus Torvalds 已提交
1151
#ifdef CONFIG_CLS_U32_PERF
1152
errfree:
1153
	free_percpu(n->pf);
L
Linus Torvalds 已提交
1154 1155
#endif
	kfree(n);
1156 1157
erridr:
	idr_remove_ext(&ht->handle_idr, handle);
L
Linus Torvalds 已提交
1158 1159 1160 1161 1162 1163 1164 1165
	return err;
}

static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg)
{
	struct tc_u_common *tp_c = tp->data;
	struct tc_u_hnode *ht;
	struct tc_u_knode *n;
E
Eric Dumazet 已提交
1166
	unsigned int h;
L
Linus Torvalds 已提交
1167 1168 1169 1170

	if (arg->stop)
		return;

1171 1172 1173
	for (ht = rtnl_dereference(tp_c->hlist);
	     ht;
	     ht = rtnl_dereference(ht->next)) {
L
Linus Torvalds 已提交
1174 1175 1176
		if (ht->prio != tp->prio)
			continue;
		if (arg->count >= arg->skip) {
1177
			if (arg->fn(tp, ht, arg) < 0) {
L
Linus Torvalds 已提交
1178 1179 1180 1181 1182 1183
				arg->stop = 1;
				return;
			}
		}
		arg->count++;
		for (h = 0; h <= ht->divisor; h++) {
1184 1185 1186
			for (n = rtnl_dereference(ht->ht[h]);
			     n;
			     n = rtnl_dereference(n->next)) {
L
Linus Torvalds 已提交
1187 1188 1189 1190
				if (arg->count < arg->skip) {
					arg->count++;
					continue;
				}
1191
				if (arg->fn(tp, n, arg) < 0) {
L
Linus Torvalds 已提交
1192 1193 1194 1195 1196 1197 1198 1199 1200
					arg->stop = 1;
					return;
				}
				arg->count++;
			}
		}
	}
}

1201 1202 1203 1204 1205 1206 1207 1208
static void u32_bind_class(void *fh, u32 classid, unsigned long cl)
{
	struct tc_u_knode *n = fh;

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

1209
static int u32_dump(struct net *net, struct tcf_proto *tp, void *fh,
J
Jamal Hadi Salim 已提交
1210
		    struct sk_buff *skb, struct tcmsg *t)
L
Linus Torvalds 已提交
1211
{
1212
	struct tc_u_knode *n = fh;
1213
	struct tc_u_hnode *ht_up, *ht_down;
1214
	struct nlattr *nest;
L
Linus Torvalds 已提交
1215 1216 1217 1218 1219 1220

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

	t->tcm_handle = n->handle;

1221 1222 1223
	nest = nla_nest_start(skb, TCA_OPTIONS);
	if (nest == NULL)
		goto nla_put_failure;
L
Linus Torvalds 已提交
1224 1225

	if (TC_U32_KEY(n->handle) == 0) {
1226
		struct tc_u_hnode *ht = fh;
E
Eric Dumazet 已提交
1227 1228
		u32 divisor = ht->divisor + 1;

1229 1230
		if (nla_put_u32(skb, TCA_U32_DIVISOR, divisor))
			goto nla_put_failure;
L
Linus Torvalds 已提交
1231
	} else {
1232 1233 1234
#ifdef CONFIG_CLS_U32_PERF
		struct tc_u32_pcnt *gpf;
		int cpu;
1235
#endif
1236

1237 1238 1239 1240
		if (nla_put(skb, TCA_U32_SEL,
			    sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key),
			    &n->sel))
			goto nla_put_failure;
1241 1242 1243

		ht_up = rtnl_dereference(n->ht_up);
		if (ht_up) {
L
Linus Torvalds 已提交
1244
			u32 htid = n->handle & 0xFFFFF000;
1245 1246
			if (nla_put_u32(skb, TCA_U32_HASH, htid))
				goto nla_put_failure;
L
Linus Torvalds 已提交
1247
		}
1248 1249 1250
		if (n->res.classid &&
		    nla_put_u32(skb, TCA_U32_CLASSID, n->res.classid))
			goto nla_put_failure;
1251 1252 1253 1254

		ht_down = rtnl_dereference(n->ht_down);
		if (ht_down &&
		    nla_put_u32(skb, TCA_U32_LINK, ht_down->handle))
1255
			goto nla_put_failure;
L
Linus Torvalds 已提交
1256

1257 1258 1259
		if (n->flags && nla_put_u32(skb, TCA_U32_FLAGS, n->flags))
			goto nla_put_failure;

L
Linus Torvalds 已提交
1260
#ifdef CONFIG_CLS_U32_MARK
1261 1262 1263 1264
		if ((n->val || n->mask)) {
			struct tc_u32_mark mark = {.val = n->val,
						   .mask = n->mask,
						   .success = 0};
1265
			int cpum;
1266

1267 1268
			for_each_possible_cpu(cpum) {
				__u32 cnt = *per_cpu_ptr(n->pcpu_success, cpum);
1269 1270 1271 1272 1273 1274 1275

				mark.success += cnt;
			}

			if (nla_put(skb, TCA_U32_MARK, sizeof(mark), &mark))
				goto nla_put_failure;
		}
L
Linus Torvalds 已提交
1276 1277
#endif

1278
		if (tcf_exts_dump(skb, &n->exts) < 0)
1279
			goto nla_put_failure;
L
Linus Torvalds 已提交
1280 1281

#ifdef CONFIG_NET_CLS_IND
1282 1283 1284 1285 1286 1287
		if (n->ifindex) {
			struct net_device *dev;
			dev = __dev_get_by_index(net, n->ifindex);
			if (dev && nla_put_string(skb, TCA_U32_INDEV, dev->name))
				goto nla_put_failure;
		}
L
Linus Torvalds 已提交
1288 1289
#endif
#ifdef CONFIG_CLS_U32_PERF
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
		gpf = kzalloc(sizeof(struct tc_u32_pcnt) +
			      n->sel.nkeys * sizeof(u64),
			      GFP_KERNEL);
		if (!gpf)
			goto nla_put_failure;

		for_each_possible_cpu(cpu) {
			int i;
			struct tc_u32_pcnt *pf = per_cpu_ptr(n->pf, cpu);

			gpf->rcnt += pf->rcnt;
			gpf->rhit += pf->rhit;
			for (i = 0; i < n->sel.nkeys; i++)
				gpf->kcnts[i] += pf->kcnts[i];
		}

1306 1307 1308 1309
		if (nla_put_64bit(skb, TCA_U32_PCNT,
				  sizeof(struct tc_u32_pcnt) +
				  n->sel.nkeys * sizeof(u64),
				  gpf, TCA_U32_PAD)) {
1310
			kfree(gpf);
1311
			goto nla_put_failure;
1312 1313
		}
		kfree(gpf);
L
Linus Torvalds 已提交
1314 1315 1316
#endif
	}

1317 1318
	nla_nest_end(skb, nest);

L
Linus Torvalds 已提交
1319
	if (TC_U32_KEY(n->handle))
1320
		if (tcf_exts_dump_stats(skb, &n->exts) < 0)
1321
			goto nla_put_failure;
L
Linus Torvalds 已提交
1322 1323
	return skb->len;

1324
nla_put_failure:
1325
	nla_nest_cancel(skb, nest);
L
Linus Torvalds 已提交
1326 1327 1328
	return -1;
}

1329
static struct tcf_proto_ops cls_u32_ops __read_mostly = {
L
Linus Torvalds 已提交
1330 1331 1332 1333 1334 1335 1336 1337 1338
	.kind		=	"u32",
	.classify	=	u32_classify,
	.init		=	u32_init,
	.destroy	=	u32_destroy,
	.get		=	u32_get,
	.change		=	u32_change,
	.delete		=	u32_delete,
	.walk		=	u32_walk,
	.dump		=	u32_dump,
1339
	.bind_class	=	u32_bind_class,
L
Linus Torvalds 已提交
1340 1341 1342 1343 1344
	.owner		=	THIS_MODULE,
};

static int __init init_u32(void)
{
1345 1346
	int i, ret;

1347
	pr_info("u32 classifier\n");
L
Linus Torvalds 已提交
1348
#ifdef CONFIG_CLS_U32_PERF
1349
	pr_info("    Performance counters on\n");
L
Linus Torvalds 已提交
1350 1351
#endif
#ifdef CONFIG_NET_CLS_IND
1352
	pr_info("    input device check on\n");
L
Linus Torvalds 已提交
1353 1354
#endif
#ifdef CONFIG_NET_CLS_ACT
1355
	pr_info("    Actions configured\n");
L
Linus Torvalds 已提交
1356
#endif
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
	tc_u_common_hash = kvmalloc_array(U32_HASH_SIZE,
					  sizeof(struct hlist_head),
					  GFP_KERNEL);
	if (!tc_u_common_hash)
		return -ENOMEM;

	for (i = 0; i < U32_HASH_SIZE; i++)
		INIT_HLIST_HEAD(&tc_u_common_hash[i]);

	ret = register_tcf_proto_ops(&cls_u32_ops);
	if (ret)
		kvfree(tc_u_common_hash);
	return ret;
L
Linus Torvalds 已提交
1370 1371
}

1372
static void __exit exit_u32(void)
L
Linus Torvalds 已提交
1373 1374
{
	unregister_tcf_proto_ops(&cls_u32_ops);
1375
	kvfree(tc_u_common_hash);
L
Linus Torvalds 已提交
1376 1377 1378 1379 1380
}

module_init(init_u32)
module_exit(exit_u32)
MODULE_LICENSE("GPL");