[PKT_SCHED]: Prefix tc actions with act_
authorPatrick McHardy <kaber@trash.net>
Mon, 9 Jan 2006 06:22:14 +0000 (22:22 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 9 Jan 2006 22:16:14 +0000 (14:16 -0800)
Clean up the net/sched directory a bit by prefix all actions with act_.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
14 files changed:
net/sched/Makefile
net/sched/act_api.c
net/sched/act_gact.c [new file with mode: 0644]
net/sched/act_ipt.c [new file with mode: 0644]
net/sched/act_mirred.c [new file with mode: 0644]
net/sched/act_pedit.c [new file with mode: 0644]
net/sched/act_police.c [new file with mode: 0644]
net/sched/act_simple.c [new file with mode: 0644]
net/sched/gact.c [deleted file]
net/sched/ipt.c [deleted file]
net/sched/mirred.c [deleted file]
net/sched/pedit.c [deleted file]
net/sched/police.c [deleted file]
net/sched/simple.c [deleted file]

index e48d0d4..0f06aec 100644 (file)
@@ -7,13 +7,13 @@ obj-y := sch_generic.o
 obj-$(CONFIG_NET_SCHED)                += sch_api.o sch_fifo.o sch_blackhole.o
 obj-$(CONFIG_NET_CLS)          += cls_api.o
 obj-$(CONFIG_NET_CLS_ACT)      += act_api.o
-obj-$(CONFIG_NET_ACT_POLICE)   += police.o
-obj-$(CONFIG_NET_CLS_POLICE)   += police.o
-obj-$(CONFIG_NET_ACT_GACT)     += gact.o
-obj-$(CONFIG_NET_ACT_MIRRED)   += mirred.o
-obj-$(CONFIG_NET_ACT_IPT)      += ipt.o
-obj-$(CONFIG_NET_ACT_PEDIT)    += pedit.o
-obj-$(CONFIG_NET_ACT_SIMP)     += simple.o
+obj-$(CONFIG_NET_ACT_POLICE)   += act_police.o
+obj-$(CONFIG_NET_CLS_POLICE)   += act_police.o
+obj-$(CONFIG_NET_ACT_GACT)     += act_gact.o
+obj-$(CONFIG_NET_ACT_MIRRED)   += act_mirred.o
+obj-$(CONFIG_NET_ACT_IPT)      += act_ipt.o
+obj-$(CONFIG_NET_ACT_PEDIT)    += act_pedit.o
+obj-$(CONFIG_NET_ACT_SIMP)     += act_simple.o
 obj-$(CONFIG_NET_SCH_CBQ)      += sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)      += sch_htb.o
 obj-$(CONFIG_NET_SCH_HPFQ)     += sch_hpfq.o
