fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / sched / act_mirred.c
index 4fcccbd..7263a2e 100644 (file)
@@ -15,7 +15,6 @@
 #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/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];
+#define MIRRED_TAB_MASK     7
+static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1];
+static u32 mirred_idx_gen;
 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 struct tcf_hashinfo mirred_hash_info = {
+       .htab   =       tcf_mirred_ht,
+       .hmask  =       MIRRED_TAB_MASK,
+       .lock   =       &mirred_lock,
+};
 
-static inline int
-tcf_mirred_release(struct tcf_mirred *p, int bind)
+static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)
 {
-       if (p) {
+       if (m) {
                if (bind)
-                       p->bindcnt--;
-               p->refcnt--;
-               if(!p->bindcnt && p->refcnt <= 0) {
-                       dev_put(p->dev);
-                       tcf_hash_destroy(p);
+                       m->tcf_bindcnt--;
+               m->tcf_refcnt--;
+               if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
+                       dev_put(m->tcfm_dev);
+                       tcf_hash_destroy(&m->common, &mirred_hash_info);
                        return 1;
                }
        }
        return 0;
 }
 
-static int
-tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
-                int ovr, int bind)
+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 tcf_mirred *m;
+       struct tcf_common *pc;
        struct net_device *dev = NULL;
        int ret = 0;
        int ok_push = 0;
@@ -111,64 +103,62 @@ tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
                }
        }
 
-       p = tcf_hash_check(parm->index, a, ovr, bind);
-       if (p == NULL) {
+       pc = tcf_hash_check(parm->index, a, bind, &mirred_hash_info);
+       if (!pc) {
                if (!parm->ifindex)
                        return -EINVAL;
-               p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
-               if (p == NULL)
+               pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind,
+                                    &mirred_idx_gen, &mirred_hash_info);
+               if (unlikely(!pc))
                        return -ENOMEM;
                ret = ACT_P_CREATED;
        } else {
                if (!ovr) {
-                       tcf_mirred_release(p, bind);
+                       tcf_mirred_release(to_mirred(pc), bind);
                        return -EEXIST;
                }
        }
+       m = to_mirred(pc);
 
-       spin_lock_bh(&p->lock);
-       p->action = parm->action;
-       p->eaction = parm->eaction;
+       spin_lock_bh(&m->tcf_lock);
+       m->tcf_action = parm->action;
+       m->tcfm_eaction = parm->eaction;
        if (parm->ifindex) {
-               p->ifindex = parm->ifindex;
+               m->tcfm_ifindex = parm->ifindex;
                if (ret != ACT_P_CREATED)
-                       dev_put(p->dev);
-               p->dev = dev;
+                       dev_put(m->tcfm_dev);
+               m->tcfm_dev = dev;
                dev_hold(dev);
-               p->ok_push = ok_push;
+               m->tcfm_ok_push = ok_push;
        }
-       spin_unlock_bh(&p->lock);
+       spin_unlock_bh(&m->tcf_lock);
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(p);
+               tcf_hash_insert(pc, &mirred_hash_info);
 
-       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)
+static int tcf_mirred_cleanup(struct tc_action *a, int bind)
 {
-       struct tcf_mirred *p = PRIV(a, mirred);
+       struct tcf_mirred *m = a->priv;
 
-       if (p != NULL)
-               return tcf_mirred_release(p, bind);
+       if (m)
+               return tcf_mirred_release(m, bind);
        return 0;
 }
 
-static int
-tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
+static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
+                     struct tcf_result *res)
 {
-       struct tcf_mirred *p = PRIV(a, mirred);
+       struct tcf_mirred *m = a->priv;
        struct net_device *dev;
        struct sk_buff *skb2 = NULL;
        u32 at = G_TC_AT(skb->tc_verd);
 
-       spin_lock(&p->lock);
+       spin_lock(&m->tcf_lock);
 
-       dev = p->dev;
-       p->tm.lastuse = jiffies;
+       dev = m->tcfm_dev;
+       m->tcf_tm.lastuse = jiffies;
 
        if (!(dev->flags&IFF_UP) ) {
                if (net_ratelimit())
@@ -177,10 +167,10 @@ tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
 bad_mirred:
                if (skb2 != NULL)
                        kfree_skb(skb2);
-               p->qstats.overlimits++;
-               p->bstats.bytes += skb->len;
-               p->bstats.packets++;
-               spin_unlock(&p->lock);
+               m->tcf_qstats.overlimits++;
+               m->tcf_bstats.bytes += skb->len;
+               m->tcf_bstats.packets++;
+               spin_unlock(&m->tcf_lock);
                /* should we be asking for packet to be dropped?
                 * may make sense for redirect case only
                */
@@ -190,59 +180,59 @@ bad_mirred:
        skb2 = skb_clone(skb, GFP_ATOMIC);
        if (skb2 == NULL)
                goto bad_mirred;
-       if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) {
+       if (m->tcfm_eaction != TCA_EGRESS_MIRROR &&
+           m->tcfm_eaction != TCA_EGRESS_REDIR) {
                if (net_ratelimit())
-                       printk("tcf_mirred unknown action %d\n", p->eaction);
+                       printk("tcf_mirred unknown action %d\n",
+                              m->tcfm_eaction);
                goto bad_mirred;
        }
 
-       p->bstats.bytes += skb2->len;
-       p->bstats.packets++;
+       m->tcf_bstats.bytes += skb2->len;
+       m->tcf_bstats.packets++;
        if (!(at & AT_EGRESS))
-               if (p->ok_push)
+               if (m->tcfm_ok_push)
                        skb_push(skb2, skb2->dev->hard_header_len);
 
        /* mirror is always swallowed */
-       if (p->eaction != TCA_EGRESS_MIRROR)
+       if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
                skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
 
        skb2->dev = dev;
-       skb2->input_dev = skb->dev;
+       skb2->iif = skb->dev->ifindex;
        dev_queue_xmit(skb2);
-       spin_unlock(&p->lock);
-       return p->action;
+       spin_unlock(&m->tcf_lock);
+       return m->tcf_action;
 }
 
-static int
-tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
        unsigned char *b = skb->tail;
+       struct tcf_mirred *m = a->priv;
        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);
+       opt.index = m->tcf_index;
+       opt.action = m->tcf_action;
+       opt.refcnt = m->tcf_refcnt - ref;
+       opt.bindcnt = m->tcf_bindcnt - bind;
+       opt.eaction = m->tcfm_eaction;
+       opt.ifindex = m->tcfm_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);
+       t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install);
+       t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse);
+       t.expires = jiffies_to_clock_t(m->tcf_tm.expires);
        RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t);
        return skb->len;
 
-      rtattr_failure:
+rtattr_failure:
        skb_trim(skb, b - skb->data);
        return -1;
 }
 
 static struct tc_action_ops act_mirred_ops = {
        .kind           =       "mirred",
+       .hinfo          =       &mirred_hash_info,
        .type           =       TCA_ACT_MIRRED,
        .capab          =       TCA_CAP_NONE,
        .owner          =       THIS_MODULE,
@@ -258,15 +248,13 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002)");
 MODULE_DESCRIPTION("Device Mirror/redirect actions");
 MODULE_LICENSE("GPL");
 
-static int __init
-mirred_init_module(void)
+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)
+static void __exit mirred_cleanup_module(void)
 {
        tcf_unregister_action(&act_mirred_ops);
 }