vserver 1.9.5.x5
[linux-2.6.git] / net / sched / sch_ingress.c
index 37eb5df..8edc32a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
 #include <linux/netfilter.h>
 #include <linux/smp.h>
 #include <net/pkt_sched.h>
 #endif
 
 
-#define PRIV(sch) ((struct ingress_qdisc_data *) (sch)->data)
+#define PRIV(sch) qdisc_priv(sch)
 
 
 /* Thanks to Doron Oz for this hack
 */
+#ifndef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NETFILTER
 static int nf_registered; 
+#endif
+#endif
 
 struct ingress_qdisc_data {
        struct Qdisc            *q;
@@ -146,27 +151,52 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
         * Unlike normal "enqueue" functions, ingress_enqueue returns a
         * firewall FW_* code.
         */
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
+       sch->bstats.packets++;
+       sch->bstats.bytes += skb->len;
        switch (result) {
-               case TC_POLICE_SHOT:
-                       result = NF_DROP;
-                       sch->stats.drops++;
+               case TC_ACT_SHOT:
+                       result = TC_ACT_SHOT;
+                       sch->qstats.drops++;
+                       break;
+               case TC_ACT_STOLEN:
+               case TC_ACT_QUEUED:
+                       result = TC_ACT_STOLEN;
                        break;
+               case TC_ACT_RECLASSIFY: 
+               case TC_ACT_OK:
+               case TC_ACT_UNSPEC:
+               default:
+                       skb->tc_index = TC_H_MIN(res.classid);
+                       result = TC_ACT_OK;
+                       break;
+       };
+/* backward compat */
+#else
+#ifdef CONFIG_NET_CLS_POLICE  
+       switch (result) {
+               case TC_POLICE_SHOT:
+               result = NF_DROP;
+               sch->qstats.drops++;
+               break;
                case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
                case TC_POLICE_OK:
                case TC_POLICE_UNSPEC:
                default:
-                       sch->stats.packets++;
-                       sch->stats.bytes += skb->len;
-                       result = NF_ACCEPT;
-                       break;
+               sch->bstats.packets++;
+               sch->bstats.bytes += skb->len;
+               result = NF_ACCEPT;
+               break;
        };
+
 #else
-       sch->stats.packets++;
-       sch->stats.bytes += skb->len;
+       D2PRINTK("Overriding result to ACCEPT\n");
+       result = NF_ACCEPT;
+       sch->bstats.packets++;
+       sch->bstats.bytes += skb->len;
+#endif
 #endif
 
-       skb->tc_index = TC_H_MIN(res.classid);
        return result;
 }
 
@@ -199,6 +229,8 @@ static unsigned int ingress_drop(struct Qdisc *sch)
        return 0;
 }
 
+#ifndef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NETFILTER
 static unsigned int
 ing_hook(unsigned int hook, struct sk_buff **pskb,
                              const struct net_device *indev,
@@ -240,25 +272,53 @@ static struct nf_hook_ops ing_ops = {
        .priority       = NF_IP_PRI_FILTER + 1,
 };
 
-int ingress_init(struct Qdisc *sch,struct rtattr *opt)
+static struct nf_hook_ops ing6_ops = {
+       .hook           = ing_hook,
+       .owner          = THIS_MODULE,
+       .pf             = PF_INET6,
+       .hooknum        = NF_IP6_PRE_ROUTING,
+       .priority       = NF_IP6_PRI_FILTER + 1,
+};
+
+#endif
+#endif
+
+static int ingress_init(struct Qdisc *sch,struct rtattr *opt)
 {
        struct ingress_qdisc_data *p = PRIV(sch);
 
+/* Make sure either netfilter or preferably CLS_ACT is
+* compiled in */
+#ifndef CONFIG_NET_CLS_ACT
+#ifndef CONFIG_NETFILTER
+       printk("You MUST compile classifier actions into the kernel\n");
+       return -EINVAL;
+#else
+       printk("Ingress scheduler: Classifier actions prefered over netfilter\n");
+#endif
+#endif
+                                                                                
+#ifndef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NETFILTER
        if (!nf_registered) {
                if (nf_register_hook(&ing_ops) < 0) {
                        printk("ingress qdisc registration error \n");
-                       goto error;
+                       return -EINVAL;
                }
                nf_registered++;
+
+               if (nf_register_hook(&ing6_ops) < 0) {
+                       printk("IPv6 ingress qdisc registration error, " \
+                           "disabling IPv6 support.\n");
+               } else
+                       nf_registered++;
        }
+#endif
+#endif
 
        DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
-       memset(p, 0, sizeof(*p));
-       p->filter_list = NULL;
        p->q = &noop_qdisc;
        return 0;
-error:
-       return -EINVAL;
 }
 
 
@@ -294,9 +354,6 @@ static void ingress_destroy(struct Qdisc *sch)
                p->filter_list = tp->next;
                tcf_destroy(tp);
        }
-       memset(p, 0, sizeof(*p));
-       p->filter_list = NULL;
-
 #if 0
 /* for future use */
        qdisc_destroy(p->q);
@@ -364,8 +421,15 @@ static int __init ingress_module_init(void)
 static void __exit ingress_module_exit(void) 
 {
        unregister_qdisc(&ingress_qdisc_ops);
-       if (nf_registered)
+#ifndef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NETFILTER
+       if (nf_registered) {
                nf_unregister_hook(&ing_ops);
+               if (nf_registered > 1)
+                       nf_unregister_hook(&ing6_ops);
+       }
+#endif
+#endif
 }
 module_init(ingress_module_init)
 module_exit(ingress_module_exit)