[PKT_SCHED]: Packet classification based on textsearch (ematch)

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Thomas Graf and committed by David S. Miller d675c989 3fc7e8a6

+194 -2
+1
include/linux/pkt_cls.h
··· 408 TCF_EM_NBYTE, 409 TCF_EM_U32, 410 TCF_EM_META, 411 __TCF_EM_MAX 412 }; 413
··· 408 TCF_EM_NBYTE, 409 TCF_EM_U32, 410 TCF_EM_META, 411 + TCF_EM_TEXT, 412 __TCF_EM_MAX 413 }; 414
+5 -2
include/linux/rtnetlink.h
··· 892 goto rtattr_failure; \ 893 __rta_fill(skb, attrtype, attrlen, data); }) 894 895 - #define RTA_PUT_NOHDR(skb, attrlen, data) \ 896 ({ if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \ 897 goto rtattr_failure; \ 898 - memcpy(skb_put(skb, RTA_ALIGN(attrlen)), data, attrlen); }) 899 900 #define RTA_PUT_U8(skb, attrtype, value) \ 901 ({ u8 _tmp = (value); \
··· 892 goto rtattr_failure; \ 893 __rta_fill(skb, attrtype, attrlen, data); }) 894 895 + #define RTA_APPEND(skb, attrlen, data) \ 896 ({ if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \ 897 goto rtattr_failure; \ 898 + memcpy(skb_put(skb, attrlen), data, attrlen); }) 899 + 900 + #define RTA_PUT_NOHDR(skb, attrlen, data) \ 901 + RTA_APPEND(skb, RTA_ALIGN(attrlen), data) 902 903 #define RTA_PUT_U8(skb, attrtype, value) \ 904 ({ u8 _tmp = (value); \
+19
include/linux/tc_ematch/tc_em_text.h
···
··· 1 + #ifndef __LINUX_TC_EM_TEXT_H 2 + #define __LINUX_TC_EM_TEXT_H 3 + 4 + #include <linux/pkt_cls.h> 5 + 6 + #define TC_EM_TEXT_ALGOSIZ 16 7 + 8 + struct tcf_em_text 9 + { 10 + char algo[TC_EM_TEXT_ALGOSIZ]; 11 + __u16 from_offset; 12 + __u16 to_offset; 13 + __u16 pattern_len; 14 + __u8 from_layer:4; 15 + __u8 to_layer:4; 16 + __u8 pad; 17 + }; 18 + 19 + #endif
+11
net/sched/Kconfig
··· 449 To compile this code as a module, choose M here: the 450 module will be called em_meta. 451 452 config NET_CLS_ACT 453 bool "Packet ACTION" 454 depends on EXPERIMENTAL && NET_CLS && NET_QOS
··· 449 To compile this code as a module, choose M here: the 450 module will be called em_meta. 451 452 + config NET_EMATCH_TEXT 453 + tristate "Textsearch" 454 + depends on NET_EMATCH 455 + ---help--- 456 + Say Y here if you want to be ablt to classify packets based on 457 + textsearch comparisons. Please select the appropriate textsearch 458 + algorithms in the Library section. 459 + 460 + To compile this code as a module, choose M here: the 461 + module will be called em_text. 462 + 463 config NET_CLS_ACT 464 bool "Packet ACTION" 465 depends on EXPERIMENTAL && NET_CLS && NET_QOS
+1
net/sched/Makefile
··· 40 obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o 41 obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o 42 obj-$(CONFIG_NET_EMATCH_META) += em_meta.o
··· 40 obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o 41 obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o 42 obj-$(CONFIG_NET_EMATCH_META) += em_meta.o 43 + obj-$(CONFIG_NET_EMATCH_TEXT) += em_text.o
+157
net/sched/em_text.c
···
··· 1 + /* 2 + * net/sched/em_text.c Textsearch ematch 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation; either version 7 + * 2 of the License, or (at your option) any later version. 8 + * 9 + * Authors: Thomas Graf <tgraf@suug.ch> 10 + */ 11 + 12 + #include <linux/config.h> 13 + #include <linux/module.h> 14 + #include <linux/types.h> 15 + #include <linux/kernel.h> 16 + #include <linux/sched.h> 17 + #include <linux/string.h> 18 + #include <linux/skbuff.h> 19 + #include <linux/textsearch.h> 20 + #include <linux/tc_ematch/tc_em_text.h> 21 + #include <net/pkt_cls.h> 22 + 23 + struct text_match 24 + { 25 + u16 from_offset; 26 + u16 to_offset; 27 + u8 from_layer; 28 + u8 to_layer; 29 + struct ts_config *config; 30 + }; 31 + 32 + #define EM_TEXT_PRIV(m) ((struct text_match *) (m)->data) 33 + 34 + static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m, 35 + struct tcf_pkt_info *info) 36 + { 37 + struct text_match *tm = EM_TEXT_PRIV(m); 38 + int from, to; 39 + struct ts_state state; 40 + 41 + from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data; 42 + from += tm->from_offset; 43 + 44 + to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data; 45 + to += tm->to_offset; 46 + 47 + return skb_find_text(skb, from, to, tm->config, &state) != UINT_MAX; 48 + } 49 + 50 + static int em_text_change(struct tcf_proto *tp, void *data, int len, 51 + struct tcf_ematch *m) 52 + { 53 + struct text_match *tm; 54 + struct tcf_em_text *conf = data; 55 + struct ts_config *ts_conf; 56 + int flags = 0; 57 + 58 + printk("Configuring text: %s from %d:%d to %d:%d len %d\n", conf->algo, conf->from_offset, 59 + conf->from_layer, conf->to_offset, conf->to_layer, conf->pattern_len); 60 + 61 + if (len < sizeof(*conf) || len < (sizeof(*conf) + conf->pattern_len)) 62 + return -EINVAL; 63 + 64 + if (conf->from_layer > conf->to_layer) 65 + return -EINVAL; 66 + 67 + if (conf->from_layer == conf->to_layer && 68 + conf->from_offset > conf->to_offset) 69 + return -EINVAL; 70 + 71 + retry: 72 + ts_conf = textsearch_prepare(conf->algo, (u8 *) conf + sizeof(*conf), 73 + conf->pattern_len, GFP_KERNEL, flags); 74 + 75 + if (flags & TS_AUTOLOAD) 76 + rtnl_lock(); 77 + 78 + if (IS_ERR(ts_conf)) { 79 + if (PTR_ERR(ts_conf) == -ENOENT && !(flags & TS_AUTOLOAD)) { 80 + rtnl_unlock(); 81 + flags |= TS_AUTOLOAD; 82 + goto retry; 83 + } else 84 + return PTR_ERR(ts_conf); 85 + } else if (flags & TS_AUTOLOAD) { 86 + textsearch_destroy(ts_conf); 87 + return -EAGAIN; 88 + } 89 + 90 + tm = kmalloc(sizeof(*tm), GFP_KERNEL); 91 + if (tm == NULL) { 92 + textsearch_destroy(ts_conf); 93 + return -ENOBUFS; 94 + } 95 + 96 + tm->from_offset = conf->from_offset; 97 + tm->to_offset = conf->to_offset; 98 + tm->from_layer = conf->from_layer; 99 + tm->to_layer = conf->to_layer; 100 + tm->config = ts_conf; 101 + 102 + m->datalen = sizeof(*tm); 103 + m->data = (unsigned long) tm; 104 + 105 + return 0; 106 + } 107 + 108 + static void em_text_destroy(struct tcf_proto *tp, struct tcf_ematch *m) 109 + { 110 + textsearch_destroy(EM_TEXT_PRIV(m)->config); 111 + } 112 + 113 + static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m) 114 + { 115 + struct text_match *tm = EM_TEXT_PRIV(m); 116 + struct tcf_em_text conf; 117 + 118 + strncpy(conf.algo, tm->config->ops->name, sizeof(conf.algo) - 1); 119 + conf.from_offset = tm->from_offset; 120 + conf.to_offset = tm->to_offset; 121 + conf.from_layer = tm->from_layer; 122 + conf.to_layer = tm->to_layer; 123 + conf.pattern_len = textsearch_get_pattern_len(tm->config); 124 + conf.pad = 0; 125 + 126 + RTA_PUT_NOHDR(skb, sizeof(conf), &conf); 127 + RTA_APPEND(skb, conf.pattern_len, textsearch_get_pattern(tm->config)); 128 + return 0; 129 + 130 + rtattr_failure: 131 + return -1; 132 + } 133 + 134 + static struct tcf_ematch_ops em_text_ops = { 135 + .kind = TCF_EM_TEXT, 136 + .change = em_text_change, 137 + .match = em_text_match, 138 + .destroy = em_text_destroy, 139 + .dump = em_text_dump, 140 + .owner = THIS_MODULE, 141 + .link = LIST_HEAD_INIT(em_text_ops.link) 142 + }; 143 + 144 + static int __init init_em_text(void) 145 + { 146 + return tcf_em_register(&em_text_ops); 147 + } 148 + 149 + static void __exit exit_em_text(void) 150 + { 151 + tcf_em_unregister(&em_text_ops); 152 + } 153 + 154 + MODULE_LICENSE("GPL"); 155 + 156 + module_init(init_em_text); 157 + module_exit(exit_em_text);