vserver 1.9.5.x5
[linux-2.6.git] / include / net / pkt_cls.h
index 4de3ea7..d12ad38 100644 (file)
@@ -1,36 +1,12 @@
 #ifndef __NET_PKT_CLS_H
 #define __NET_PKT_CLS_H
 
-
 #include <linux/pkt_cls.h>
-
-struct rtattr;
-struct tcmsg;
+#include <net/sch_generic.h>
+#include <net/act_api.h>
 
 /* 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