netdev
[Top] [All Lists]

[PATCH 1/6] PKT_SCHED: Add generic classifier routines

To: "David S. Miller" <davem@xxxxxxxxxxxxx>
Subject: [PATCH 1/6] PKT_SCHED: Add generic classifier routines
From: Thomas Graf <tgraf@xxxxxxx>
Date: Fri, 29 Oct 2004 02:22:29 +0200
Cc: netdev@xxxxxxxxxxx, hadi@xxxxxxxxxx
In-reply-to: <20041029002113.GY12289@postel.suug.ch>
References: <20041029002113.GY12289@postel.suug.ch>
Sender: netdev-bounce@xxxxxxxxxxx
Adds generic routines used by classifier to:
 - bind/unbind to classes
 - configure action/police/indev
 - dump action/police

Signed-off-by: Thomas Graf <tgraf@xxxxxxx>

--- linux-2.6.10-rc1-bk7.orig/include/net/pkt_cls.h     2004-10-28 
22:03:20.000000000 +0200
+++ linux-2.6.10-rc1-bk7/include/net/pkt_cls.h  2004-10-28 23:53:05.000000000 
+0200
@@ -3,6 +3,7 @@
 
 #include <linux/pkt_cls.h>
 #include <net/sch_generic.h>
+#include <net/act_api.h>
 
 /* Basic packet classifier frontend definitions. */
 
@@ -41,4 +42,190 @@
        return old_cl;
 }
 
+static inline void
+tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base)
+{
+       unsigned long cl;
+
+       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);
+}
+
+static inline void
+tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
+{
+       unsigned long cl;
+
+       if ((cl = __cls_set_class(&r->class, 0)) != 0)
+               tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+}
+
+#ifdef CONFIG_NET_CLS_ACT
+static inline int
+tcf_change_act_police(struct tcf_proto *tp, struct tc_action **action,
+       struct rtattr *act_police_tlv, struct rtattr *rate_tlv)
+{
+       int ret;
+       struct tc_action *act;
+
+       act = kmalloc(sizeof(*act), GFP_KERNEL);
+       if (NULL == act)
+               return -ENOMEM;
+       memset(act, 0, sizeof(*act));
+       
+       ret = tcf_action_init_1(act_police_tlv, rate_tlv, act, "police",
+               TCA_ACT_NOREPLACE, TCA_ACT_BIND);
+       if (ret < 0) {
+               tcf_action_destroy(act, TCA_ACT_UNBIND);
+               return ret;
+       }
+
+       act->type = TCA_OLD_COMPAT;
+
+       if (*action) {
+               tcf_tree_lock(tp);
+               act = xchg(action, act);
+               tcf_tree_unlock(tp);
+
+               tcf_action_destroy(act, TCA_ACT_UNBIND);
+       } else
+               *action = act;
+
+       return 0;
+}
+
+static inline int
+tcf_change_act(struct tcf_proto *tp, struct tc_action **action,
+       struct rtattr *act_tlv, struct rtattr *rate_tlv)
+{
+       int ret;
+       struct tc_action *act;
+
+       act = kmalloc(sizeof(*act), GFP_KERNEL);
+       if (NULL == act)
+               return -ENOMEM;
+       memset(act, 0, sizeof(*act));
+
+       ret = tcf_action_init(act_tlv, rate_tlv, act, NULL,
+               TCA_ACT_NOREPLACE, TCA_ACT_BIND);
+       if (ret < 0) {
+               tcf_action_destroy(act, TCA_ACT_UNBIND);
+               return ret;
+       }
+
+       if (*action) {
+               tcf_tree_lock(tp);
+               act = xchg(action, act);
+               tcf_tree_unlock(tp);
+
+               tcf_action_destroy(act, TCA_ACT_UNBIND);
+       } else
+               *action = act;
+
+       return 0;
+}
+
+static inline int
+tcf_dump_act(struct sk_buff *skb, struct tc_action *action,
+       int act_type, int compat_type)
+{
+       /*
+        * again for backward compatible mode - we want
+        * to work with both old and new modes of entering
+        * tc data even if iproute2  was newer - jhs
+        */
+       if (action) {
+               struct rtattr * p_rta = (struct rtattr*) skb->tail;
+
+               if (action->type != TCA_OLD_COMPAT) {
+                       RTA_PUT(skb, act_type, 0, NULL);
+                       if (tcf_action_dump(skb, action, 0, 0) < 0)
+                               goto rtattr_failure;
+               } else {
+                       RTA_PUT(skb, compat_type, 0, NULL);
+                       if (tcf_action_dump_old(skb, action, 0, 0) < 0)
+                               goto rtattr_failure;
+               }
+               
+               p_rta->rta_len = skb->tail - (u8*)p_rta;
+       }
+       return 0;
+
+rtattr_failure:
+       return -1;
+}
+
+#ifdef CONFIG_NET_CLS_IND
+static inline int
+tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv)
+{
+       if (RTA_PAYLOAD(indev_tlv) >= IFNAMSIZ) {
+               printk("cls: bad indev name %s\n", (char *) 
RTA_DATA(indev_tlv));
+               return -EINVAL;
+       }
+
+       memset(indev, 0, IFNAMSIZ);
+       sprintf(indev, "%s", (char *) RTA_DATA(indev_tlv));
+
+       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 /* CONFIG_NET_CLS_ACT */
+
+
+#ifdef CONFIG_NET_CLS_POLICE
+static inline int
+tcf_change_police(struct tcf_proto *tp, struct tcf_police **police,
+       struct rtattr *police_tlv, struct rtattr *rate_tlv)
+{
+       struct tcf_police *p = tcf_police_locate(police_tlv, rate_tlv);
+
+       if (*police) {
+               tcf_tree_lock(tp);
+               p = xchg(police, p);
+               tcf_tree_unlock(tp);
+
+               tcf_police_release(p, TCA_ACT_UNBIND);
+       } else
+               *police = p;
+
+       return 0;
+}
+
+static inline int
+tcf_dump_police(struct sk_buff *skb, struct tcf_police *police,
+       int police_type)
+{
+       if (police) {
+               struct rtattr * p_rta = (struct rtattr*) skb->tail;
+
+               RTA_PUT(skb, police_type, 0, NULL);
+
+               if (tcf_police_dump(skb, police) < 0)
+                       goto rtattr_failure;
+
+               p_rta->rta_len = skb->tail - (u8*)p_rta;
+       }
+       return 0;
+
+rtattr_failure:
+       return -1;
+}
+#endif /* CONFIG_NET_CLS_POLICE */
+
 #endif

<Prev in Thread] Current Thread [Next in Thread>