X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fnet%2Fpkt_cls.h;h=d12ad3831d14743e230903da099dc40b2719ce47;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=4de3ea73ca5d1bdc6e91a1278b1bc7f2dd04039c;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 4de3ea73c..d12ad3831 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -1,36 +1,12 @@ #ifndef __NET_PKT_CLS_H #define __NET_PKT_CLS_H - #include - -struct rtattr; -struct tcmsg; +#include +#include /* Basic packet classifier frontend definitions. */ -struct tcf_result -{ - unsigned long class; - u32 classid; -}; - -struct tcf_proto -{ - /* Fast access part */ - struct tcf_proto *next; - void *root; - int (*classify)(struct sk_buff*, struct tcf_proto*, struct tcf_result *); - u32 protocol; - - /* All the rest */ - u32 prio; - u32 classid; - struct Qdisc *q; - void *data; - struct tcf_proto_ops *ops; -}; - struct tcf_walker { int stop; @@ -39,86 +15,160 @@ struct tcf_walker int (*fn)(struct tcf_proto *, unsigned long node, struct tcf_walker *); }; -struct module; +extern int register_tcf_proto_ops(struct tcf_proto_ops *ops); +extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops); -struct tcf_proto_ops +static inline unsigned long +__cls_set_class(unsigned long *clp, unsigned long cl) { - struct tcf_proto_ops *next; - char kind[IFNAMSIZ]; + unsigned long old_cl; + + old_cl = *clp; + *clp = cl; + return old_cl; +} - int (*classify)(struct sk_buff*, struct tcf_proto*, struct tcf_result *); - int (*init)(struct tcf_proto*); - void (*destroy)(struct tcf_proto*); +static inline unsigned long +cls_set_class(struct tcf_proto *tp, unsigned long *clp, + unsigned long cl) +{ + unsigned long old_cl; + + tcf_tree_lock(tp); + old_cl = __cls_set_class(clp, cl); + tcf_tree_unlock(tp); + + return old_cl; +} - unsigned long (*get)(struct tcf_proto*, u32 handle); - void (*put)(struct tcf_proto*, unsigned long); - int (*change)(struct tcf_proto*, unsigned long, u32 handle, struct rtattr **, unsigned long *); - int (*delete)(struct tcf_proto*, unsigned long); - void (*walk)(struct tcf_proto*, struct tcf_walker *arg); +static inline void +tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base) +{ + unsigned long cl; - /* rtnetlink specific */ - int (*dump)(struct tcf_proto*, unsigned long, struct sk_buff *skb, struct tcmsg*); + cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, r->classid); + cl = cls_set_class(tp, &r->class, cl); + if (cl) + tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); +} - struct module *owner; -}; +static inline void +tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r) +{ + unsigned long cl; -/* Main classifier routine: scans classifier chain attached - to this qdisc, (optionally) tests for protocol and asks - specific classifiers. - */ + if ((cl = __cls_set_class(&r->class, 0)) != 0) + tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); +} -static inline int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res) +struct tcf_exts { - int err = 0; - u32 protocol = skb->protocol; #ifdef CONFIG_NET_CLS_ACT - struct tcf_proto *otp = tp; -reclassify: + struct tc_action *action; +#elif defined CONFIG_NET_CLS_POLICE + struct tcf_police *police; #endif - protocol = skb->protocol; +}; - for ( ; tp; tp = tp->next) { - if ((tp->protocol == protocol || - tp->protocol == __constant_htons(ETH_P_ALL)) && - (err = tp->classify(skb, tp, res)) >= 0) { +/* Map to export classifier specific extension TLV types to the + * generic extensions API. Unsupported extensions must be set to 0. + */ +struct tcf_ext_map +{ + int action; + int police; +}; + +/** + * tcf_exts_is_predicative - check if a predicative extension is present + * @exts: tc filter extensions handle + * + * Returns 1 if a predicative extension is present, i.e. an extension which + * might cause further actions and thus overrule the regular tcf_result. + */ +static inline int +tcf_exts_is_predicative(struct tcf_exts *exts) +{ #ifdef CONFIG_NET_CLS_ACT - if ( TC_ACT_RECLASSIFY == err) { - __u32 verd = (__u32) G_TC_VERD(skb->tc_verd); - tp = otp; - - if (MAX_REC_LOOP < verd++) { - printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n",tp->prio&0xffff, ntohs(tp->protocol)); - return TC_ACT_SHOT; - } - skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd); - goto reclassify; - } else { - if (skb->tc_verd) - skb->tc_verd = SET_TC_VERD(skb->tc_verd,0); - return err; - } + return !!exts->action; +#elif defined CONFIG_NET_CLS_POLICE + return !!exts->police; #else - - return err; + return 0; #endif - } - - } - return -1; } -static inline void tcf_destroy(struct tcf_proto *tp) +/** + * tcf_exts_is_available - check if at least one extension is present + * @exts: tc filter extensions handle + * + * Returns 1 if at least one extension is present. + */ +static inline int +tcf_exts_is_available(struct tcf_exts *exts) { - tp->ops->destroy(tp); - module_put(tp->ops->owner); - kfree(tp); + /* All non-predicative extensions must be added here. */ + return tcf_exts_is_predicative(exts); } -extern int register_tcf_proto_ops(struct tcf_proto_ops *ops); -extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops); -extern int ing_filter(struct sk_buff *skb); +/** + * tcf_exts_exec - execute tc filter extensions + * @skb: socket buffer + * @exts: tc filter extensions handle + * @res: desired result + * + * Executes all configured extensions. Returns 0 on a normal execution, + * a negative number if the filter must be considered unmatched or + * a positive action code (TC_ACT_*) which must be returned to the + * underlying layer. + */ +static inline int +tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, + struct tcf_result *res) +{ +#ifdef CONFIG_NET_CLS_ACT + if (exts->action) + return tcf_action_exec(skb, exts->action, res); +#elif defined CONFIG_NET_CLS_POLICE + if (exts->police) + return tcf_police(skb, exts->police); +#endif + + return 0; +} +extern int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb, + struct rtattr *rate_tlv, struct tcf_exts *exts, + struct tcf_ext_map *map); +extern void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts); +extern void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, + struct tcf_exts *src); +extern int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, + struct tcf_ext_map *map); +extern int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts, + struct tcf_ext_map *map); + +#ifdef CONFIG_NET_CLS_IND +static inline int +tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv) +{ + if (rtattr_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) + return -EINVAL; + return 0; +} +static inline int +tcf_match_indev(struct sk_buff *skb, char *indev) +{ + if (0 != indev[0]) { + if (NULL == skb->input_dev) + return 0; + else if (0 != strcmp(indev, skb->input_dev->name)) + return 0; + } + return 1; +} +#endif /* CONFIG_NET_CLS_IND */ #endif