xref: /openbmc/linux/net/sched/em_nbyte.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * net/sched/em_nbyte.c	N-Byte ematch
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
5*1da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
6*1da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
7*1da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
8*1da177e4SLinus Torvalds  *
9*1da177e4SLinus Torvalds  * Authors:	Thomas Graf <tgraf@suug.ch>
10*1da177e4SLinus Torvalds  */
11*1da177e4SLinus Torvalds 
12*1da177e4SLinus Torvalds #include <linux/config.h>
13*1da177e4SLinus Torvalds #include <linux/module.h>
14*1da177e4SLinus Torvalds #include <linux/types.h>
15*1da177e4SLinus Torvalds #include <linux/kernel.h>
16*1da177e4SLinus Torvalds #include <linux/sched.h>
17*1da177e4SLinus Torvalds #include <linux/string.h>
18*1da177e4SLinus Torvalds #include <linux/skbuff.h>
19*1da177e4SLinus Torvalds #include <linux/tc_ematch/tc_em_nbyte.h>
20*1da177e4SLinus Torvalds #include <net/pkt_cls.h>
21*1da177e4SLinus Torvalds 
22*1da177e4SLinus Torvalds struct nbyte_data
23*1da177e4SLinus Torvalds {
24*1da177e4SLinus Torvalds 	struct tcf_em_nbyte	hdr;
25*1da177e4SLinus Torvalds 	char			pattern[0];
26*1da177e4SLinus Torvalds };
27*1da177e4SLinus Torvalds 
28*1da177e4SLinus Torvalds static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len,
29*1da177e4SLinus Torvalds 			   struct tcf_ematch *em)
30*1da177e4SLinus Torvalds {
31*1da177e4SLinus Torvalds 	struct tcf_em_nbyte *nbyte = data;
32*1da177e4SLinus Torvalds 
33*1da177e4SLinus Torvalds 	if (data_len < sizeof(*nbyte) ||
34*1da177e4SLinus Torvalds 	    data_len < (sizeof(*nbyte) + nbyte->len))
35*1da177e4SLinus Torvalds 		return -EINVAL;
36*1da177e4SLinus Torvalds 
37*1da177e4SLinus Torvalds 	em->datalen = sizeof(*nbyte) + nbyte->len;
38*1da177e4SLinus Torvalds 	em->data = (unsigned long) kmalloc(em->datalen, GFP_KERNEL);
39*1da177e4SLinus Torvalds 	if (em->data == 0UL)
40*1da177e4SLinus Torvalds 		return -ENOBUFS;
41*1da177e4SLinus Torvalds 
42*1da177e4SLinus Torvalds 	memcpy((void *) em->data, data, em->datalen);
43*1da177e4SLinus Torvalds 
44*1da177e4SLinus Torvalds 	return 0;
45*1da177e4SLinus Torvalds }
46*1da177e4SLinus Torvalds 
47*1da177e4SLinus Torvalds static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em,
48*1da177e4SLinus Torvalds 			  struct tcf_pkt_info *info)
49*1da177e4SLinus Torvalds {
50*1da177e4SLinus Torvalds 	struct nbyte_data *nbyte = (struct nbyte_data *) em->data;
51*1da177e4SLinus Torvalds 	unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer);
52*1da177e4SLinus Torvalds 
53*1da177e4SLinus Torvalds 	ptr += nbyte->hdr.off;
54*1da177e4SLinus Torvalds 
55*1da177e4SLinus Torvalds 	if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len))
56*1da177e4SLinus Torvalds 		return 0;
57*1da177e4SLinus Torvalds 
58*1da177e4SLinus Torvalds 	return !memcmp(ptr + nbyte->hdr.off, nbyte->pattern, nbyte->hdr.len);
59*1da177e4SLinus Torvalds }
60*1da177e4SLinus Torvalds 
61*1da177e4SLinus Torvalds static struct tcf_ematch_ops em_nbyte_ops = {
62*1da177e4SLinus Torvalds 	.kind	  = TCF_EM_NBYTE,
63*1da177e4SLinus Torvalds 	.change	  = em_nbyte_change,
64*1da177e4SLinus Torvalds 	.match	  = em_nbyte_match,
65*1da177e4SLinus Torvalds 	.owner	  = THIS_MODULE,
66*1da177e4SLinus Torvalds 	.link	  = LIST_HEAD_INIT(em_nbyte_ops.link)
67*1da177e4SLinus Torvalds };
68*1da177e4SLinus Torvalds 
69*1da177e4SLinus Torvalds static int __init init_em_nbyte(void)
70*1da177e4SLinus Torvalds {
71*1da177e4SLinus Torvalds 	return tcf_em_register(&em_nbyte_ops);
72*1da177e4SLinus Torvalds }
73*1da177e4SLinus Torvalds 
74*1da177e4SLinus Torvalds static void __exit exit_em_nbyte(void)
75*1da177e4SLinus Torvalds {
76*1da177e4SLinus Torvalds 	tcf_em_unregister(&em_nbyte_ops);
77*1da177e4SLinus Torvalds }
78*1da177e4SLinus Torvalds 
79*1da177e4SLinus Torvalds MODULE_LICENSE("GPL");
80*1da177e4SLinus Torvalds 
81*1da177e4SLinus Torvalds module_init(init_em_nbyte);
82*1da177e4SLinus Torvalds module_exit(exit_em_nbyte);
83