index bd651a4..792ce59 100644 (file)
@@ -290,7 +290,7 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
        if (a_o == NULL) {
 #ifdef CONFIG_KMOD
                rtnl_unlock();
-               request_module(act_name);
+               request_module("act_%s", act_name);
                rtnl_lock();
 
                a_o = tc_lookup_action_n(act_name);
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
new file mode 100644 (file)
index 0000000..a1e68f7
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * net/sched/gact.c    Generic actions
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ * copyright   Jamal Hadi Salim (2002-4)
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/tc_act/tc_gact.h>
+#include <net/tc_act/tc_gact.h>
+
+/* use generic hash table */
+#define MY_TAB_SIZE    16
+#define MY_TAB_MASK    15
+
+static u32 idx_gen;
+static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE];
+static DEFINE_RWLOCK(gact_lock);
+
+/* ovewrride the defaults */
+#define tcf_st         tcf_gact
+#define tc_st          tc_gact
+#define tcf_t_lock     gact_lock
+#define tcf_ht         tcf_gact_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+
+#ifdef CONFIG_GACT_PROB
+static int gact_net_rand(struct tcf_gact *p)
+{
+       if (net_random()%p->pval)
+               return p->action;
+       return p->paction;
+}
+
+static int gact_determ(struct tcf_gact *p)
+{
+       if (p->bstats.packets%p->pval)
+               return p->action;
+       return p->paction;
+}
+
+typedef int (*g_rand)(struct tcf_gact *p);
+static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ };
+#endif
+
+static int tcf_gact_init(struct rtattr *rta, struct rtattr *est,
+                         struct tc_action *a, int ovr, int bind)
+{
+       struct rtattr *tb[TCA_GACT_MAX];
+       struct tc_gact *parm;
+       struct tcf_gact *p;
+       int ret = 0;
+
+       if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0)
+               return -EINVAL;
+
+       if (tb[TCA_GACT_PARMS - 1] == NULL ||
+           RTA_PAYLOAD(tb[TCA_GACT_PARMS - 1]) < sizeof(*parm))
+               return -EINVAL;
+       parm = RTA_DATA(tb[TCA_GACT_PARMS - 1]);
+
+       if (tb[TCA_GACT_PROB-1] != NULL)
+#ifdef CONFIG_GACT_PROB
+               if (RTA_PAYLOAD(tb[TCA_GACT_PROB-1]) < sizeof(struct tc_gact_p))
+                       return -EINVAL;
+#else
+               return -EOPNOTSUPP;
+#endif
+
+       p = tcf_hash_check(parm->index, a, ovr, bind);
+       if (p == NULL) {
+               p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+               if (p == NULL)
+                       return -ENOMEM;
+               ret = ACT_P_CREATED;
+       } else {
+               if (!ovr) {
+                       tcf_hash_release(p, bind);
+                       return -EEXIST;
+               }
+       }
+
+       spin_lock_bh(&p->lock);
+       p->action = parm->action;
+#ifdef CONFIG_GACT_PROB
+       if (tb[TCA_GACT_PROB-1] != NULL) {
+               struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]);
+               p->paction = p_parm->paction;
+               p->pval    = p_parm->pval;
+               p->ptype   = p_parm->ptype;
+       }
+#endif
+       spin_unlock_bh(&p->lock);
+       if (ret == ACT_P_CREATED)
+               tcf_hash_insert(p);
+       return ret;
+}
+
+static int
+tcf_gact_cleanup(struct tc_action *a, int bind)
+{
+       struct tcf_gact *p = PRIV(a, gact);
+
+       if (p != NULL)
+               return tcf_hash_release(p, bind);
+       return 0;
+}
+
+static int
+tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
+{
+       struct tcf_gact *p = PRIV(a, gact);
+       int action = TC_ACT_SHOT;
+
+       spin_lock(&p->lock);
+#ifdef CONFIG_GACT_PROB
+       if (p->ptype && gact_rand[p->ptype] != NULL)
+               action = gact_rand[p->ptype](p);
+       else
+               action = p->action;
+#else
+       action = p->action;
+#endif
+       p->bstats.bytes += skb->len;
+       p->bstats.packets++;
+       if (action == TC_ACT_SHOT)
+               p->qstats.drops++;
+       p->tm.lastuse = jiffies;
+       spin_unlock(&p->lock);
+
+       return action;
+}
+
+static int
+tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+       unsigned char *b = skb->tail;
+       struct tc_gact opt;
+       struct tcf_gact *p = PRIV(a, gact);
+       struct tcf_t t;
+
+       opt.index = p->index;
+       opt.refcnt = p->refcnt - ref;
+       opt.bindcnt = p->bindcnt - bind;
+       opt.action = p->action;
+       RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt);
+#ifdef CONFIG_GACT_PROB
+       if (p->ptype) {
+               struct tc_gact_p p_opt;
+               p_opt.paction = p->paction;
+               p_opt.pval = p->pval;
+               p_opt.ptype = p->ptype;
+               RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt);
+       }
+#endif
+       t.install = jiffies_to_clock_t(jiffies - p->tm.install);
+       t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
+       t.expires = jiffies_to_clock_t(p->tm.expires);
+       RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t);
+       return skb->len;
+
+      rtattr_failure:
+       skb_trim(skb, b - skb->data);
+       return -1;
+}
+
+static struct tc_action_ops act_gact_ops = {
+       .kind           =       "gact",
+       .type           =       TCA_ACT_GACT,
+       .capab          =       TCA_CAP_NONE,
+       .owner          =       THIS_MODULE,
+       .act            =       tcf_gact,
+       .dump           =       tcf_gact_dump,
+       .cleanup        =       tcf_gact_cleanup,
+       .lookup         =       tcf_hash_search,
+       .init           =       tcf_gact_init,
+       .walk           =       tcf_generic_walker
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
+MODULE_DESCRIPTION("Generic Classifier actions");
+MODULE_LICENSE("GPL");
+
+static int __init
+gact_init_module(void)
+{
+#ifdef CONFIG_GACT_PROB
+       printk("GACT probability on\n");
+#else
+       printk("GACT probability NOT on\n");
+#endif
+       return tcf_register_action(&act_gact_ops);
+}
+
+static void __exit
+gact_cleanup_module(void)
+{
+       tcf_unregister_action(&act_gact_ops);
+}
+
+module_init(gact_init_module);
+module_exit(gact_cleanup_module);
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
new file mode 100644 (file)
index 0000000..b500193
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * net/sched/ipt.c     iptables target interface
+ *
+ *TODO: Add other tables. For now we only support the ipv4 table targets
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ * Copyright:  Jamal Hadi Salim (2002-4)
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/kmod.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/tc_act/tc_ipt.h>
+#include <net/tc_act/tc_ipt.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+/* use generic hash table */
+#define MY_TAB_SIZE     16
+#define MY_TAB_MASK     15
+
+static u32 idx_gen;
+static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE];
+/* ipt hash table lock */
+static DEFINE_RWLOCK(ipt_lock);
+
+/* ovewrride the defaults */
+#define tcf_st         tcf_ipt
+#define tcf_t_lock     ipt_lock
+#define tcf_ht         tcf_ipt_ht
+
+#define CONFIG_NET_ACT_INIT
+#include <net/pkt_act.h>
+
+static int
+ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
+{
+       struct ipt_target *target;
+       int ret = 0;
+
+       target = ipt_find_target(t->u.user.name, t->u.user.revision);
+       if (!target)
+               return -ENOENT;
+
+       DPRINTK("ipt_init_target: found %s\n", target->name);
+       t->u.kernel.target = target;
+
+       if (t->u.kernel.target->checkentry
+           && !t->u.kernel.target->checkentry(table, NULL, t->data,
+                                              t->u.target_size - sizeof(*t),
+                                              hook)) {
+               DPRINTK("ipt_init_target: check failed for `%s'.\n",
+                       t->u.kernel.target->name);
+               module_put(t->u.kernel.target->me);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static void
+ipt_destroy_target(struct ipt_entry_target *t)
+{
+       if (t->u.kernel.target->destroy)
+               t->u.kernel.target->destroy(t->data,
+                                           t->u.target_size - sizeof(*t));
+        module_put(t->u.kernel.target->me);
+}
+
+static int
+tcf_ipt_release(struct tcf_ipt *p, int bind)
+{
+       int ret = 0;
+       if (p) {
+               if (bind)
+                       p->bindcnt--;
+               p->refcnt--;
+               if (p->bindcnt <= 0 && p->refcnt <= 0) {
+                       ipt_destroy_target(p->t);
+                       kfree(p->tname);
+                       kfree(p->t);
+                       tcf_hash_destroy(p);
+                       ret = ACT_P_DELETED;
+               }
+       }
+       return ret;
+}
+
+static int
+tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
+             int ovr, int bind)
+{
+       struct rtattr *tb[TCA_IPT_MAX];
+       struct tcf_ipt *p;
+       struct ipt_entry_target *td, *t;
+       char *tname;
+       int ret = 0, err;
+       u32 hook = 0;
+       u32 index = 0;
+
+       if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0)
+               return -EINVAL;
+
+       if (tb[TCA_IPT_HOOK-1] == NULL ||
+           RTA_PAYLOAD(tb[TCA_IPT_HOOK-1]) < sizeof(u32))
+               return -EINVAL;
+       if (tb[TCA_IPT_TARG-1] == NULL ||
+           RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < sizeof(*t))
+               return -EINVAL;
+       td = (struct ipt_entry_target *)RTA_DATA(tb[TCA_IPT_TARG-1]);
+       if (RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < td->u.target_size)
+               return -EINVAL;
+
+       if (tb[TCA_IPT_INDEX-1] != NULL &&
+           RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32))
+               index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]);
+
+       p = tcf_hash_check(index, a, ovr, bind);
+       if (p == NULL) {
+               p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind);
+               if (p == NULL)
+                       return -ENOMEM;
+               ret = ACT_P_CREATED;
+       } else {
+               if (!ovr) {
+                       tcf_ipt_release(p, bind);
+                       return -EEXIST;
+               }
+       }
+
+       hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]);
+
+       err = -ENOMEM;
+       tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
+       if (tname == NULL)
+               goto err1;
+       if (tb[TCA_IPT_TABLE - 1] == NULL ||
+           rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ)
+               strcpy(tname, "mangle");
+
+       t = kmalloc(td->u.target_size, GFP_KERNEL);
+       if (t == NULL)
+               goto err2;
+       memcpy(t, td, td->u.target_size);
+
+       if ((err = ipt_init_target(t, tname, hook)) < 0)
+               goto err3;
+
+       spin_lock_bh(&p->lock);
+       if (ret != ACT_P_CREATED) {
+               ipt_destroy_target(p->t);
+               kfree(p->tname);
+               kfree(p->t);
+       }
+       p->tname = tname;
+       p->t     = t;
+       p->hook  = hook;
+       spin_unlock_bh(&p->lock);
+       if (ret == ACT_P_CREATED)
+               tcf_hash_insert(p);
+       return ret;
+
+err3:
+       kfree(t);
+err2:
+       kfree(tname);
+err1:
+       kfree(p);
+       return err;
+}
+
+static int
+tcf_ipt_cleanup(struct tc_action *a, int bind)
+{
+       struct tcf_ipt *p = PRIV(a, ipt);
+       return tcf_ipt_release(p, bind);
+}
+
+static int
+tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
+{
+       int ret = 0, result = 0;
+       struct tcf_ipt *p = PRIV(a, ipt);
+
+       if (skb_cloned(skb)) {
+               if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+                       return TC_ACT_UNSPEC;
+       }
+
+       spin_lock(&p->lock);
+
+       p->tm.lastuse = jiffies;
+       p->bstats.bytes += skb->len;
+       p->bstats.packets++;
+
+       /* yes, we have to worry about both in and out dev
+        worry later - danger - this API seems to have changed
+        from earlier kernels */
+
+       /* iptables targets take a double skb pointer in case the skb
+        * needs to be replaced. We don't own the skb, so this must not
+        * happen. The pskb_expand_head above should make sure of this */
+       ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL,
+                                           p->hook, p->t->data, NULL);
+       switch (ret) {
+       case NF_ACCEPT:
+               result = TC_ACT_OK;
+               break;
+       case NF_DROP:
+               result = TC_ACT_SHOT;
+               p->qstats.drops++;
+               break;
+       case IPT_CONTINUE:
+               result = TC_ACT_PIPE;
+               break;
+       default:
+               if (net_ratelimit())
+                       printk("Bogus netfilter code %d assume ACCEPT\n", ret);
+               result = TC_POLICE_OK;
+               break;
+       }
+       spin_unlock(&p->lock);
+       return result;
+
+}
+
+static int
+tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+       struct ipt_entry_target *t;
+       struct tcf_t tm;
+       struct tc_cnt c;
+       unsigned char *b = skb->tail;
+       struct tcf_ipt *p = PRIV(a, ipt);
+
+       /* for simple targets kernel size == user size
+       ** user name = target name
+       ** for foolproof you need to not assume this
+       */
+
+       t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC);
+       if (t == NULL)
+               goto rtattr_failure;
+
+       c.bindcnt = p->bindcnt - bind;
+       c.refcnt = p->refcnt - ref;
+       memcpy(t, p->t, p->t->u.user.target_size);
+       strcpy(t->u.user.name, p->t->u.kernel.target->name);
+
+       DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname,
+               strlen(p->tname));
+       DPRINTK("\tdump target name %s size %d size user %d "
+               "data[0] %x data[1] %x\n", p->t->u.kernel.target->name,
+               p->t->u.target_size, p->t->u.user.target_size,
+               p->t->data[0], p->t->data[1]);
+       RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t);
+       RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index);
+       RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook);
+       RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c);
+       RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname);
+       tm.install = jiffies_to_clock_t(jiffies - p->tm.install);
+       tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
+       tm.expires = jiffies_to_clock_t(p->tm.expires);
+       RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm);
+       kfree(t);
+       return skb->len;
+
+      rtattr_failure:
+       skb_trim(skb, b - skb->data);
+       kfree(t);
+       return -1;
+}
+
+static struct tc_action_ops act_ipt_ops = {
+       .kind           =       "ipt",
+       .type           =       TCA_ACT_IPT,
+       .capab          =       TCA_CAP_NONE,
+       .owner          =       THIS_MODULE,
+       .act            =       tcf_ipt,
+       .dump           =       tcf_ipt_dump,
+       .cleanup        =       tcf_ipt_cleanup,
+       .lookup         =       tcf_hash_search,
+       .init           =       tcf_ipt_init,
+       .walk           =       tcf_generic_walker
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
+MODULE_DESCRIPTION("Iptables target actions");
+MODULE_LICENSE("GPL");
+
+static int __init
+ipt_init_module(void)
+{
+       return tcf_register_action(&act_ipt_ops);
+}
+
+static void __exit
+ipt_cleanup_module(void)
+{
+       tcf_unregister_action(&act_ipt_ops);
+}
+
+module_init(ipt_init_module);
+module_exit(ipt_cleanup_module);
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
new file mode 100644 (file)
index 0000000..4fcccbd
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * net/sched/mirred.c  packet mirroring and redirect actions
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ * Authors:    Jamal Hadi Salim (2002-4)
+ *
+ * TODO: Add ingress support (and socket redirect support)
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/tc_act/tc_mirred.h>
+#include <net/tc_act/tc_mirred.h>
+
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+
+/* use generic hash table */
+#define MY_TAB_SIZE     8
+#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
+static u32 idx_gen;
+static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE];
+static DEFINE_RWLOCK(mirred_lock);
+
+/* ovewrride the defaults */
+#define tcf_st         tcf_mirred
+#define tc_st          tc_mirred
+#define tcf_t_lock     mirred_lock
+#define tcf_ht         tcf_mirred_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+
+static inline int
+tcf_mirred_release(struct tcf_mirred *p, int bind)
+{
+       if (p) {
+               if (bind)
+                       p->bindcnt--;
+               p->refcnt--;
+               if(!p->bindcnt && p->refcnt <= 0) {
+                       dev_put(p->dev);
+                       tcf_hash_destroy(p);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int
+tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
+                int ovr, int bind)
+{
+       struct rtattr *tb[TCA_MIRRED_MAX];
+       struct tc_mirred *parm;
+       struct tcf_mirred *p;
+       struct net_device *dev = NULL;
+       int ret = 0;
+       int ok_push = 0;
+
+       if (rta == NULL || rtattr_parse_nested(tb, TCA_MIRRED_MAX, rta) < 0)
+               return -EINVAL;
+
+       if (tb[TCA_MIRRED_PARMS-1] == NULL ||
+           RTA_PAYLOAD(tb[TCA_MIRRED_PARMS-1]) < sizeof(*parm))
+               return -EINVAL;
+       parm = RTA_DATA(tb[TCA_MIRRED_PARMS-1]);
+
+       if (parm->ifindex) {
+               dev = __dev_get_by_index(parm->ifindex);
+               if (dev == NULL)
+                       return -ENODEV;
+               switch (dev->type) {
+                       case ARPHRD_TUNNEL:
+                       case ARPHRD_TUNNEL6:
+                       case ARPHRD_SIT:
+                       case ARPHRD_IPGRE:
+                       case ARPHRD_VOID:
+                       case ARPHRD_NONE:
+                               ok_push = 0;
+                               break;
+                       default:
+                               ok_push = 1;
+                               break;
+               }
+       }
+
+       p = tcf_hash_check(parm->index, a, ovr, bind);
+       if (p == NULL) {
+               if (!parm->ifindex)
+                       return -EINVAL;
+               p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+               if (p == NULL)
+                       return -ENOMEM;
+               ret = ACT_P_CREATED;
+       } else {
+               if (!ovr) {
+                       tcf_mirred_release(p, bind);
+                       return -EEXIST;
+               }
+       }
+
+       spin_lock_bh(&p->lock);
+       p->action = parm->action;
+       p->eaction = parm->eaction;
+       if (parm->ifindex) {
+               p->ifindex = parm->ifindex;
+               if (ret != ACT_P_CREATED)
+                       dev_put(p->dev);
+               p->dev = dev;
+               dev_hold(dev);
+               p->ok_push = ok_push;
+       }
+       spin_unlock_bh(&p->lock);
+       if (ret == ACT_P_CREATED)
+               tcf_hash_insert(p);
+
+       DPRINTK("tcf_mirred_init index %d action %d eaction %d device %s "
+               "ifindex %d\n", parm->index, parm->action, parm->eaction,
+               dev->name, parm->ifindex);
+       return ret;
+}
+
+static int
+tcf_mirred_cleanup(struct tc_action *a, int bind)
+{
+       struct tcf_mirred *p = PRIV(a, mirred);
+
+       if (p != NULL)
+               return tcf_mirred_release(p, bind);
+       return 0;
+}
+
+static int
+tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
+{
+       struct tcf_mirred *p = PRIV(a, mirred);
+       struct net_device *dev;
+       struct sk_buff *skb2 = NULL;
+       u32 at = G_TC_AT(skb->tc_verd);
+
+       spin_lock(&p->lock);
+
+       dev = p->dev;
+       p->tm.lastuse = jiffies;
+
+       if (!(dev->flags&IFF_UP) ) {
+               if (net_ratelimit())
+                       printk("mirred to Houston: device %s is gone!\n",
+                              dev->name);
+bad_mirred:
+               if (skb2 != NULL)
+                       kfree_skb(skb2);
+               p->qstats.overlimits++;
+               p->bstats.bytes += skb->len;
+               p->bstats.packets++;
+               spin_unlock(&p->lock);
+               /* should we be asking for packet to be dropped?
+                * may make sense for redirect case only
+               */
+               return TC_ACT_SHOT;
+       }
+
+       skb2 = skb_clone(skb, GFP_ATOMIC);
+       if (skb2 == NULL)
+               goto bad_mirred;
+       if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) {
+               if (net_ratelimit())
+                       printk("tcf_mirred unknown action %d\n", p->eaction);
+               goto bad_mirred;
+       }
+
+       p->bstats.bytes += skb2->len;
+       p->bstats.packets++;
+       if (!(at & AT_EGRESS))
+               if (p->ok_push)
+                       skb_push(skb2, skb2->dev->hard_header_len);
+
+       /* mirror is always swallowed */
+       if (p->eaction != TCA_EGRESS_MIRROR)
+               skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
+
+       skb2->dev = dev;
+       skb2->input_dev = skb->dev;
+       dev_queue_xmit(skb2);
+       spin_unlock(&p->lock);
+       return p->action;
+}
+
+static int
+tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+       unsigned char *b = skb->tail;
+       struct tc_mirred opt;
+       struct tcf_mirred *p = PRIV(a, mirred);
+       struct tcf_t t;
+
+       opt.index = p->index;
+       opt.action = p->action;
+       opt.refcnt = p->refcnt - ref;
+       opt.bindcnt = p->bindcnt - bind;
+       opt.eaction = p->eaction;
+       opt.ifindex = p->ifindex;
+       DPRINTK("tcf_mirred_dump index %d action %d eaction %d ifindex %d\n",
+                p->index, p->action, p->eaction, p->ifindex);
+       RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt);
+       t.install = jiffies_to_clock_t(jiffies - p->tm.install);
+       t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
+       t.expires = jiffies_to_clock_t(p->tm.expires);
+       RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t);
+       return skb->len;
+
+      rtattr_failure:
+       skb_trim(skb, b - skb->data);
+       return -1;
+}
+
+static struct tc_action_ops act_mirred_ops = {
+       .kind           =       "mirred",
+       .type           =       TCA_ACT_MIRRED,
+       .capab          =       TCA_CAP_NONE,
+       .owner          =       THIS_MODULE,
+       .act            =       tcf_mirred,
+       .dump           =       tcf_mirred_dump,
+       .cleanup        =       tcf_mirred_cleanup,
+       .lookup         =       tcf_hash_search,
+       .init           =       tcf_mirred_init,
+       .walk           =       tcf_generic_walker
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2002)");
+MODULE_DESCRIPTION("Device Mirror/redirect actions");
+MODULE_LICENSE("GPL");
+
+static int __init
+mirred_init_module(void)
+{
+       printk("Mirror/redirect action on\n");
+       return tcf_register_action(&act_mirred_ops);
+}
+
+static void __exit
+mirred_cleanup_module(void)
+{
+       tcf_unregister_action(&act_mirred_ops);
+}
+
+module_init(mirred_init_module);
+module_exit(mirred_cleanup_module);
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
new file mode 100644 (file)
index 0000000..1742a68
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * net/sched/pedit.c   Generic packet editor
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ * Authors:    Jamal Hadi Salim (2002-4)
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/tc_act/tc_pedit.h>
+#include <net/tc_act/tc_pedit.h>
+
+
+#define PEDIT_DEB 1
+
+/* use generic hash table */
+#define MY_TAB_SIZE     16
+#define MY_TAB_MASK     15
+static u32 idx_gen;
+static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE];
+static DEFINE_RWLOCK(pedit_lock);
+
+#define tcf_st         tcf_pedit
+#define tc_st          tc_pedit
+#define tcf_t_lock     pedit_lock
+#define tcf_ht         tcf_pedit_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+
+static int
+tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
+               int ovr, int bind)
+{
+       struct rtattr *tb[TCA_PEDIT_MAX];
+       struct tc_pedit *parm;
+       int ret = 0;
+       struct tcf_pedit *p;
+       struct tc_pedit_key *keys = NULL;
+       int ksize;
+
+       if (rta == NULL || rtattr_parse_nested(tb, TCA_PEDIT_MAX, rta) < 0)
+               return -EINVAL;
+
+       if (tb[TCA_PEDIT_PARMS - 1] == NULL ||
+           RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm))
+               return -EINVAL;
+       parm = RTA_DATA(tb[TCA_PEDIT_PARMS-1]);
+       ksize = parm->nkeys * sizeof(struct tc_pedit_key);
+       if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize)
+               return -EINVAL;
+
+       p = tcf_hash_check(parm->index, a, ovr, bind);
+       if (p == NULL) {
+               if (!parm->nkeys)
+                       return -EINVAL;
+               p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+               if (p == NULL)
+                       return -ENOMEM;
+               keys = kmalloc(ksize, GFP_KERNEL);
+               if (keys == NULL) {
+                       kfree(p);
+                       return -ENOMEM;
+               }
+               ret = ACT_P_CREATED;
+       } else {
+               if (!ovr) {
+                       tcf_hash_release(p, bind);
+                       return -EEXIST;
+               }
+               if (p->nkeys && p->nkeys != parm->nkeys) {
+                       keys = kmalloc(ksize, GFP_KERNEL);
+                       if (keys == NULL)
+                               return -ENOMEM;
+               }
+       }
+
+       spin_lock_bh(&p->lock);
+       p->flags = parm->flags;
+       p->action = parm->action;
+       if (keys) {
+               kfree(p->keys);
+               p->keys = keys;
+               p->nkeys = parm->nkeys;
+       }
+       memcpy(p->keys, parm->keys, ksize);
+       spin_unlock_bh(&p->lock);
+       if (ret == ACT_P_CREATED)
+               tcf_hash_insert(p);
+       return ret;
+}
+
+static int
+tcf_pedit_cleanup(struct tc_action *a, int bind)
+{
+       struct tcf_pedit *p = PRIV(a, pedit);
+
+       if (p != NULL) {
+               struct tc_pedit_key *keys = p->keys;
+               if (tcf_hash_release(p, bind)) {
+                       kfree(keys);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int
+tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
+{
+       struct tcf_pedit *p = PRIV(a, pedit);
+       int i, munged = 0;
+       u8 *pptr;
+
+       if (!(skb->tc_verd & TC_OK2MUNGE)) {
+               /* should we set skb->cloned? */
+               if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+                       return p->action;
+               }
+       }
+
+       pptr = skb->nh.raw;
+
+       spin_lock(&p->lock);
+
+       p->tm.lastuse = jiffies;
+
+       if (p->nkeys > 0) {
+               struct tc_pedit_key *tkey = p->keys;
+
+               for (i = p->nkeys; i > 0; i--, tkey++) {
+                       u32 *ptr;
+                       int offset = tkey->off;
+
+                       if (tkey->offmask) {
+                               if (skb->len > tkey->at) {
+                                        char *j = pptr + tkey->at;
+                                        offset += ((*j & tkey->offmask) >> 
+                                                  tkey->shift);
+                               } else {
+                                       goto bad;
+                               }
+                       }
+
+                       if (offset % 4) {
+                               printk("offset must be on 32 bit boundaries\n");
+                               goto bad;
+                       }
+                       if (skb->len < 0 || (offset > 0 && offset > skb->len)) {
+                               printk("offset %d cant exceed pkt length %d\n",
+                                      offset, skb->len);
+                               goto bad;
+                       }
+
+                       ptr = (u32 *)(pptr+offset);
+                       /* just do it, baby */
+                       *ptr = ((*ptr & tkey->mask) ^ tkey->val);
+                       munged++;
+               }
+               
+               if (munged)
+                       skb->tc_verd = SET_TC_MUNGED(skb->tc_verd);
+               goto done;
+       } else {
+               printk("pedit BUG: index %d\n",p->index);
+       }
+
+bad:
+       p->qstats.overlimits++;
+done:
+       p->bstats.bytes += skb->len;
+       p->bstats.packets++;
+       spin_unlock(&p->lock);
+       return p->action;
+}
+
+static int
+tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
+{
+       unsigned char *b = skb->tail;
+       struct tc_pedit *opt;
+       struct tcf_pedit *p = PRIV(a, pedit);
+       struct tcf_t t;
+       int s; 
+               
+       s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key);
+
+       /* netlink spinlocks held above us - must use ATOMIC */
+       opt = kmalloc(s, GFP_ATOMIC);
+       if (opt == NULL)
+               return -ENOBUFS;
+       memset(opt, 0, s);
+
+       memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key));
+       opt->index = p->index;
+       opt->nkeys = p->nkeys;
+       opt->flags = p->flags;
+       opt->action = p->action;
+       opt->refcnt = p->refcnt - ref;
+       opt->bindcnt = p->bindcnt - bind;
+
+
+#ifdef PEDIT_DEB
+       {                
+               /* Debug - get rid of later */
+               int i;
+               struct tc_pedit_key *key = opt->keys;
+
+               for (i=0; i<opt->nkeys; i++, key++) {
+                       printk( "\n key #%d",i);
+                       printk( "  at %d: val %08x mask %08x",
+                       (unsigned int)key->off,
+                       (unsigned int)key->val,
+                       (unsigned int)key->mask);
+               }
+       }
+#endif
+
+       RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
+       t.install = jiffies_to_clock_t(jiffies - p->tm.install);
+       t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
+       t.expires = jiffies_to_clock_t(p->tm.expires);
+       RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
+       kfree(opt);
+       return skb->len;
+
+rtattr_failure:
+       skb_trim(skb, b - skb->data);
+       kfree(opt);
+       return -1;
+}
+
+static
+struct tc_action_ops act_pedit_ops = {
+       .kind           =       "pedit",
+       .type           =       TCA_ACT_PEDIT,
+       .capab          =       TCA_CAP_NONE,
+       .owner          =       THIS_MODULE,
+       .act            =       tcf_pedit,
+       .dump           =       tcf_pedit_dump,
+       .cleanup        =       tcf_pedit_cleanup,
+       .lookup         =       tcf_hash_search,
+       .init           =       tcf_pedit_init,
+       .walk           =       tcf_generic_walker
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
+MODULE_DESCRIPTION("Generic Packet Editor actions");
+MODULE_LICENSE("GPL");
+
+static int __init
+pedit_init_module(void)
+{
+       return tcf_register_action(&act_pedit_ops);
+}
+
+static void __exit
+pedit_cleanup_module(void)
+{
+       tcf_unregister_action(&act_pedit_ops);
+}
+
+module_init(pedit_init_module);
+module_exit(pedit_cleanup_module);
+
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
new file mode 100644 (file)
index 0000000..fa877f8
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ * net/sched/police.c  Input police filter.
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *             J Hadi Salim (action changes)
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/bitops.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/module.h>
+#include <linux/rtnetlink.h>
+#include <linux/init.h>
+#include <net/sock.h>
+#include <net/act_api.h>
+
+#define L2T(p,L)   ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
+#define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
+#define PRIV(a) ((struct tcf_police *) (a)->priv)
+
+/* use generic hash table */
+#define MY_TAB_SIZE     16
+#define MY_TAB_MASK     15
+static u32 idx_gen;
+static struct tcf_police *tcf_police_ht[MY_TAB_SIZE];
+/* Policer hash table lock */
+static DEFINE_RWLOCK(police_lock);
+
+/* Each policer is serialized by its individual spinlock */
+
+static __inline__ unsigned tcf_police_hash(u32 index)
+{
+       return index&0xF;
+}
+
+static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
+{
+       struct tcf_police *p;
+
+       read_lock(&police_lock);
+       for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) {
+               if (p->index == index)
+                       break;
+       }
+       read_unlock(&police_lock);
+       return p;
+}
+
+#ifdef CONFIG_NET_CLS_ACT
+static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
+                              int type, struct tc_action *a)
+{
+       struct tcf_police *p;
+       int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
+       struct rtattr *r;
+
+       read_lock(&police_lock);
+
+       s_i = cb->args[0];
+
+       for (i = 0; i < MY_TAB_SIZE; i++) {
+               p = tcf_police_ht[tcf_police_hash(i)];
+
+               for (; p; p = p->next) {
+                       index++;
+                       if (index < s_i)
+                               continue;
+                       a->priv = p;
+                       a->order = index;
+                       r = (struct rtattr*) skb->tail;
+                       RTA_PUT(skb, a->order, 0, NULL);
+                       if (type == RTM_DELACTION)
+                               err = tcf_action_dump_1(skb, a, 0, 1);
+                       else
+                               err = tcf_action_dump_1(skb, a, 0, 0);
+                       if (err < 0) {
+                               index--;
+                               skb_trim(skb, (u8*)r - skb->data);
+                               goto done;
+                       }
+                       r->rta_len = skb->tail - (u8*)r;
+                       n_i++;
+               }
+       }
+done:
+       read_unlock(&police_lock);
+       if (n_i)
+               cb->args[0] += n_i;
+       return n_i;
+
+rtattr_failure:
+       skb_trim(skb, (u8*)r - skb->data);
+       goto done;
+}
+
+static inline int
+tcf_hash_search(struct tc_action *a, u32 index)
+{
+       struct tcf_police *p = tcf_police_lookup(index);
+
+       if (p != NULL) {
+               a->priv = p;
+               return 1;
+       } else {
+               return 0;
+       }
+}
+#endif
+
+static inline u32 tcf_police_new_index(void)
+{
+       do {
+               if (++idx_gen == 0)
+                       idx_gen = 1;
+       } while (tcf_police_lookup(idx_gen));
+
+       return idx_gen;
+}
+
+void tcf_police_destroy(struct tcf_police *p)
+{
+       unsigned h = tcf_police_hash(p->index);
+       struct tcf_police **p1p;
+       
+       for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) {
+               if (*p1p == p) {
+                       write_lock_bh(&police_lock);
+                       *p1p = p->next;
+                       write_unlock_bh(&police_lock);
+#ifdef CONFIG_NET_ESTIMATOR
+                       gen_kill_estimator(&p->bstats, &p->rate_est);
+#endif
+                       if (p->R_tab)
+                               qdisc_put_rtab(p->R_tab);
+                       if (p->P_tab)
+                               qdisc_put_rtab(p->P_tab);
+                       kfree(p);
+                       return;
+               }
+       }
+       BUG_TRAP(0);
+}
+
+#ifdef CONFIG_NET_CLS_ACT
+static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
+                                 struct tc_action *a, int ovr, int bind)
+{
+       unsigned h;
+       int ret = 0, err;
+       struct rtattr *tb[TCA_POLICE_MAX];
+       struct tc_police *parm;
+       struct tcf_police *p;
+       struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
+
+       if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
+               return -EINVAL;
+
+       if (tb[TCA_POLICE_TBF-1] == NULL ||
+           RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm))
+               return -EINVAL;
+       parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
+
+       if (tb[TCA_POLICE_RESULT-1] != NULL &&
+           RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+               return -EINVAL;
+       if (tb[TCA_POLICE_RESULT-1] != NULL &&
+           RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+               return -EINVAL;
+
+       if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
+               a->priv = p;
+               if (bind) {
+                       p->bindcnt += 1;
+                       p->refcnt += 1;
+               }
+               if (ovr)
+                       goto override;
+               return ret;
+       }
+
+       p = kmalloc(sizeof(*p), GFP_KERNEL);
+       if (p == NULL)
+               return -ENOMEM;
+       memset(p, 0, sizeof(*p));
+
+       ret = ACT_P_CREATED;
+       p->refcnt = 1;
+       spin_lock_init(&p->lock);
+       p->stats_lock = &p->lock;
+       if (bind)
+               p->bindcnt = 1;
+override:
+       if (parm->rate.rate) {
+               err = -ENOMEM;
+               R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
+               if (R_tab == NULL)
+                       goto failure;
+               if (parm->peakrate.rate) {
+                       P_tab = qdisc_get_rtab(&parm->peakrate,
+                                              tb[TCA_POLICE_PEAKRATE-1]);
+                       if (p->P_tab == NULL) {
+                               qdisc_put_rtab(R_tab);
+                               goto failure;
+                       }
+               }
+       }
+       /* No failure allowed after this point */
+       spin_lock_bh(&p->lock);
+       if (R_tab != NULL) {
+               qdisc_put_rtab(p->R_tab);
+               p->R_tab = R_tab;
+       }
+       if (P_tab != NULL) {
+               qdisc_put_rtab(p->P_tab);
+               p->P_tab = P_tab;
+       }
+
+       if (tb[TCA_POLICE_RESULT-1])
+               p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
+       p->toks = p->burst = parm->burst;
+       p->mtu = parm->mtu;
+       if (p->mtu == 0) {
+               p->mtu = ~0;
+               if (p->R_tab)
+                       p->mtu = 255<<p->R_tab->rate.cell_log;
+       }
+       if (p->P_tab)
+               p->ptoks = L2T_P(p, p->mtu);
+       p->action = parm->action;
+
+#ifdef CONFIG_NET_ESTIMATOR
+       if (tb[TCA_POLICE_AVRATE-1])
+               p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
+       if (est)
+               gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
+#endif
+
+       spin_unlock_bh(&p->lock);
+       if (ret != ACT_P_CREATED)
+               return ret;
+
+       PSCHED_GET_TIME(p->t_c);
+       p->index = parm->index ? : tcf_police_new_index();
+       h = tcf_police_hash(p->index);
+       write_lock_bh(&police_lock);
+       p->next = tcf_police_ht[h];
+       tcf_police_ht[h] = p;
+       write_unlock_bh(&police_lock);
+
+       a->priv = p;
+       return ret;
+
+failure:
+       if (ret == ACT_P_CREATED)
+               kfree(p);
+       return err;
+}
+
+static int tcf_act_police_cleanup(struct tc_action *a, int bind)
+{
+       struct tcf_police *p = PRIV(a);
+
+       if (p != NULL)
+               return tcf_police_release(p, bind);
+       return 0;
+}
+
+static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
+                          struct tcf_result *res)
+{
+       psched_time_t now;
+       struct tcf_police *p = PRIV(a);
+       long toks;
+       long ptoks = 0;
+
+       spin_lock(&p->lock);
+
+       p->bstats.bytes += skb->len;
+       p->bstats.packets++;
+
+#ifdef CONFIG_NET_ESTIMATOR
+       if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) {
+               p->qstats.overlimits++;
+               spin_unlock(&p->lock);
+               return p->action;
+       }
+#endif
+
+       if (skb->len <= p->mtu) {
+               if (p->R_tab == NULL) {
+                       spin_unlock(&p->lock);
+                       return p->result;
+               }
+
+               PSCHED_GET_TIME(now);
+
+               toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst);
+
+               if (p->P_tab) {
+                       ptoks = toks + p->ptoks;
+                       if (ptoks > (long)L2T_P(p, p->mtu))
+                               ptoks = (long)L2T_P(p, p->mtu);
+                       ptoks -= L2T_P(p, skb->len);
+               }
+               toks += p->toks;
+               if (toks > (long)p->burst)
+                       toks = p->burst;
+               toks -= L2T(p, skb->len);
+
+               if ((toks|ptoks) >= 0) {
+                       p->t_c = now;
+                       p->toks = toks;
+                       p->ptoks = ptoks;
+                       spin_unlock(&p->lock);
+                       return p->result;
+               }
+       }
+
+       p->qstats.overlimits++;
+       spin_unlock(&p->lock);
+       return p->action;
+}
+
+static int
+tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+       unsigned char    *b = skb->tail;
+       struct tc_police opt;
+       struct tcf_police *p = PRIV(a);
+
+       opt.index = p->index;
+       opt.action = p->action;
+       opt.mtu = p->mtu;
+       opt.burst = p->burst;
+       opt.refcnt = p->refcnt - ref;
+       opt.bindcnt = p->bindcnt - bind;
+       if (p->R_tab)
+               opt.rate = p->R_tab->rate;
+       else
+               memset(&opt.rate, 0, sizeof(opt.rate));
+       if (p->P_tab)
+               opt.peakrate = p->P_tab->rate;
+       else
+               memset(&opt.peakrate, 0, sizeof(opt.peakrate));
+       RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
+       if (p->result)
+               RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result);
+#ifdef CONFIG_NET_ESTIMATOR
+       if (p->ewma_rate)
+               RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate);
+#endif
+       return skb->len;
+
+rtattr_failure:
+       skb_trim(skb, b - skb->data);
+       return -1;
+}
+
+MODULE_AUTHOR("Alexey Kuznetsov");
+MODULE_DESCRIPTION("Policing actions");
+MODULE_LICENSE("GPL");
+
+static struct tc_action_ops act_police_ops = {
+       .kind           =       "police",
+       .type           =       TCA_ID_POLICE,
+       .capab          =       TCA_CAP_NONE,
+       .owner          =       THIS_MODULE,
+       .act            =       tcf_act_police,
+       .dump           =       tcf_act_police_dump,
+       .cleanup        =       tcf_act_police_cleanup,
+       .lookup         =       tcf_hash_search,
+       .init           =       tcf_act_police_locate,
+       .walk           =       tcf_generic_walker
+};
+
+static int __init
+police_init_module(void)
+{
+       return tcf_register_action(&act_police_ops);
+}
+
+static void __exit
+police_cleanup_module(void)
+{
+       tcf_unregister_action(&act_police_ops);
+}
+
+module_init(police_init_module);
+module_exit(police_cleanup_module);
+
+#else /* CONFIG_NET_CLS_ACT */
+
+struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
+{
+       unsigned h;
+       struct tcf_police *p;
+       struct rtattr *tb[TCA_POLICE_MAX];
+       struct tc_police *parm;
+
+       if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
+               return NULL;
+
+       if (tb[TCA_POLICE_TBF-1] == NULL ||
+           RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm))
+               return NULL;
+
+       parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
+
+       if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
+               p->refcnt++;
+               return p;
+       }
+
+       p = kmalloc(sizeof(*p), GFP_KERNEL);
+       if (p == NULL)
+               return NULL;
+
+       memset(p, 0, sizeof(*p));
+       p->refcnt = 1;
+       spin_lock_init(&p->lock);
+       p->stats_lock = &p->lock;
+       if (parm->rate.rate) {
+               p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
+               if (p->R_tab == NULL)
+                       goto failure;
+               if (parm->peakrate.rate) {
+                       p->P_tab = qdisc_get_rtab(&parm->peakrate,
+                                                 tb[TCA_POLICE_PEAKRATE-1]);
+                       if (p->P_tab == NULL)
+                               goto failure;
+               }
+       }
+       if (tb[TCA_POLICE_RESULT-1]) {
+               if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+                       goto failure;
+               p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
+       }
+#ifdef CONFIG_NET_ESTIMATOR
+       if (tb[TCA_POLICE_AVRATE-1]) {
+               if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32))
+                       goto failure;
+               p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
+       }
+#endif
+       p->toks = p->burst = parm->burst;
+       p->mtu = parm->mtu;
+       if (p->mtu == 0) {
+               p->mtu = ~0;
+               if (p->R_tab)
+                       p->mtu = 255<<p->R_tab->rate.cell_log;
+       }
+       if (p->P_tab)
+               p->ptoks = L2T_P(p, p->mtu);
+       PSCHED_GET_TIME(p->t_c);
+       p->index = parm->index ? : tcf_police_new_index();
+       p->action = parm->action;
+#ifdef CONFIG_NET_ESTIMATOR
+       if (est)
+               gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
+#endif
+       h = tcf_police_hash(p->index);
+       write_lock_bh(&police_lock);
+       p->next = tcf_police_ht[h];
+       tcf_police_ht[h] = p;
+       write_unlock_bh(&police_lock);
+       return p;
+
+failure:
+       if (p->R_tab)
+               qdisc_put_rtab(p->R_tab);
+       kfree(p);
+       return NULL;
+}
+
+int tcf_police(struct sk_buff *skb, struct tcf_police *p)
+{
+       psched_time_t now;
+       long toks;
+       long ptoks = 0;
+
+       spin_lock(&p->lock);
+
+       p->bstats.bytes += skb->len;
+       p->bstats.packets++;
+
+#ifdef CONFIG_NET_ESTIMATOR
+       if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) {
+               p->qstats.overlimits++;
+               spin_unlock(&p->lock);
+               return p->action;
+       }
+#endif
+
+       if (skb->len <= p->mtu) {
+               if (p->R_tab == NULL) {
+                       spin_unlock(&p->lock);
+                       return p->result;
+               }
+
+               PSCHED_GET_TIME(now);
+
+               toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst);
+
+               if (p->P_tab) {
+                       ptoks = toks + p->ptoks;
+                       if (ptoks > (long)L2T_P(p, p->mtu))
+                               ptoks = (long)L2T_P(p, p->mtu);
+                       ptoks -= L2T_P(p, skb->len);
+               }
+               toks += p->toks;
+               if (toks > (long)p->burst)
+                       toks = p->burst;
+               toks -= L2T(p, skb->len);
+
+               if ((toks|ptoks) >= 0) {
+                       p->t_c = now;
+                       p->toks = toks;
+                       p->ptoks = ptoks;
+                       spin_unlock(&p->lock);
+                       return p->result;
+               }
+       }
+
+       p->qstats.overlimits++;
+       spin_unlock(&p->lock);
+       return p->action;
+}
+EXPORT_SYMBOL(tcf_police);
+
+int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p)
+{
+       unsigned char    *b = skb->tail;
+       struct tc_police opt;
+
+       opt.index = p->index;
+       opt.action = p->action;
+       opt.mtu = p->mtu;
+       opt.burst = p->burst;
+       if (p->R_tab)
+               opt.rate = p->R_tab->rate;
+       else
+               memset(&opt.rate, 0, sizeof(opt.rate));
+       if (p->P_tab)
+               opt.peakrate = p->P_tab->rate;
+       else
+               memset(&opt.peakrate, 0, sizeof(opt.peakrate));
+       RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
+       if (p->result)
+               RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result);
+#ifdef CONFIG_NET_ESTIMATOR
+       if (p->ewma_rate)
+               RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate);
+#endif
+       return skb->len;
+
+rtattr_failure:
+       skb_trim(skb, b - skb->data);
+       return -1;
+}
+
+int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p)
+{
+       struct gnet_dump d;
+       
+       if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
+                       TCA_XSTATS, p->stats_lock, &d) < 0)
+               goto errout;
+       
+       if (gnet_stats_copy_basic(&d, &p->bstats) < 0 ||
+#ifdef CONFIG_NET_ESTIMATOR
+           gnet_stats_copy_rate_est(&d, &p->rate_est) < 0 ||
+#endif
+           gnet_stats_copy_queue(&d, &p->qstats) < 0)
+               goto errout;
+
+       if (gnet_stats_finish_copy(&d) < 0)
+               goto errout;
+
+       return 0;
+
+errout:
+       return -1;
+}
+
+#endif /* CONFIG_NET_CLS_ACT */
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
new file mode 100644 (file)
index 0000000..e5f2e1f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * net/sched/simp.c    Simple example of an action
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ * Authors:    Jamal Hadi Salim (2005)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <net/pkt_sched.h>
+
+#define TCA_ACT_SIMP 22
+
+/* XXX: Hide all these common elements under some macro 
+ * probably
+*/
+#include <linux/tc_act/tc_defact.h>
+#include <net/tc_act/tc_defact.h>
+
+/* use generic hash table with 8 buckets */
+#define MY_TAB_SIZE     8
+#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
+static u32 idx_gen;
+static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE];
+static DEFINE_RWLOCK(simp_lock);
+
+/* override the defaults */
+#define tcf_st         tcf_defact
+#define tc_st          tc_defact
+#define tcf_t_lock     simp_lock
+#define tcf_ht         tcf_simp_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+#include <net/act_generic.h>
+
+static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
+{
+       struct tcf_defact *p = PRIV(a, defact);
+
+       spin_lock(&p->lock);
+       p->tm.lastuse = jiffies;
+       p->bstats.bytes += skb->len;
+       p->bstats.packets++;
+
+       /* print policy string followed by _ then packet count 
+        * Example if this was the 3rd packet and the string was "hello" 
+        * then it would look like "hello_3" (without quotes) 
+        **/
+       printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets);
+       spin_unlock(&p->lock);
+       return p->action;
+}
+
+static struct tc_action_ops act_simp_ops = {
+       .kind = "simple",
+       .type = TCA_ACT_SIMP,
+       .capab = TCA_CAP_NONE,
+       .owner = THIS_MODULE,
+       .act = tcf_simp,
+       tca_use_default_ops
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2005)");
+MODULE_DESCRIPTION("Simple example action");
+MODULE_LICENSE("GPL");
+
+static int __init simp_init_module(void)
+{
+       int ret = tcf_register_action(&act_simp_ops);
+       if (!ret)
+               printk("Simple TC action Loaded\n");
+       return ret;
+}
+
+static void __exit simp_cleanup_module(void)
+{
+       tcf_unregister_action(&act_simp_ops);
+}
+
+module_init(simp_init_module);
+module_exit(simp_cleanup_module);
diff --git a/net/sched/gact.c b/net/sched/gact.c
deleted file mode 100644 (file)
index a1e68f7..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * net/sched/gact.c    Generic actions
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- *
- * copyright   Jamal Hadi Salim (2002-4)
- *
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
-#include <linux/tc_act/tc_gact.h>
-#include <net/tc_act/tc_gact.h>
-
-/* use generic hash table */
-#define MY_TAB_SIZE    16
-#define MY_TAB_MASK    15
-
-static u32 idx_gen;
-static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE];
-static DEFINE_RWLOCK(gact_lock);
-
-/* ovewrride the defaults */
-#define tcf_st         tcf_gact
-#define tc_st          tc_gact
-#define tcf_t_lock     gact_lock
-#define tcf_ht         tcf_gact_ht
-
-#define CONFIG_NET_ACT_INIT 1
-#include <net/pkt_act.h>
-
-#ifdef CONFIG_GACT_PROB
-static int gact_net_rand(struct tcf_gact *p)
-{
-       if (net_random()%p->pval)
-               return p->action;
-       return p->paction;
-}
-
-static int gact_determ(struct tcf_gact *p)
-{
-       if (p->bstats.packets%p->pval)
-               return p->action;
-       return p->paction;
-}
-
-typedef int (*g_rand)(struct tcf_gact *p);
-static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ };
-#endif
-
-static int tcf_gact_init(struct rtattr *rta, struct rtattr *est,
-                         struct tc_action *a, int ovr, int bind)
-{
-       struct rtattr *tb[TCA_GACT_MAX];
-       struct tc_gact *parm;
-       struct tcf_gact *p;
-       int ret = 0;
-
-       if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0)
-               return -EINVAL;
-
-       if (tb[TCA_GACT_PARMS - 1] == NULL ||
-           RTA_PAYLOAD(tb[TCA_GACT_PARMS - 1]) < sizeof(*parm))
-               return -EINVAL;
-       parm = RTA_DATA(tb[TCA_GACT_PARMS - 1]);
-
-       if (tb[TCA_GACT_PROB-1] != NULL)
-#ifdef CONFIG_GACT_PROB
-               if (RTA_PAYLOAD(tb[TCA_GACT_PROB-1]) < sizeof(struct tc_gact_p))
-                       return -EINVAL;
-#else
-               return -EOPNOTSUPP;
-#endif
-
-       p = tcf_hash_check(parm->index, a, ovr, bind);
-       if (p == NULL) {
-               p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
-               if (p == NULL)
-                       return -ENOMEM;
-               ret = ACT_P_CREATED;
-       } else {
-               if (!ovr) {
-                       tcf_hash_release(p, bind);
-                       return -EEXIST;
-               }
-       }
-
-       spin_lock_bh(&p->lock);
-       p->action = parm->action;
-#ifdef CONFIG_GACT_PROB
-       if (tb[TCA_GACT_PROB-1] != NULL) {
-               struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]);
-               p->paction = p_parm->paction;
-               p->pval    = p_parm->pval;
-               p->ptype   = p_parm->ptype;
-       }
-#endif
-       spin_unlock_bh(&p->lock);
-       if (ret == ACT_P_CREATED)
-               tcf_hash_insert(p);
-       return ret;
-}
-
-static int
-tcf_gact_cleanup(struct tc_action *a, int bind)
-{
-       struct tcf_gact *p = PRIV(a, gact);
-
-       if (p != NULL)
-               return tcf_hash_release(p, bind);
-       return 0;
-}
-
-static int
-tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
-{
-       struct tcf_gact *p = PRIV(a, gact);
-       int action = TC_ACT_SHOT;
-
-       spin_lock(&p->lock);
-#ifdef CONFIG_GACT_PROB
-       if (p->ptype && gact_rand[p->ptype] != NULL)
-               action = gact_rand[p->ptype](p);
-       else
-               action = p->action;
-#else
-       action = p->action;
-#endif
-       p->bstats.bytes += skb->len;
-       p->bstats.packets++;
-       if (action == TC_ACT_SHOT)
-               p->qstats.drops++;
-       p->tm.lastuse = jiffies;
-       spin_unlock(&p->lock);
-
-       return action;
-}
-
-static int
-tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
-{
-       unsigned char *b = skb->tail;
-       struct tc_gact opt;
-       struct tcf_gact *p = PRIV(a, gact);
-       struct tcf_t t;
-
-       opt.index = p->index;
-       opt.refcnt = p->refcnt - ref;
-       opt.bindcnt = p->bindcnt - bind;
-       opt.action = p->action;
-       RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt);
-#ifdef CONFIG_GACT_PROB
-       if (p->ptype) {
-               struct tc_gact_p p_opt;
-               p_opt.paction = p->paction;
-               p_opt.pval = p->pval;
-               p_opt.ptype = p->ptype;
-               RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt);
-       }
-#endif
-       t.install = jiffies_to_clock_t(jiffies - p->tm.install);
-       t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
-       t.expires = jiffies_to_clock_t(p->tm.expires);
-       RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t);
-       return skb->len;
-
-      rtattr_failure:
-       skb_trim(skb, b - skb->data);
-       return -1;
-}
-
-static struct tc_action_ops act_gact_ops = {
-       .kind           =       "gact",
-       .type           =       TCA_ACT_GACT,
-       .capab          =       TCA_CAP_NONE,
-       .owner          =       THIS_MODULE,
-       .act            =       tcf_gact,
-       .dump           =       tcf_gact_dump,
-       .cleanup        =       tcf_gact_cleanup,
-       .lookup         =       tcf_hash_search,
-       .init           =       tcf_gact_init,
-       .walk           =       tcf_generic_walker
-};
-
-MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
-MODULE_DESCRIPTION("Generic Classifier actions");
-MODULE_LICENSE("GPL");
-
-static int __init
-gact_init_module(void)
-{
-#ifdef CONFIG_GACT_PROB
-       printk("GACT probability on\n");
-#else
-       printk("GACT probability NOT on\n");
-#endif
-       return tcf_register_action(&act_gact_ops);
-}
-
-static void __exit
-gact_cleanup_module(void)
-{
-       tcf_unregister_action(&act_gact_ops);
-}
-
-module_init(gact_init_module);
-module_exit(gact_cleanup_module);
diff --git a/net/sched/ipt.c b/net/sched/ipt.c
deleted file mode 100644 (file)
index b500193..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * net/sched/ipt.c     iptables target interface
- *
- *TODO: Add other tables. For now we only support the ipv4 table targets
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- *
- * Copyright:  Jamal Hadi Salim (2002-4)
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/kmod.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
-#include <linux/tc_act/tc_ipt.h>
-#include <net/tc_act/tc_ipt.h>
-
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-/* use generic hash table */
-#define MY_TAB_SIZE     16
-#define MY_TAB_MASK     15
-
-static u32 idx_gen;
-static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE];
-/* ipt hash table lock */
-static DEFINE_RWLOCK(ipt_lock);
-
-/* ovewrride the defaults */
-#define tcf_st         tcf_ipt
-#define tcf_t_lock     ipt_lock
-#define tcf_ht         tcf_ipt_ht
-
-#define CONFIG_NET_ACT_INIT
-#include <net/pkt_act.h>
-
-static int
-ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
-{
-       struct ipt_target *target;
-       int ret = 0;
-
-       target = ipt_find_target(t->u.user.name, t->u.user.revision);
-       if (!target)
-               return -ENOENT;
-
-       DPRINTK("ipt_init_target: found %s\n", target->name);
-       t->u.kernel.target = target;
-
-       if (t->u.kernel.target->checkentry
-           && !t->u.kernel.target->checkentry(table, NULL, t->data,
-                                              t->u.target_size - sizeof(*t),
-                                              hook)) {
-               DPRINTK("ipt_init_target: check failed for `%s'.\n",
-                       t->u.kernel.target->name);
-               module_put(t->u.kernel.target->me);
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-static void
-ipt_destroy_target(struct ipt_entry_target *t)
-{
-       if (t->u.kernel.target->destroy)
-               t->u.kernel.target->destroy(t->data,
-                                           t->u.target_size - sizeof(*t));
-        module_put(t->u.kernel.target->me);
-}
-
-static int
-tcf_ipt_release(struct tcf_ipt *p, int bind)
-{
-       int ret = 0;
-       if (p) {
-               if (bind)
-                       p->bindcnt--;
-               p->refcnt--;
-               if (p->bindcnt <= 0 && p->refcnt <= 0) {
-                       ipt_destroy_target(p->t);
-                       kfree(p->tname);
-                       kfree(p->t);
-                       tcf_hash_destroy(p);
-                       ret = ACT_P_DELETED;
-               }
-       }
-       return ret;
-}
-
-static int
-tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
-             int ovr, int bind)
-{
-       struct rtattr *tb[TCA_IPT_MAX];
-       struct tcf_ipt *p;
-       struct ipt_entry_target *td, *t;
-       char *tname;
-       int ret = 0, err;
-       u32 hook = 0;
-       u32 index = 0;
-
-       if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0)
-               return -EINVAL;
-
-       if (tb[TCA_IPT_HOOK-1] == NULL ||
-           RTA_PAYLOAD(tb[TCA_IPT_HOOK-1]) < sizeof(u32))
-               return -EINVAL;
-       if (tb[TCA_IPT_TARG-1] == NULL ||
-           RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < sizeof(*t))
-               return -EINVAL;
-       td = (struct ipt_entry_target *)RTA_DATA(tb[TCA_IPT_TARG-1]);
-       if (RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < td->u.target_size)
-               return -EINVAL;
-
-       if (tb[TCA_IPT_INDEX-1] != NULL &&
-           RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32))
-               index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]);
-
-       p = tcf_hash_check(index, a, ovr, bind);
-       if (p == NULL) {
-               p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind);
-               if (p == NULL)
-                       return -ENOMEM;
-               ret = ACT_P_CREATED;
-       } else {
-               if (!ovr) {
-                       tcf_ipt_release(p, bind);
-                       return -EEXIST;
-               }
-       }
-
-       hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]);
-
-       err = -ENOMEM;
-       tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
-       if (tname == NULL)
-               goto err1;
-       if (tb[TCA_IPT_TABLE - 1] == NULL ||
-           rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ)
-               strcpy(tname, "mangle");
-
-       t = kmalloc(td->u.target_size, GFP_KERNEL);
-       if (t == NULL)
-               goto err2;
-       memcpy(t, td, td->u.target_size);
-
-       if ((err = ipt_init_target(t, tname, hook)) < 0)
-               goto err3;
-
-       spin_lock_bh(&p->lock);
-       if (ret != ACT_P_CREATED) {
-               ipt_destroy_target(p->t);
-               kfree(p->tname);
-               kfree(p->t);
-       }
-       p->tname = tname;
-       p->t     = t;
-       p->hook  = hook;
-       spin_unlock_bh(&p->lock);
-       if (ret == ACT_P_CREATED)
-               tcf_hash_insert(p);
-       return ret;
-
-err3:
-       kfree(t);
-err2:
-       kfree(tname);
-err1:
-       kfree(p);
-       return err;
-}
-
-static int
-tcf_ipt_cleanup(struct tc_action *a, int bind)
-{
-       struct tcf_ipt *p = PRIV(a, ipt);
-       return tcf_ipt_release(p, bind);
-}
-
-static int
-tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
-{
-       int ret = 0, result = 0;
-       struct tcf_ipt *p = PRIV(a, ipt);
-
-       if (skb_cloned(skb)) {
-               if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-                       return TC_ACT_UNSPEC;
-       }
-
-       spin_lock(&p->lock);
-
-       p->tm.lastuse = jiffies;
-       p->bstats.bytes += skb->len;
-       p->bstats.packets++;
-
-       /* yes, we have to worry about both in and out dev
-        worry later - danger - this API seems to have changed
-        from earlier kernels */
-
-       /* iptables targets take a double skb pointer in case the skb
-        * needs to be replaced. We don't own the skb, so this must not
-        * happen. The pskb_expand_head above should make sure of this */
-       ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL,
-                                           p->hook, p->t->data, NULL);
-       switch (ret) {
-       case NF_ACCEPT:
-               result = TC_ACT_OK;
-               break;
-       case NF_DROP:
-               result = TC_ACT_SHOT;
-               p->qstats.drops++;
-               break;
-       case IPT_CONTINUE:
-               result = TC_ACT_PIPE;
-               break;
-       default:
-               if (net_ratelimit())
-                       printk("Bogus netfilter code %d assume ACCEPT\n", ret);
-               result = TC_POLICE_OK;
-               break;
-       }
-       spin_unlock(&p->lock);
-       return result;
-
-}
-
-static int
-tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
-{
-       struct ipt_entry_target *t;
-       struct tcf_t tm;
-       struct tc_cnt c;
-       unsigned char *b = skb->tail;
-       struct tcf_ipt *p = PRIV(a, ipt);
-
-       /* for simple targets kernel size == user size
-       ** user name = target name
-       ** for foolproof you need to not assume this
-       */
-
-       t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC);
-       if (t == NULL)
-               goto rtattr_failure;
-
-       c.bindcnt = p->bindcnt - bind;
-       c.refcnt = p->refcnt - ref;
-       memcpy(t, p->t, p->t->u.user.target_size);
-       strcpy(t->u.user.name, p->t->u.kernel.target->name);
-
-       DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname,
-               strlen(p->tname));
-       DPRINTK("\tdump target name %s size %d size user %d "
-               "data[0] %x data[1] %x\n", p->t->u.kernel.target->name,
-               p->t->u.target_size, p->t->u.user.target_size,
-               p->t->data[0], p->t->data[1]);
-       RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t);
-       RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index);
-       RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook);
-       RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c);
-       RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname);
-       tm.install = jiffies_to_clock_t(jiffies - p->tm.install);
-       tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
-       tm.expires = jiffies_to_clock_t(p->tm.expires);
-       RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm);
-       kfree(t);
-       return skb->len;
-
-      rtattr_failure:
-       skb_trim(skb, b - skb->data);
-       kfree(t);
-       return -1;
-}
-
-static struct tc_action_ops act_ipt_ops = {
-       .kind           =       "ipt",
-       .type           =       TCA_ACT_IPT,
-       .capab          =       TCA_CAP_NONE,
-       .owner          =       THIS_MODULE,
-       .act            =       tcf_ipt,
-       .dump           =       tcf_ipt_dump,
-       .cleanup        =       tcf_ipt_cleanup,
-       .lookup         =       tcf_hash_search,
-       .init           =       tcf_ipt_init,
-       .walk           =       tcf_generic_walker
-};
-
-MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
-MODULE_DESCRIPTION("Iptables target actions");
-MODULE_LICENSE("GPL");
-
-static int __init
-ipt_init_module(void)
-{
-       return tcf_register_action(&act_ipt_ops);
-}
-
-static void __exit
-ipt_cleanup_module(void)
-{
-       tcf_unregister_action(&act_ipt_ops);
-}
-
-module_init(ipt_init_module);
-module_exit(ipt_cleanup_module);
diff --git a/net/sched/mirred.c b/net/sched/mirred.c
deleted file mode 100644 (file)
index 4fcccbd..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * net/sched/mirred.c  packet mirroring and redirect actions
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- *
- * Authors:    Jamal Hadi Salim (2002-4)
- *
- * TODO: Add ingress support (and socket redirect support)
- *
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
-#include <linux/tc_act/tc_mirred.h>
-#include <net/tc_act/tc_mirred.h>
-
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-
-
-/* use generic hash table */
-#define MY_TAB_SIZE     8
-#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
-static u32 idx_gen;
-static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE];
-static DEFINE_RWLOCK(mirred_lock);
-
-/* ovewrride the defaults */
-#define tcf_st         tcf_mirred
-#define tc_st          tc_mirred
-#define tcf_t_lock     mirred_lock
-#define tcf_ht         tcf_mirred_ht
-
-#define CONFIG_NET_ACT_INIT 1
-#include <net/pkt_act.h>
-
-static inline int
-tcf_mirred_release(struct tcf_mirred *p, int bind)
-{
-       if (p) {
-               if (bind)
-                       p->bindcnt--;
-               p->refcnt--;
-               if(!p->bindcnt && p->refcnt <= 0) {
-                       dev_put(p->dev);
-                       tcf_hash_destroy(p);
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-static int
-tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
-                int ovr, int bind)
-{
-       struct rtattr *tb[TCA_MIRRED_MAX];
-       struct tc_mirred *parm;
-       struct tcf_mirred *p;
-       struct net_device *dev = NULL;
-       int ret = 0;
-       int ok_push = 0;
-
-       if (rta == NULL || rtattr_parse_nested(tb, TCA_MIRRED_MAX, rta) < 0)
-               return -EINVAL;
-
-       if (tb[TCA_MIRRED_PARMS-1] == NULL ||
-           RTA_PAYLOAD(tb[TCA_MIRRED_PARMS-1]) < sizeof(*parm))
-               return -EINVAL;
-       parm = RTA_DATA(tb[TCA_MIRRED_PARMS-1]);
-
-       if (parm->ifindex) {
-               dev = __dev_get_by_index(parm->ifindex);
-               if (dev == NULL)
-                       return -ENODEV;
-               switch (dev->type) {
-                       case ARPHRD_TUNNEL:
-                       case ARPHRD_TUNNEL6:
-                       case ARPHRD_SIT:
-                       case ARPHRD_IPGRE:
-                       case ARPHRD_VOID:
-                       case ARPHRD_NONE:
-                               ok_push = 0;
-                               break;
-                       default:
-                               ok_push = 1;
-                               break;
-               }
-       }
-
-       p = tcf_hash_check(parm->index, a, ovr, bind);
-       if (p == NULL) {
-               if (!parm->ifindex)
-                       return -EINVAL;
-               p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
-               if (p == NULL)
-                       return -ENOMEM;
-               ret = ACT_P_CREATED;
-       } else {
-               if (!ovr) {
-                       tcf_mirred_release(p, bind);
-                       return -EEXIST;
-               }
-       }
-
-       spin_lock_bh(&p->lock);
-       p->action = parm->action;
-       p->eaction = parm->eaction;
-       if (parm->ifindex) {
-               p->ifindex = parm->ifindex;
-               if (ret != ACT_P_CREATED)
-                       dev_put(p->dev);
-               p->dev = dev;
-               dev_hold(dev);
-               p->ok_push = ok_push;
-       }
-       spin_unlock_bh(&p->lock);
-       if (ret == ACT_P_CREATED)
-               tcf_hash_insert(p);
-
-       DPRINTK("tcf_mirred_init index %d action %d eaction %d device %s "
-               "ifindex %d\n", parm->index, parm->action, parm->eaction,
-               dev->name, parm->ifindex);
-       return ret;
-}
-
-static int
-tcf_mirred_cleanup(struct tc_action *a, int bind)
-{
-       struct tcf_mirred *p = PRIV(a, mirred);
-
-       if (p != NULL)
-               return tcf_mirred_release(p, bind);
-       return 0;
-}
-
-static int
-tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
-{
-       struct tcf_mirred *p = PRIV(a, mirred);
-       struct net_device *dev;
-       struct sk_buff *skb2 = NULL;
-       u32 at = G_TC_AT(skb->tc_verd);
-
-       spin_lock(&p->lock);
-
-       dev = p->dev;
-       p->tm.lastuse = jiffies;
-
-       if (!(dev->flags&IFF_UP) ) {
-               if (net_ratelimit())
-                       printk("mirred to Houston: device %s is gone!\n",
-                              dev->name);
-bad_mirred:
-               if (skb2 != NULL)
-                       kfree_skb(skb2);
-               p->qstats.overlimits++;
-               p->bstats.bytes += skb->len;
-               p->bstats.packets++;
-               spin_unlock(&p->lock);
-               /* should we be asking for packet to be dropped?
-                * may make sense for redirect case only
-               */
-               return TC_ACT_SHOT;
-       }
-
-       skb2 = skb_clone(skb, GFP_ATOMIC);
-       if (skb2 == NULL)
-               goto bad_mirred;
-       if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) {
-               if (net_ratelimit())
-                       printk("tcf_mirred unknown action %d\n", p->eaction);
-               goto bad_mirred;
-       }
-
-       p->bstats.bytes += skb2->len;
-       p->bstats.packets++;
-       if (!(at & AT_EGRESS))
-               if (p->ok_push)
-                       skb_push(skb2, skb2->dev->hard_header_len);
-
-       /* mirror is always swallowed */
-       if (p->eaction != TCA_EGRESS_MIRROR)
-               skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
-
-       skb2->dev = dev;
-       skb2->input_dev = skb->dev;
-       dev_queue_xmit(skb2);
-       spin_unlock(&p->lock);
-       return p->action;
-}
-
-static int
-tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
-{
-       unsigned char *b = skb->tail;
-       struct tc_mirred opt;
-       struct tcf_mirred *p = PRIV(a, mirred);
-       struct tcf_t t;
-
-       opt.index = p->index;
-       opt.action = p->action;
-       opt.refcnt = p->refcnt - ref;
-       opt.bindcnt = p->bindcnt - bind;
-       opt.eaction = p->eaction;
-       opt.ifindex = p->ifindex;
-       DPRINTK("tcf_mirred_dump index %d action %d eaction %d ifindex %d\n",
-                p->index, p->action, p->eaction, p->ifindex);
-       RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt);
-       t.install = jiffies_to_clock_t(jiffies - p->tm.install);
-       t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
-       t.expires = jiffies_to_clock_t(p->tm.expires);
-       RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t);
-       return skb->len;
-
-      rtattr_failure:
-       skb_trim(skb, b - skb->data);
-       return -1;
-}
-
-static struct tc_action_ops act_mirred_ops = {
-       .kind           =       "mirred",
-       .type           =       TCA_ACT_MIRRED,
-       .capab          =       TCA_CAP_NONE,
-       .owner          =       THIS_MODULE,
-       .act            =       tcf_mirred,
-       .dump           =       tcf_mirred_dump,
-       .cleanup        =       tcf_mirred_cleanup,
-       .lookup         =       tcf_hash_search,
-       .init           =       tcf_mirred_init,
-       .walk           =       tcf_generic_walker
-};
-
-MODULE_AUTHOR("Jamal Hadi Salim(2002)");
-MODULE_DESCRIPTION("Device Mirror/redirect actions");
-MODULE_LICENSE("GPL");
-
-static int __init
-mirred_init_module(void)
-{
-       printk("Mirror/redirect action on\n");
-       return tcf_register_action(&act_mirred_ops);
-}
-
-static void __exit
-mirred_cleanup_module(void)
-{
-       tcf_unregister_action(&act_mirred_ops);
-}
-
-module_init(mirred_init_module);
-module_exit(mirred_cleanup_module);
diff --git a/net/sched/pedit.c b/net/sched/pedit.c
deleted file mode 100644 (file)
index 1742a68..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * net/sched/pedit.c   Generic packet editor
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- *
- * Authors:    Jamal Hadi Salim (2002-4)
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
-#include <linux/tc_act/tc_pedit.h>
-#include <net/tc_act/tc_pedit.h>
-
-
-#define PEDIT_DEB 1
-
-/* use generic hash table */
-#define MY_TAB_SIZE     16
-#define MY_TAB_MASK     15
-static u32 idx_gen;
-static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE];
-static DEFINE_RWLOCK(pedit_lock);
-
-#define tcf_st         tcf_pedit
-#define tc_st          tc_pedit
-#define tcf_t_lock     pedit_lock
-#define tcf_ht         tcf_pedit_ht
-
-#define CONFIG_NET_ACT_INIT 1
-#include <net/pkt_act.h>
-
-static int
-tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
-               int ovr, int bind)
-{
-       struct rtattr *tb[TCA_PEDIT_MAX];
-       struct tc_pedit *parm;
-       int ret = 0;
-       struct tcf_pedit *p;
-       struct tc_pedit_key *keys = NULL;
-       int ksize;
-
-       if (rta == NULL || rtattr_parse_nested(tb, TCA_PEDIT_MAX, rta) < 0)
-               return -EINVAL;
-
-       if (tb[TCA_PEDIT_PARMS - 1] == NULL ||
-           RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm))
-               return -EINVAL;
-       parm = RTA_DATA(tb[TCA_PEDIT_PARMS-1]);
-       ksize = parm->nkeys * sizeof(struct tc_pedit_key);
-       if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize)
-               return -EINVAL;
-
-       p = tcf_hash_check(parm->index, a, ovr, bind);
-       if (p == NULL) {
-               if (!parm->nkeys)
-                       return -EINVAL;
-               p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
-               if (p == NULL)
-                       return -ENOMEM;
-               keys = kmalloc(ksize, GFP_KERNEL);
-               if (keys == NULL) {
-                       kfree(p);
-                       return -ENOMEM;
-               }
-               ret = ACT_P_CREATED;
-       } else {
-               if (!ovr) {
-                       tcf_hash_release(p, bind);
-                       return -EEXIST;
-               }
-               if (p->nkeys && p->nkeys != parm->nkeys) {
-                       keys = kmalloc(ksize, GFP_KERNEL);
-                       if (keys == NULL)
-                               return -ENOMEM;
-               }
-       }
-
-       spin_lock_bh(&p->lock);
-       p->flags = parm->flags;
-       p->action = parm->action;
-       if (keys) {
-               kfree(p->keys);
-               p->keys = keys;
-               p->nkeys = parm->nkeys;
-       }
-       memcpy(p->keys, parm->keys, ksize);
-       spin_unlock_bh(&p->lock);
-       if (ret == ACT_P_CREATED)
-               tcf_hash_insert(p);
-       return ret;
-}
-
-static int
-tcf_pedit_cleanup(struct tc_action *a, int bind)
-{
-       struct tcf_pedit *p = PRIV(a, pedit);
-
-       if (p != NULL) {
-               struct tc_pedit_key *keys = p->keys;
-               if (tcf_hash_release(p, bind)) {
-                       kfree(keys);
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-static int
-tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
-{
-       struct tcf_pedit *p = PRIV(a, pedit);
-       int i, munged = 0;
-       u8 *pptr;
-
-       if (!(skb->tc_verd & TC_OK2MUNGE)) {
-               /* should we set skb->cloned? */
-               if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
-                       return p->action;
-               }
-       }
-
-       pptr = skb->nh.raw;
-
-       spin_lock(&p->lock);
-
-       p->tm.lastuse = jiffies;
-
-       if (p->nkeys > 0) {
-               struct tc_pedit_key *tkey = p->keys;
-
-               for (i = p->nkeys; i > 0; i--, tkey++) {
-                       u32 *ptr;
-                       int offset = tkey->off;
-
-                       if (tkey->offmask) {
-                               if (skb->len > tkey->at) {
-                                        char *j = pptr + tkey->at;
-                                        offset += ((*j & tkey->offmask) >> 
-                                                  tkey->shift);
-                               } else {
-                                       goto bad;
-                               }
-                       }
-
-                       if (offset % 4) {
-                               printk("offset must be on 32 bit boundaries\n");
-                               goto bad;
-                       }
-                       if (skb->len < 0 || (offset > 0 && offset > skb->len)) {
-                               printk("offset %d cant exceed pkt length %d\n",
-                                      offset, skb->len);
-                               goto bad;
-                       }
-
-                       ptr = (u32 *)(pptr+offset);
-                       /* just do it, baby */
-                       *ptr = ((*ptr & tkey->mask) ^ tkey->val);
-                       munged++;
-               }
-               
-               if (munged)
-                       skb->tc_verd = SET_TC_MUNGED(skb->tc_verd);
-               goto done;
-       } else {
-               printk("pedit BUG: index %d\n",p->index);
-       }
-
-bad:
-       p->qstats.overlimits++;
-done:
-       p->bstats.bytes += skb->len;
-       p->bstats.packets++;
-       spin_unlock(&p->lock);
-       return p->action;
-}
-
-static int
-tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
-{
-       unsigned char *b = skb->tail;
-       struct tc_pedit *opt;
-       struct tcf_pedit *p = PRIV(a, pedit);
-       struct tcf_t t;
-       int s; 
-               
-       s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key);
-
-       /* netlink spinlocks held above us - must use ATOMIC */
-       opt = kmalloc(s, GFP_ATOMIC);
-       if (opt == NULL)
-               return -ENOBUFS;
-       memset(opt, 0, s);
-
-       memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key));
-       opt->index = p->index;
-       opt->nkeys = p->nkeys;
-       opt->flags = p->flags;
-       opt->action = p->action;
-       opt->refcnt = p->refcnt - ref;
-       opt->bindcnt = p->bindcnt - bind;
-
-
-#ifdef PEDIT_DEB
-       {                
-               /* Debug - get rid of later */
-               int i;
-               struct tc_pedit_key *key = opt->keys;
-
-               for (i=0; i<opt->nkeys; i++, key++) {
-                       printk( "\n key #%d",i);
-                       printk( "  at %d: val %08x mask %08x",
-                       (unsigned int)key->off,
-                       (unsigned int)key->val,
-                       (unsigned int)key->mask);
-               }
-       }
-#endif
-
-       RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
-       t.install = jiffies_to_clock_t(jiffies - p->tm.install);
-       t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
-       t.expires = jiffies_to_clock_t(p->tm.expires);
-       RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
-       kfree(opt);
-       return skb->len;
-
-rtattr_failure:
-       skb_trim(skb, b - skb->data);
-       kfree(opt);
-       return -1;
-}
-
-static
-struct tc_action_ops act_pedit_ops = {
-       .kind           =       "pedit",
-       .type           =       TCA_ACT_PEDIT,
-       .capab          =       TCA_CAP_NONE,
-       .owner          =       THIS_MODULE,
-       .act            =       tcf_pedit,
-       .dump           =       tcf_pedit_dump,
-       .cleanup        =       tcf_pedit_cleanup,
-       .lookup         =       tcf_hash_search,
-       .init           =       tcf_pedit_init,
-       .walk           =       tcf_generic_walker
-};
-
-MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
-MODULE_DESCRIPTION("Generic Packet Editor actions");
-MODULE_LICENSE("GPL");
-
-static int __init
-pedit_init_module(void)
-{
-       return tcf_register_action(&act_pedit_ops);
-}
-
-static void __exit
-pedit_cleanup_module(void)
-{
-       tcf_unregister_action(&act_pedit_ops);
-}
-
-module_init(pedit_init_module);
-module_exit(pedit_cleanup_module);
-
diff --git a/net/sched/police.c b/net/sched/police.c
deleted file mode 100644 (file)
index fa877f8..0000000
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * net/sched/police.c  Input police filter.
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- *
- * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- *             J Hadi Salim (action changes)
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/module.h>
-#include <linux/rtnetlink.h>
-#include <linux/init.h>
-#include <net/sock.h>
-#include <net/act_api.h>
-
-#define L2T(p,L)   ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
-#define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
-#define PRIV(a) ((struct tcf_police *) (a)->priv)
-
-/* use generic hash table */
-#define MY_TAB_SIZE     16
-#define MY_TAB_MASK     15
-static u32 idx_gen;
-static struct tcf_police *tcf_police_ht[MY_TAB_SIZE];
-/* Policer hash table lock */
-static DEFINE_RWLOCK(police_lock);
-
-/* Each policer is serialized by its individual spinlock */
-
-static __inline__ unsigned tcf_police_hash(u32 index)
-{
-       return index&0xF;
-}
-
-static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
-{
-       struct tcf_police *p;
-
-       read_lock(&police_lock);
-       for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) {
-               if (p->index == index)
-                       break;
-       }
-       read_unlock(&police_lock);
-       return p;
-}
-
-#ifdef CONFIG_NET_CLS_ACT
-static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
-                              int type, struct tc_action *a)
-{
-       struct tcf_police *p;
-       int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
-       struct rtattr *r;
-
-       read_lock(&police_lock);
-
-       s_i = cb->args[0];
-
-       for (i = 0; i < MY_TAB_SIZE; i++) {
-               p = tcf_police_ht[tcf_police_hash(i)];
-
-               for (; p; p = p->next) {
-                       index++;
-                       if (index < s_i)
-                               continue;
-                       a->priv = p;
-                       a->order = index;
-                       r = (struct rtattr*) skb->tail;
-                       RTA_PUT(skb, a->order, 0, NULL);
-                       if (type == RTM_DELACTION)
-                               err = tcf_action_dump_1(skb, a, 0, 1);
-                       else
-                               err = tcf_action_dump_1(skb, a, 0, 0);
-                       if (err < 0) {
-                               index--;
-                               skb_trim(skb, (u8*)r - skb->data);
-                               goto done;
-                       }
-                       r->rta_len = skb->tail - (u8*)r;
-                       n_i++;
-               }
-       }
-done:
-       read_unlock(&police_lock);
-       if (n_i)
-               cb->args[0] += n_i;
-       return n_i;
-
-rtattr_failure:
-       skb_trim(skb, (u8*)r - skb->data);
-       goto done;
-}
-
-static inline int
-tcf_hash_search(struct tc_action *a, u32 index)
-{
-       struct tcf_police *p = tcf_police_lookup(index);
-
-       if (p != NULL) {
-               a->priv = p;
-               return 1;
-       } else {
-               return 0;
-       }
-}
-#endif
-
-static inline u32 tcf_police_new_index(void)
-{
-       do {
-               if (++idx_gen == 0)
-                       idx_gen = 1;
-       } while (tcf_police_lookup(idx_gen));
-
-       return idx_gen;
-}
-
-void tcf_police_destroy(struct tcf_police *p)
-{
-       unsigned h = tcf_police_hash(p->index);
-       struct tcf_police **p1p;
-       
-       for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) {
-               if (*p1p == p) {
-                       write_lock_bh(&police_lock);
-                       *p1p = p->next;
-                       write_unlock_bh(&police_lock);
-#ifdef CONFIG_NET_ESTIMATOR
-                       gen_kill_estimator(&p->bstats, &p->rate_est);
-#endif
-                       if (p->R_tab)
-                               qdisc_put_rtab(p->R_tab);
-                       if (p->P_tab)
-                               qdisc_put_rtab(p->P_tab);
-                       kfree(p);
-                       return;
-               }
-       }
-       BUG_TRAP(0);
-}
-
-#ifdef CONFIG_NET_CLS_ACT
-static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
-                                 struct tc_action *a, int ovr, int bind)
-{
-       unsigned h;
-       int ret = 0, err;
-       struct rtattr *tb[TCA_POLICE_MAX];
-       struct tc_police *parm;
-       struct tcf_police *p;
-       struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
-
-       if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
-               return -EINVAL;
-
-       if (tb[TCA_POLICE_TBF-1] == NULL ||
-           RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm))
-               return -EINVAL;
-       parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
-
-       if (tb[TCA_POLICE_RESULT-1] != NULL &&
-           RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
-               return -EINVAL;
-       if (tb[TCA_POLICE_RESULT-1] != NULL &&
-           RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
-               return -EINVAL;
-
-       if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
-               a->priv = p;
-               if (bind) {
-                       p->bindcnt += 1;
-                       p->refcnt += 1;
-               }
-               if (ovr)
-                       goto override;
-               return ret;
-       }
-
-       p = kmalloc(sizeof(*p), GFP_KERNEL);
-       if (p == NULL)
-               return -ENOMEM;
-       memset(p, 0, sizeof(*p));
-
-       ret = ACT_P_CREATED;
-       p->refcnt = 1;
-       spin_lock_init(&p->lock);
-       p->stats_lock = &p->lock;
-       if (bind)
-               p->bindcnt = 1;
-override:
-       if (parm->rate.rate) {
-               err = -ENOMEM;
-               R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
-               if (R_tab == NULL)
-                       goto failure;
-               if (parm->peakrate.rate) {
-                       P_tab = qdisc_get_rtab(&parm->peakrate,
-                                              tb[TCA_POLICE_PEAKRATE-1]);
-                       if (p->P_tab == NULL) {
-                               qdisc_put_rtab(R_tab);
-                               goto failure;
-                       }
-               }
-       }
-       /* No failure allowed after this point */
-       spin_lock_bh(&p->lock);
-       if (R_tab != NULL) {
-               qdisc_put_rtab(p->R_tab);
-               p->R_tab = R_tab;
-       }
-       if (P_tab != NULL) {
-               qdisc_put_rtab(p->P_tab);
-               p->P_tab = P_tab;
-       }
-
-       if (tb[TCA_POLICE_RESULT-1])
-               p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
-       p->toks = p->burst = parm->burst;
-       p->mtu = parm->mtu;
-       if (p->mtu == 0) {
-               p->mtu = ~0;
-               if (p->R_tab)
-                       p->mtu = 255<<p->R_tab->rate.cell_log;
-       }
-       if (p->P_tab)
-               p->ptoks = L2T_P(p, p->mtu);
-       p->action = parm->action;
-
-#ifdef CONFIG_NET_ESTIMATOR
-       if (tb[TCA_POLICE_AVRATE-1])
-               p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
-       if (est)
-               gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
-#endif
-
-       spin_unlock_bh(&p->lock);
-       if (ret != ACT_P_CREATED)
-               return ret;
-
-       PSCHED_GET_TIME(p->t_c);
-       p->index = parm->index ? : tcf_police_new_index();
-       h = tcf_police_hash(p->index);
-       write_lock_bh(&police_lock);
-       p->next = tcf_police_ht[h];
-       tcf_police_ht[h] = p;
-       write_unlock_bh(&police_lock);
-
-       a->priv = p;
-       return ret;
-
-failure:
-       if (ret == ACT_P_CREATED)
-               kfree(p);
-       return err;
-}
-
-static int tcf_act_police_cleanup(struct tc_action *a, int bind)
-{
-       struct tcf_police *p = PRIV(a);
-
-       if (p != NULL)
-               return tcf_police_release(p, bind);
-       return 0;
-}
-
-static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
-                          struct tcf_result *res)
-{
-       psched_time_t now;
-       struct tcf_police *p = PRIV(a);
-       long toks;
-       long ptoks = 0;
-
-       spin_lock(&p->lock);
-
-       p->bstats.bytes += skb->len;
-       p->bstats.packets++;
-
-#ifdef CONFIG_NET_ESTIMATOR
-       if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) {
-               p->qstats.overlimits++;
-               spin_unlock(&p->lock);
-               return p->action;
-       }
-#endif
-
-       if (skb->len <= p->mtu) {
-               if (p->R_tab == NULL) {
-                       spin_unlock(&p->lock);
-                       return p->result;
-               }
-
-               PSCHED_GET_TIME(now);
-
-               toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst);
-
-               if (p->P_tab) {
-                       ptoks = toks + p->ptoks;
-                       if (ptoks > (long)L2T_P(p, p->mtu))
-                               ptoks = (long)L2T_P(p, p->mtu);
-                       ptoks -= L2T_P(p, skb->len);
-               }
-               toks += p->toks;
-               if (toks > (long)p->burst)
-                       toks = p->burst;
-               toks -= L2T(p, skb->len);
-
-               if ((toks|ptoks) >= 0) {
-                       p->t_c = now;
-                       p->toks = toks;
-                       p->ptoks = ptoks;
-                       spin_unlock(&p->lock);
-                       return p->result;
-               }
-       }
-
-       p->qstats.overlimits++;
-       spin_unlock(&p->lock);
-       return p->action;
-}
-
-static int
-tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
-{
-       unsigned char    *b = skb->tail;
-       struct tc_police opt;
-       struct tcf_police *p = PRIV(a);
-
-       opt.index = p->index;
-       opt.action = p->action;
-       opt.mtu = p->mtu;
-       opt.burst = p->burst;
-       opt.refcnt = p->refcnt - ref;
-       opt.bindcnt = p->bindcnt - bind;
-       if (p->R_tab)
-               opt.rate = p->R_tab->rate;
-       else
-               memset(&opt.rate, 0, sizeof(opt.rate));
-       if (p->P_tab)
-               opt.peakrate = p->P_tab->rate;
-       else
-               memset(&opt.peakrate, 0, sizeof(opt.peakrate));
-       RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
-       if (p->result)
-               RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result);
-#ifdef CONFIG_NET_ESTIMATOR
-       if (p->ewma_rate)
-               RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate);
-#endif
-       return skb->len;
-
-rtattr_failure:
-       skb_trim(skb, b - skb->data);
-       return -1;
-}
-
-MODULE_AUTHOR("Alexey Kuznetsov");
-MODULE_DESCRIPTION("Policing actions");
-MODULE_LICENSE("GPL");
-
-static struct tc_action_ops act_police_ops = {
-       .kind           =       "police",
-       .type           =       TCA_ID_POLICE,
-       .capab          =       TCA_CAP_NONE,
-       .owner          =       THIS_MODULE,
-       .act            =       tcf_act_police,
-       .dump           =       tcf_act_police_dump,
-       .cleanup        =       tcf_act_police_cleanup,
-       .lookup         =       tcf_hash_search,
-       .init           =       tcf_act_police_locate,
-       .walk           =       tcf_generic_walker
-};
-
-static int __init
-police_init_module(void)
-{
-       return tcf_register_action(&act_police_ops);
-}
-
-static void __exit
-police_cleanup_module(void)
-{
-       tcf_unregister_action(&act_police_ops);
-}
-
-module_init(police_init_module);
-module_exit(police_cleanup_module);
-
-#else /* CONFIG_NET_CLS_ACT */
-
-struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
-{
-       unsigned h;
-       struct tcf_police *p;
-       struct rtattr *tb[TCA_POLICE_MAX];
-       struct tc_police *parm;
-
-       if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
-               return NULL;
-
-       if (tb[TCA_POLICE_TBF-1] == NULL ||
-           RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm))
-               return NULL;
-
-       parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
-
-       if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
-               p->refcnt++;
-               return p;
-       }
-
-       p = kmalloc(sizeof(*p), GFP_KERNEL);
-       if (p == NULL)
-               return NULL;
-
-       memset(p, 0, sizeof(*p));
-       p->refcnt = 1;
-       spin_lock_init(&p->lock);
-       p->stats_lock = &p->lock;
-       if (parm->rate.rate) {
-               p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
-               if (p->R_tab == NULL)
-                       goto failure;
-               if (parm->peakrate.rate) {
-                       p->P_tab = qdisc_get_rtab(&parm->peakrate,
-                                                 tb[TCA_POLICE_PEAKRATE-1]);
-                       if (p->P_tab == NULL)
-                               goto failure;
-               }
-       }
-       if (tb[TCA_POLICE_RESULT-1]) {
-               if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
-                       goto failure;
-               p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
-       }
-#ifdef CONFIG_NET_ESTIMATOR
-       if (tb[TCA_POLICE_AVRATE-1]) {
-               if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32))
-                       goto failure;
-               p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
-       }
-#endif
-       p->toks = p->burst = parm->burst;
-       p->mtu = parm->mtu;
-       if (p->mtu == 0) {
-               p->mtu = ~0;
-               if (p->R_tab)
-                       p->mtu = 255<<p->R_tab->rate.cell_log;
-       }
-       if (p->P_tab)
-               p->ptoks = L2T_P(p, p->mtu);
-       PSCHED_GET_TIME(p->t_c);
-       p->index = parm->index ? : tcf_police_new_index();
-       p->action = parm->action;
-#ifdef CONFIG_NET_ESTIMATOR
-       if (est)
-               gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
-#endif
-       h = tcf_police_hash(p->index);
-       write_lock_bh(&police_lock);
-       p->next = tcf_police_ht[h];
-       tcf_police_ht[h] = p;
-       write_unlock_bh(&police_lock);
-       return p;
-
-failure:
-       if (p->R_tab)
-               qdisc_put_rtab(p->R_tab);
-       kfree(p);
-       return NULL;
-}
-
-int tcf_police(struct sk_buff *skb, struct tcf_police *p)
-{
-       psched_time_t now;
-       long toks;
-       long ptoks = 0;
-
-       spin_lock(&p->lock);
-
-       p->bstats.bytes += skb->len;
-       p->bstats.packets++;
-
-#ifdef CONFIG_NET_ESTIMATOR
-       if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) {
-               p->qstats.overlimits++;
-               spin_unlock(&p->lock);
-               return p->action;
-       }
-#endif
-
-       if (skb->len <= p->mtu) {
-               if (p->R_tab == NULL) {
-                       spin_unlock(&p->lock);
-                       return p->result;
-               }
-
-               PSCHED_GET_TIME(now);
-
-               toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst);
-
-               if (p->P_tab) {
-                       ptoks = toks + p->ptoks;
-                       if (ptoks > (long)L2T_P(p, p->mtu))
-                               ptoks = (long)L2T_P(p, p->mtu);
-                       ptoks -= L2T_P(p, skb->len);
-               }
-               toks += p->toks;
-               if (toks > (long)p->burst)
-                       toks = p->burst;
-               toks -= L2T(p, skb->len);
-
-               if ((toks|ptoks) >= 0) {
-                       p->t_c = now;
-                       p->toks = toks;
-                       p->ptoks = ptoks;
-                       spin_unlock(&p->lock);
-                       return p->result;
-               }
-       }
-
-       p->qstats.overlimits++;
-       spin_unlock(&p->lock);
-       return p->action;
-}
-EXPORT_SYMBOL(tcf_police);
-
-int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p)
-{
-       unsigned char    *b = skb->tail;
-       struct tc_police opt;
-
-       opt.index = p->index;
-       opt.action = p->action;
-       opt.mtu = p->mtu;
-       opt.burst = p->burst;
-       if (p->R_tab)
-               opt.rate = p->R_tab->rate;
-       else
-               memset(&opt.rate, 0, sizeof(opt.rate));
-       if (p->P_tab)
-               opt.peakrate = p->P_tab->rate;
-       else
-               memset(&opt.peakrate, 0, sizeof(opt.peakrate));
-       RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
-       if (p->result)
-               RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result);
-#ifdef CONFIG_NET_ESTIMATOR
-       if (p->ewma_rate)
-               RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate);
-#endif
-       return skb->len;
-
-rtattr_failure:
-       skb_trim(skb, b - skb->data);
-       return -1;
-}
-
-int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p)
-{
-       struct gnet_dump d;
-       
-       if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
-                       TCA_XSTATS, p->stats_lock, &d) < 0)
-               goto errout;
-       
-       if (gnet_stats_copy_basic(&d, &p->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
-           gnet_stats_copy_rate_est(&d, &p->rate_est) < 0 ||
-#endif
-           gnet_stats_copy_queue(&d, &p->qstats) < 0)
-               goto errout;
-
-       if (gnet_stats_finish_copy(&d) < 0)
-               goto errout;
-
-       return 0;
-
-errout:
-       return -1;
-}
-
-#endif /* CONFIG_NET_CLS_ACT */
diff --git a/net/sched/simple.c b/net/sched/simple.c
deleted file mode 100644 (file)
index e5f2e1f..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * net/sched/simp.c    Simple example of an action
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- *
- * Authors:    Jamal Hadi Salim (2005)
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
-#include <net/pkt_sched.h>
-
-#define TCA_ACT_SIMP 22
-
-/* XXX: Hide all these common elements under some macro 
- * probably
-*/
-#include <linux/tc_act/tc_defact.h>
-#include <net/tc_act/tc_defact.h>
-
-/* use generic hash table with 8 buckets */
-#define MY_TAB_SIZE     8
-#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
-static u32 idx_gen;
-static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE];
-static DEFINE_RWLOCK(simp_lock);
-
-/* override the defaults */
-#define tcf_st         tcf_defact
-#define tc_st          tc_defact
-#define tcf_t_lock     simp_lock
-#define tcf_ht         tcf_simp_ht
-
-#define CONFIG_NET_ACT_INIT 1
-#include <net/pkt_act.h>
-#include <net/act_generic.h>
-
-static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
-{
-       struct tcf_defact *p = PRIV(a, defact);
-
-       spin_lock(&p->lock);
-       p->tm.lastuse = jiffies;
-       p->bstats.bytes += skb->len;
-       p->bstats.packets++;
-
-       /* print policy string followed by _ then packet count 
-        * Example if this was the 3rd packet and the string was "hello" 
-        * then it would look like "hello_3" (without quotes) 
-        **/
-       printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets);
-       spin_unlock(&p->lock);
-       return p->action;
-}
-
-static struct tc_action_ops act_simp_ops = {
-       .kind = "simple",
-       .type = TCA_ACT_SIMP,
-       .capab = TCA_CAP_NONE,
-       .owner = THIS_MODULE,
-       .act = tcf_simp,
-       tca_use_default_ops
-};
-
-MODULE_AUTHOR("Jamal Hadi Salim(2005)");
-MODULE_DESCRIPTION("Simple example action");
-MODULE_LICENSE("GPL");
-
-static int __init simp_init_module(void)
-{
-       int ret = tcf_register_action(&act_simp_ops);
-       if (!ret)
-               printk("Simple TC action Loaded\n");
-       return ret;
-}
-
-static void __exit simp_cleanup_module(void)
-{
-       tcf_unregister_action(&act_simp_ops);
-}
-
-module_init(simp_init_module);
-module_exit(simp_cleanup_module);