net: wireless: Add CFG80211_ALLOW_RECONNECT option
[linux-2.6.git] / net / sched / cls_rsvp.h
index ba87419..b014279 100644 (file)
    powerful classification engine.  */
 
 
-struct rsvp_head
-{
+struct rsvp_head {
        u32                     tmap[256/32];
        u32                     hgenerator;
        u8                      tgenerator;
        struct rsvp_session     *ht[256];
 };
 
-struct rsvp_session
-{
+struct rsvp_session {
        struct rsvp_session     *next;
-       u32                     dst[RSVP_DST_LEN];
+       __be32                  dst[RSVP_DST_LEN];
        struct tc_rsvp_gpi      dpi;
        u8                      protocol;
        u8                      tunnelid;
        /* 16 (src,sport) hash slots, and one wildcard source slot */
-       struct rsvp_filter      *ht[16+1];
+       struct rsvp_filter      *ht[16 + 1];
 };
 
 
-struct rsvp_filter
-{
+struct rsvp_filter {
        struct rsvp_filter      *next;
-       u32                     src[RSVP_DST_LEN];
+       __be32                  src[RSVP_DST_LEN];
        struct tc_rsvp_gpi      spi;
        u8                      tunnelhdr;
 
@@ -100,17 +97,19 @@ struct rsvp_filter
        struct rsvp_session     *sess;
 };
 
-static __inline__ unsigned hash_dst(u32 *dst, u8 protocol, u8 tunnelid)
+static inline unsigned int hash_dst(__be32 *dst, u8 protocol, u8 tunnelid)
 {
-       unsigned h = dst[RSVP_DST_LEN-1];
+       unsigned int h = (__force __u32)dst[RSVP_DST_LEN - 1];
+
        h ^= h>>16;
        h ^= h>>8;
        return (h ^ protocol ^ tunnelid) & 0xFF;
 }
 
-static __inline__ unsigned hash_src(u32 *src)
+static inline unsigned int hash_src(__be32 *src)
 {
-       unsigned h = src[RSVP_DST_LEN-1];
+       unsigned int h = (__force __u32)src[RSVP_DST_LEN-1];
+
        h ^= h>>16;
        h ^= h>>8;
        h ^= h>>4;
@@ -130,22 +129,30 @@ static struct tcf_ext_map rsvp_ext_map = {
        else if (r > 0)                                 \
                return r;                               \
 }
-       
-static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
+
+static int rsvp_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                         struct tcf_result *res)
 {
-       struct rsvp_session **sht = ((struct rsvp_head*)tp->root)->ht;
+       struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht;
        struct rsvp_session *s;
        struct rsvp_filter *f;
-       unsigned h1, h2;
-       u32 *dst, *src;
+       unsigned int h1, h2;
+       __be32 *dst, *src;
        u8 protocol;
        u8 tunnelid = 0;
        u8 *xprt;
 #if RSVP_DST_LEN == 4
-       struct ipv6hdr *nhptr = skb->nh.ipv6h;
+       struct ipv6hdr *nhptr;
+
+       if (!pskb_network_may_pull(skb, sizeof(*nhptr)))
+               return -1;
+       nhptr = ipv6_hdr(skb);
 #else
-       struct iphdr *nhptr = skb->nh.iph;
+       struct iphdr *nhptr;
+
+       if (!pskb_network_may_pull(skb, sizeof(*nhptr)))
+               return -1;
+       nhptr = ip_hdr(skb);
 #endif
 
 restart:
@@ -154,13 +161,13 @@ restart:
        src = &nhptr->saddr.s6_addr32[0];
        dst = &nhptr->daddr.s6_addr32[0];
        protocol = nhptr->nexthdr;
-       xprt = ((u8*)nhptr) + sizeof(struct ipv6hdr);
+       xprt = ((u8 *)nhptr) + sizeof(struct ipv6hdr);
 #else
        src = &nhptr->saddr;
        dst = &nhptr->daddr;
        protocol = nhptr->protocol;
-       xprt = ((u8*)nhptr) + (nhptr->ihl<<2);
-       if (nhptr->frag_off&__constant_htons(IP_MF|IP_OFFSET))
+       xprt = ((u8 *)nhptr) + (nhptr->ihl<<2);
+       if (ip_is_fragment(nhptr))
                return -1;
 #endif
 
@@ -168,23 +175,25 @@ restart:
        h2 = hash_src(src);
 
        for (s = sht[h1]; s; s = s->next) {
-               if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] &&
+               if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN - 1] &&
                    protocol == s->protocol &&
-                   !(s->dpi.mask & (*(u32*)(xprt+s->dpi.offset)^s->dpi.key))
+                   !(s->dpi.mask &
+                     (*(u32 *)(xprt + s->dpi.offset) ^ s->dpi.key)) &&
 #if RSVP_DST_LEN == 4
-                   && dst[0] == s->dst[0]
-                   && dst[1] == s->dst[1]
-                   && dst[2] == s->dst[2]
+                   dst[0] == s->dst[0] &&
+                   dst[1] == s->dst[1] &&
+                   dst[2] == s->dst[2] &&
 #endif
-                   && tunnelid == s->tunnelid) {
+                   tunnelid == s->tunnelid) {
 
                        for (f = s->ht[h2]; f; f = f->next) {
-                               if (src[RSVP_DST_LEN-1] == f->src[RSVP_DST_LEN-1] &&
-                                   !(f->spi.mask & (*(u32*)(xprt+f->spi.offset)^f->spi.key))
+                               if (src[RSVP_DST_LEN-1] == f->src[RSVP_DST_LEN - 1] &&
+                                   !(f->spi.mask & (*(u32 *)(xprt + f->spi.offset) ^ f->spi.key))
 #if RSVP_DST_LEN == 4
-                                   && src[0] == f->src[0]
-                                   && src[1] == f->src[1]
-                                   && src[2] == f->src[2]
+                                   &&
+                                   src[0] == f->src[0] &&
+                                   src[1] == f->src[1] &&
+                                   src[2] == f->src[2]
 #endif
                                    ) {
                                        *res = f->res;
@@ -195,7 +204,7 @@ matched:
                                                return 0;
 
                                        tunnelid = f->res.classid;
-                                       nhptr = (void*)(xprt + f->tunnelhdr - sizeof(*nhptr));
+                                       nhptr = (void *)(xprt + f->tunnelhdr - sizeof(*nhptr));
                                        goto restart;
                                }
                        }
@@ -214,11 +223,11 @@ matched:
 
 static unsigned long rsvp_get(struct tcf_proto *tp, u32 handle)
 {
-       struct rsvp_session **sht = ((struct rsvp_head*)tp->root)->ht;
+       struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht;
        struct rsvp_session *s;
        struct rsvp_filter *f;
-       unsigned h1 = handle&0xFF;
-       unsigned h2 = (handle>>8)&0xFF;
+       unsigned int h1 = handle & 0xFF;
+       unsigned int h2 = (handle >> 8) & 0xFF;
 
        if (h2 > 16)
                return 0;
@@ -240,16 +249,15 @@ static int rsvp_init(struct tcf_proto *tp)
 {
        struct rsvp_head *data;
 
-       data = kmalloc(sizeof(struct rsvp_head), GFP_KERNEL);
+       data = kzalloc(sizeof(struct rsvp_head), GFP_KERNEL);
        if (data) {
-               memset(data, 0, sizeof(struct rsvp_head));
                tp->root = data;
                return 0;
        }
        return -ENOBUFS;
 }
 
-static inline void
+static void
 rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f)
 {
        tcf_unbind_filter(tp, &f->res);
@@ -268,13 +276,13 @@ static void rsvp_destroy(struct tcf_proto *tp)
 
        sht = data->ht;
 
-       for (h1=0; h1<256; h1++) {
+       for (h1 = 0; h1 < 256; h1++) {
                struct rsvp_session *s;
 
                while ((s = sht[h1]) != NULL) {
                        sht[h1] = s->next;
 
-                       for (h2=0; h2<=16; h2++) {
+                       for (h2 = 0; h2 <= 16; h2++) {
                                struct rsvp_filter *f;
 
                                while ((f = s->ht[h2]) != NULL) {
@@ -290,13 +298,13 @@ static void rsvp_destroy(struct tcf_proto *tp)
 
 static int rsvp_delete(struct tcf_proto *tp, unsigned long arg)
 {
-       struct rsvp_filter **fp, *f = (struct rsvp_filter*)arg;
-       unsigned h = f->handle;
+       struct rsvp_filter **fp, *f = (struct rsvp_filter *)arg;
+       unsigned int h = f->handle;
        struct rsvp_session **sp;
        struct rsvp_session *s = f->sess;
        int i;
 
-       for (fp = &s->ht[(h>>8)&0xFF]; *fp; fp = &(*fp)->next) {
+       for (fp = &s->ht[(h >> 8) & 0xFF]; *fp; fp = &(*fp)->next) {
                if (*fp == f) {
                        tcf_tree_lock(tp);
                        *fp = f->next;
@@ -305,12 +313,12 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg)
 
                        /* Strip tree */
 
-                       for (i=0; i<=16; i++)
+                       for (i = 0; i <= 16; i++)
                                if (s->ht[i])
                                        return 0;
 
                        /* OK, session has no flows */
-                       for (sp = &((struct rsvp_head*)tp->root)->ht[h&0xFF];
+                       for (sp = &((struct rsvp_head *)tp->root)->ht[h & 0xFF];
                             *sp; sp = &(*sp)->next) {
                                if (*sp == s) {
                                        tcf_tree_lock(tp);
@@ -328,13 +336,14 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg)
        return 0;
 }
 
-static unsigned gen_handle(struct tcf_proto *tp, unsigned salt)
+static unsigned int gen_handle(struct tcf_proto *tp, unsigned salt)
 {
        struct rsvp_head *data = tp->root;
        int i = 0xFFFF;
 
        while (i-- > 0) {
                u32 h;
+
                if ((data->hgenerator += 0x10000) == 0)
                        data->hgenerator = 0x10000;
                h = data->hgenerator|salt;
@@ -346,10 +355,10 @@ static unsigned gen_handle(struct tcf_proto *tp, unsigned salt)
 
 static int tunnel_bts(struct rsvp_head *data)
 {
-       int n = data->tgenerator>>5;
-       u32 b = 1<<(data->tgenerator&0x1F);
-       
-       if (data->tmap[n]&b)
+       int n = data->tgenerator >> 5;
+       u32 b = 1 << (data->tgenerator & 0x1F);
+
+       if (data->tmap[n] & b)
                return 0;
        data->tmap[n] |= b;
        return 1;
@@ -363,10 +372,10 @@ static void tunnel_recycle(struct rsvp_head *data)
 
        memset(tmap, 0, sizeof(tmap));
 
-       for (h1=0; h1<256; h1++) {
+       for (h1 = 0; h1 < 256; h1++) {
                struct rsvp_session *s;
                for (s = sht[h1]; s; s = s->next) {
-                       for (h2=0; h2<=16; h2++) {
+                       for (h2 = 0; h2 <= 16; h2++) {
                                struct rsvp_filter *f;
 
                                for (f = s->ht[h2]; f; f = f->next) {
@@ -386,8 +395,8 @@ static u32 gen_tunnel(struct rsvp_head *data)
 {
        int i, k;
 
-       for (k=0; k<2; k++) {
-               for (i=255; i>0; i--) {
+       for (k = 0; k < 2; k++) {
+               for (i = 255; i > 0; i--) {
                        if (++data->tgenerator == 0)
                                data->tgenerator = 1;
                        if (tunnel_bts(data))
@@ -398,39 +407,50 @@ static u32 gen_tunnel(struct rsvp_head *data)
        return 0;
 }
 
+static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = {
+       [TCA_RSVP_CLASSID]      = { .type = NLA_U32 },
+       [TCA_RSVP_DST]          = { .type = NLA_BINARY,
+                                   .len = RSVP_DST_LEN * sizeof(u32) },
+       [TCA_RSVP_SRC]          = { .type = NLA_BINARY,
+                                   .len = RSVP_DST_LEN * sizeof(u32) },
+       [TCA_RSVP_PINFO]        = { .len = sizeof(struct tc_rsvp_pinfo) },
+};
+
 static int rsvp_change(struct tcf_proto *tp, unsigned long base,
                       u32 handle,
-                      struct rtattr **tca,
+                      struct nlattr **tca,
                       unsigned long *arg)
 {
        struct rsvp_head *data = tp->root;
        struct rsvp_filter *f, **fp;
        struct rsvp_session *s, **sp;
        struct tc_rsvp_pinfo *pinfo = NULL;
-       struct rtattr *opt = tca[TCA_OPTIONS-1];
-       struct rtattr *tb[TCA_RSVP_MAX];
+       struct nlattr *opt = tca[TCA_OPTIONS];
+       struct nlattr *tb[TCA_RSVP_MAX + 1];
        struct tcf_exts e;
-       unsigned h1, h2;
-       u32 *dst;
+       unsigned int h1, h2;
+       __be32 *dst;
        int err;
 
        if (opt == NULL)
                return handle ? -EINVAL : 0;
 
-       if (rtattr_parse_nested(tb, TCA_RSVP_MAX, opt) < 0)
-               return -EINVAL;
+       err = nla_parse_nested(tb, TCA_RSVP_MAX, opt, rsvp_policy);
+       if (err < 0)
+               return err;
 
-       err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &rsvp_ext_map);
+       err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &rsvp_ext_map);
        if (err < 0)
                return err;
 
-       if ((f = (struct rsvp_filter*)*arg) != NULL) {
+       f = (struct rsvp_filter *)*arg;
+       if (f) {
                /* Node exists: adjust only classid */
 
                if (f->handle != handle && handle)
                        goto errout2;
-               if (tb[TCA_RSVP_CLASSID-1]) {
-                       f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);
+               if (tb[TCA_RSVP_CLASSID]) {
+                       f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID]);
                        tcf_bind_filter(tp, &f->res, base);
                }
 
@@ -442,42 +462,28 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
        err = -EINVAL;
        if (handle)
                goto errout2;
-       if (tb[TCA_RSVP_DST-1] == NULL)
+       if (tb[TCA_RSVP_DST] == NULL)
                goto errout2;
 
        err = -ENOBUFS;
-       f = kmalloc(sizeof(struct rsvp_filter), GFP_KERNEL);
+       f = kzalloc(sizeof(struct rsvp_filter), GFP_KERNEL);
        if (f == NULL)
                goto errout2;
 
-       memset(f, 0, sizeof(*f));
        h2 = 16;
-       if (tb[TCA_RSVP_SRC-1]) {
-               err = -EINVAL;
-               if (RTA_PAYLOAD(tb[TCA_RSVP_SRC-1]) != sizeof(f->src))
-                       goto errout;
-               memcpy(f->src, RTA_DATA(tb[TCA_RSVP_SRC-1]), sizeof(f->src));
+       if (tb[TCA_RSVP_SRC]) {
+               memcpy(f->src, nla_data(tb[TCA_RSVP_SRC]), sizeof(f->src));
                h2 = hash_src(f->src);
        }
-       if (tb[TCA_RSVP_PINFO-1]) {
-               err = -EINVAL;
-               if (RTA_PAYLOAD(tb[TCA_RSVP_PINFO-1]) < sizeof(struct tc_rsvp_pinfo))
-                       goto errout;
-               pinfo = RTA_DATA(tb[TCA_RSVP_PINFO-1]);
+       if (tb[TCA_RSVP_PINFO]) {
+               pinfo = nla_data(tb[TCA_RSVP_PINFO]);
                f->spi = pinfo->spi;
                f->tunnelhdr = pinfo->tunnelhdr;
        }
-       if (tb[TCA_RSVP_CLASSID-1]) {
-               err = -EINVAL;
-               if (RTA_PAYLOAD(tb[TCA_RSVP_CLASSID-1]) != 4)
-                       goto errout;
-               f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);
-       }
+       if (tb[TCA_RSVP_CLASSID])
+               f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID]);
 
-       err = -EINVAL;
-       if (RTA_PAYLOAD(tb[TCA_RSVP_DST-1]) != sizeof(f->src))
-               goto errout;
-       dst = RTA_DATA(tb[TCA_RSVP_DST-1]);
+       dst = nla_data(tb[TCA_RSVP_DST]);
        h1 = hash_dst(dst, pinfo ? pinfo->protocol : 0, pinfo ? pinfo->tunnelid : 0);
 
        err = -ENOMEM;
@@ -495,16 +501,16 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
                        goto errout;
        }
 
-       for (sp = &data->ht[h1]; (s=*sp) != NULL; sp = &s->next) {
+       for (sp = &data->ht[h1]; (s = *sp) != NULL; sp = &s->next) {
                if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] &&
                    pinfo && pinfo->protocol == s->protocol &&
-                   memcmp(&pinfo->dpi, &s->dpi, sizeof(s->dpi)) == 0
+                   memcmp(&pinfo->dpi, &s->dpi, sizeof(s->dpi)) == 0 &&
 #if RSVP_DST_LEN == 4
-                   && dst[0] == s->dst[0]
-                   && dst[1] == s->dst[1]
-                   && dst[2] == s->dst[2]
+                   dst[0] == s->dst[0] &&
+                   dst[1] == s->dst[1] &&
+                   dst[2] == s->dst[2] &&
 #endif
-                   && pinfo->tunnelid == s->tunnelid) {
+                   pinfo->tunnelid == s->tunnelid) {
 
 insert:
                        /* OK, we found appropriate session */
@@ -518,7 +524,7 @@ insert:
                        tcf_exts_change(tp, &f->exts, &e);
 
                        for (fp = &s->ht[h2]; *fp; fp = &(*fp)->next)
-                               if (((*fp)->spi.mask&f->spi.mask) != f->spi.mask)
+                               if (((*fp)->spi.mask & f->spi.mask) != f->spi.mask)
                                        break;
                        f->next = *fp;
                        wmb();
@@ -532,10 +538,9 @@ insert:
        /* No session found. Create new one. */
 
        err = -ENOBUFS;
-       s = kmalloc(sizeof(struct rsvp_session), GFP_KERNEL);
+       s = kzalloc(sizeof(struct rsvp_session), GFP_KERNEL);
        if (s == NULL)
                goto errout;
-       memset(s, 0, sizeof(*s));
        memcpy(s->dst, dst, sizeof(s->dst));
 
        if (pinfo) {
@@ -550,7 +555,7 @@ insert:
        s->next = *sp;
        wmb();
        *sp = s;
-       
+
        goto insert;
 
 errout:
@@ -563,7 +568,7 @@ errout2:
 static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 {
        struct rsvp_head *head = tp->root;
-       unsigned h, h1;
+       unsigned int h, h1;
 
        if (arg->stop)
                return;
@@ -594,10 +599,10 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
                     struct sk_buff *skb, struct tcmsg *t)
 {
-       struct rsvp_filter *f = (struct rsvp_filter*)fh;
+       struct rsvp_filter *f = (struct rsvp_filter *)fh;
        struct rsvp_session *s;
-       unsigned char    *b = skb->tail;
-       struct rtattr *rta;
+       unsigned char *b = skb_tail_pointer(skb);
+       struct nlattr *nest;
        struct tc_rsvp_pinfo pinfo;
 
        if (f == NULL)
@@ -606,39 +611,38 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
 
        t->tcm_handle = f->handle;
 
+       nest = nla_nest_start(skb, TCA_OPTIONS);
+       if (nest == NULL)
+               goto nla_put_failure;
 
-       rta = (struct rtattr*)b;
-       RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
-
-       RTA_PUT(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst);
+       NLA_PUT(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst);
        pinfo.dpi = s->dpi;
        pinfo.spi = f->spi;
        pinfo.protocol = s->protocol;
        pinfo.tunnelid = s->tunnelid;
        pinfo.tunnelhdr = f->tunnelhdr;
        pinfo.pad = 0;
-       RTA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo);
+       NLA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo);
        if (f->res.classid)
-               RTA_PUT(skb, TCA_RSVP_CLASSID, 4, &f->res.classid);
-       if (((f->handle>>8)&0xFF) != 16)
-               RTA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src);
+               NLA_PUT_U32(skb, TCA_RSVP_CLASSID, f->res.classid);
+       if (((f->handle >> 8) & 0xFF) != 16)
+               NLA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src);
 
        if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0)
-               goto rtattr_failure;
+               goto nla_put_failure;
 
-       rta->rta_len = skb->tail - b;
+       nla_nest_end(skb, nest);
 
        if (tcf_exts_dump_stats(skb, &f->exts, &rsvp_ext_map) < 0)
-               goto rtattr_failure;
+               goto nla_put_failure;
        return skb->len;
 
-rtattr_failure:
-       skb_trim(skb, b - skb->data);
+nla_put_failure:
+       nlmsg_trim(skb, b);
        return -1;
 }
 
-static struct tcf_proto_ops RSVP_OPS = {
-       .next           =       NULL,
+static struct tcf_proto_ops RSVP_OPS __read_mostly = {
        .kind           =       RSVP_ID,
        .classify       =       rsvp_classify,
        .init           =       rsvp_init,
@@ -657,7 +661,7 @@ static int __init init_rsvp(void)
        return register_tcf_proto_ops(&RSVP_OPS);
 }
 
-static void __exit exit_rsvp(void) 
+static void __exit exit_rsvp(void)
 {
        unregister_tcf_proto_ops(&RSVP_OPS);
 }