X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=net%2Fsched%2Fcls_rsvp.h;h=232fb919681076f0f5c6321aad6c2fc6a747ced2;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=f70fad175a6f1b52511c84ee278f068133f821de;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index f70fad175..232fb9196 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h @@ -95,9 +95,7 @@ struct rsvp_filter u8 tunnelhdr; struct tcf_result res; -#ifdef CONFIG_NET_CLS_POLICE - struct tcf_police *police; -#endif + struct tcf_exts exts; u32 handle; struct rsvp_session *sess; @@ -120,18 +118,20 @@ static __inline__ unsigned hash_src(u32 *src) return h & 0xF; } -#ifdef CONFIG_NET_CLS_POLICE -#define RSVP_POLICE() \ -if (f->police) { \ - int pol_res = tcf_police(skb, f->police); \ - if (pol_res < 0) continue; \ - if (pol_res) return pol_res; \ -} -#else -#define RSVP_POLICE() -#endif - +static struct tcf_ext_map rsvp_ext_map = { + .police = TCA_RSVP_POLICE, + .action = TCA_RSVP_ACT +}; +#define RSVP_APPLY_RESULT() \ +{ \ + int r = tcf_exts_exec(skb, &f->exts, res); \ + if (r < 0) \ + continue; \ + else if (r > 0) \ + return r; \ +} + static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res) { @@ -189,8 +189,7 @@ restart: #endif ) { *res = f->res; - - RSVP_POLICE(); + RSVP_APPLY_RESULT(); matched: if (f->tunnelhdr == 0) @@ -205,7 +204,7 @@ matched: /* And wildcard bucket... */ for (f = s->ht[16]; f; f = f->next) { *res = f->res; - RSVP_POLICE(); + RSVP_APPLY_RESULT(); goto matched; } return -1; @@ -251,6 +250,14 @@ static int rsvp_init(struct tcf_proto *tp) return -ENOBUFS; } +static inline void +rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f) +{ + tcf_unbind_filter(tp, &f->res); + tcf_exts_destroy(tp, &f->exts); + kfree(f); +} + static void rsvp_destroy(struct tcf_proto *tp) { struct rsvp_head *data = xchg(&tp->root, NULL); @@ -272,15 +279,8 @@ static void rsvp_destroy(struct tcf_proto *tp) struct rsvp_filter *f; while ((f = s->ht[h2]) != NULL) { - unsigned long cl; - s->ht[h2] = f->next; - if ((cl = __cls_set_class(&f->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); -#ifdef CONFIG_NET_CLS_POLICE - tcf_police_release(f->police,TCA_ACT_UNBIND); -#endif - kfree(f); + rsvp_delete_filter(tp, f); } } kfree(s); @@ -299,21 +299,10 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) for (fp = &s->ht[(h>>8)&0xFF]; *fp; fp = &(*fp)->next) { if (*fp == f) { - unsigned long cl; - - tcf_tree_lock(tp); *fp = f->next; tcf_tree_unlock(tp); - - if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); - -#ifdef CONFIG_NET_CLS_POLICE - tcf_police_release(f->police,TCA_ACT_UNBIND); -#endif - - kfree(f); + rsvp_delete_filter(tp, f); /* Strip tree */ @@ -421,6 +410,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base, struct tc_rsvp_pinfo *pinfo = NULL; struct rtattr *opt = tca[TCA_OPTIONS-1]; struct rtattr *tb[TCA_RSVP_MAX]; + struct tcf_exts e; unsigned h1, h2; u32 *dst; int err; @@ -428,45 +418,38 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base, if (opt == NULL) return handle ? -EINVAL : 0; - if (rtattr_parse(tb, TCA_RSVP_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0) + if (rtattr_parse_nested(tb, TCA_RSVP_MAX, opt) < 0) return -EINVAL; + err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &rsvp_ext_map); + if (err < 0) + return err; + if ((f = (struct rsvp_filter*)*arg) != NULL) { /* Node exists: adjust only classid */ if (f->handle != handle && handle) - return -EINVAL; + goto errout2; if (tb[TCA_RSVP_CLASSID-1]) { - unsigned long cl; - f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]); - cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid)); - if (cl) - tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + tcf_bind_filter(tp, &f->res, base); } -#ifdef CONFIG_NET_CLS_POLICE - if (tb[TCA_RSVP_POLICE-1]) { - struct tcf_police *police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]); - - tcf_tree_lock(tp); - police = xchg(&f->police, police); - tcf_tree_unlock(tp); - tcf_police_release(police,TCA_ACT_UNBIND); - } -#endif + tcf_exts_change(tp, &f->exts, &e); return 0; } /* Now more serious part... */ + err = -EINVAL; if (handle) - return -EINVAL; + goto errout2; if (tb[TCA_RSVP_DST-1] == NULL) - return -EINVAL; + goto errout2; + err = -ENOBUFS; f = kmalloc(sizeof(struct rsvp_filter), GFP_KERNEL); if (f == NULL) - return -ENOBUFS; + goto errout2; memset(f, 0, sizeof(*f)); h2 = 16; @@ -531,11 +514,9 @@ insert: f->sess = s; if (f->tunnelhdr == 0) - cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid)); -#ifdef CONFIG_NET_CLS_POLICE - if (tb[TCA_RSVP_POLICE-1]) - f->police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]); -#endif + tcf_bind_filter(tp, &f->res, base); + + 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) @@ -576,6 +557,8 @@ insert: errout: if (f) kfree(f); +errout2: + tcf_exts_destroy(tp, &e); return err; } @@ -601,7 +584,7 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg) } if (arg->fn(tp, (unsigned long)f, arg) < 0) { arg->stop = 1; - break; + return; } arg->count++; } @@ -640,27 +623,14 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, 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); -#ifdef CONFIG_NET_CLS_POLICE - if (f->police) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; - - RTA_PUT(skb, TCA_RSVP_POLICE, 0, NULL); - - if (tcf_police_dump(skb, f->police) < 0) - goto rtattr_failure; - p_rta->rta_len = skb->tail - (u8*)p_rta; - } -#endif + if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0) + goto rtattr_failure; rta->rta_len = skb->tail - b; -#ifdef CONFIG_NET_CLS_POLICE - if (f->police) { - if (qdisc_copy_stats(skb, &f->police->stats, - f->police->stats_lock)) - goto rtattr_failure; - } -#endif + + if (tcf_exts_dump_stats(skb, &f->exts, &rsvp_ext_map) < 0) + goto rtattr_failure; return skb->len; rtattr_failure: