X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fsched%2Fsch_tbf.c;h=b296672f76326c9f07a7cbaf1d3343f41e4ceafa;hb=4836e3007882984279ca63d3c42bf0b14616eb78;hp=85da8daa61d20a7c6130577c03c182d2d42ef213;hpb=7baca6ad0ef09c8a78d798c93a3ce25336e8f50f;p=linux-2.6 diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 85da8daa61..b296672f76 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -13,28 +13,12 @@ */ #include -#include -#include -#include #include #include -#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include #include @@ -127,21 +111,21 @@ struct tbf_sched_data long tokens; /* Current number of B tokens */ long ptokens; /* Current number of P tokens */ psched_time_t t_c; /* Time check-point */ - struct timer_list wd_timer; /* Watchdog timer */ struct Qdisc *qdisc; /* Inner qdisc, default - bfifo queue */ + struct qdisc_watchdog watchdog; /* Watchdog timer */ }; -#define L2T(q,L) ((q)->R_tab->data[(L)>>(q)->R_tab->rate.cell_log]) -#define L2T_P(q,L) ((q)->P_tab->data[(L)>>(q)->P_tab->rate.cell_log]) +#define L2T(q,L) qdisc_l2t((q)->R_tab,L) +#define L2T_P(q,L) qdisc_l2t((q)->P_tab,L) static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct tbf_sched_data *q = qdisc_priv(sch); int ret; - if (skb->len > q->max_size) { + if (qdisc_pkt_len(skb) > q->max_size) { sch->qstats.drops++; -#ifdef CONFIG_NET_CLS_POLICE +#ifdef CONFIG_NET_CLS_ACT if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) #endif kfree_skb(skb); @@ -149,13 +133,14 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) return NET_XMIT_DROP; } - if ((ret = q->qdisc->enqueue(skb, q->qdisc)) != 0) { + ret = qdisc_enqueue(skb, q->qdisc); + if (ret != 0) { sch->qstats.drops++; return ret; } sch->q.qlen++; - sch->bstats.bytes += skb->len; + sch->bstats.bytes += qdisc_pkt_len(skb); sch->bstats.packets++; return 0; } @@ -185,14 +170,6 @@ static unsigned int tbf_drop(struct Qdisc* sch) return len; } -static void tbf_watchdog(unsigned long arg) -{ - struct Qdisc *sch = (struct Qdisc*)arg; - - sch->flags &= ~TCQ_F_THROTTLED; - netif_schedule(sch->dev); -} - static struct sk_buff *tbf_dequeue(struct Qdisc* sch) { struct tbf_sched_data *q = qdisc_priv(sch); @@ -202,13 +179,12 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) if (skb) { psched_time_t now; - long toks, delay; + long toks; long ptoks = 0; - unsigned int len = skb->len; - - PSCHED_GET_TIME(now); + unsigned int len = qdisc_pkt_len(skb); - toks = PSCHED_TDIFF_SAFE(now, q->t_c, q->buffer); + now = psched_get_time(); + toks = psched_tdiff_bounded(now, q->t_c, q->buffer); if (q->P_tab) { ptoks = toks + q->ptokens; @@ -230,12 +206,8 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) return skb; } - delay = PSCHED_US2JIFFIE(max_t(long, -toks, -ptoks)); - - if (delay == 0) - delay = 1; - - mod_timer(&q->wd_timer, jiffies+delay); + qdisc_watchdog_schedule(&q->watchdog, + now + max_t(long, -toks, -ptoks)); /* Maybe we have a shorter packet in the queue, which can be sent now. It sounds cool, @@ -254,7 +226,6 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) sch->qstats.drops++; } - sch->flags |= TCQ_F_THROTTLED; sch->qstats.overlimits++; } return NULL; @@ -266,64 +237,45 @@ static void tbf_reset(struct Qdisc* sch) qdisc_reset(q->qdisc); sch->q.qlen = 0; - PSCHED_GET_TIME(q->t_c); + q->t_c = psched_get_time(); q->tokens = q->buffer; q->ptokens = q->mtu; - sch->flags &= ~TCQ_F_THROTTLED; - del_timer(&q->wd_timer); + qdisc_watchdog_cancel(&q->watchdog); } -static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) -{ - struct Qdisc *q; - struct rtattr *rta; - int ret; - - q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops, - TC_H_MAKE(sch->handle, 1)); - if (q) { - rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); - if (rta) { - rta->rta_type = RTM_NEWQDISC; - rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); - ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit; - - ret = q->ops->change(q, rta); - kfree(rta); - - if (ret == 0) - return q; - } - qdisc_destroy(q); - } - - return NULL; -} +static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = { + [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) }, + [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, + [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, +}; -static int tbf_change(struct Qdisc* sch, struct rtattr *opt) +static int tbf_change(struct Qdisc* sch, struct nlattr *opt) { - int err = -EINVAL; + int err; struct tbf_sched_data *q = qdisc_priv(sch); - struct rtattr *tb[TCA_TBF_PTAB]; + struct nlattr *tb[TCA_TBF_PTAB + 1]; struct tc_tbf_qopt *qopt; struct qdisc_rate_table *rtab = NULL; struct qdisc_rate_table *ptab = NULL; struct Qdisc *child = NULL; int max_size,n; - if (rtattr_parse_nested(tb, TCA_TBF_PTAB, opt) || - tb[TCA_TBF_PARMS-1] == NULL || - RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt)) + err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy); + if (err < 0) + return err; + + err = -EINVAL; + if (tb[TCA_TBF_PARMS] == NULL) goto done; - qopt = RTA_DATA(tb[TCA_TBF_PARMS-1]); - rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB-1]); + qopt = nla_data(tb[TCA_TBF_PARMS]); + rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB]); if (rtab == NULL) goto done; if (qopt->peakrate.rate) { if (qopt->peakrate.rate > qopt->rate.rate) - ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB-1]); + ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]); if (ptab == NULL) goto done; } @@ -343,8 +295,11 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt) goto done; if (qopt->limit > 0) { - if ((child = tbf_create_dflt_qdisc(sch, qopt->limit)) == NULL) + child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); + if (IS_ERR(child)) { + err = PTR_ERR(child); goto done; + } } sch_tree_lock(sch); @@ -370,18 +325,15 @@ done: return err; } -static int tbf_init(struct Qdisc* sch, struct rtattr *opt) +static int tbf_init(struct Qdisc* sch, struct nlattr *opt) { struct tbf_sched_data *q = qdisc_priv(sch); if (opt == NULL) return -EINVAL; - PSCHED_GET_TIME(q->t_c); - init_timer(&q->wd_timer); - q->wd_timer.function = tbf_watchdog; - q->wd_timer.data = (unsigned long)sch; - + q->t_c = psched_get_time(); + qdisc_watchdog_init(&q->watchdog, sch); q->qdisc = &noop_qdisc; return tbf_change(sch, opt); @@ -391,7 +343,7 @@ static void tbf_destroy(struct Qdisc *sch) { struct tbf_sched_data *q = qdisc_priv(sch); - del_timer(&q->wd_timer); + qdisc_watchdog_cancel(&q->watchdog); if (q->P_tab) qdisc_put_rtab(q->P_tab); @@ -404,12 +356,12 @@ static void tbf_destroy(struct Qdisc *sch) static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) { struct tbf_sched_data *q = qdisc_priv(sch); - unsigned char *b = skb->tail; - struct rtattr *rta; + struct nlattr *nest; struct tc_tbf_qopt opt; - rta = (struct rtattr*)b; - RTA_PUT(skb, TCA_OPTIONS, 0, NULL); + nest = nla_nest_start(skb, TCA_OPTIONS); + if (nest == NULL) + goto nla_put_failure; opt.limit = q->limit; opt.rate = q->R_tab->rate; @@ -419,13 +371,13 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) memset(&opt.peakrate, 0, sizeof(opt.peakrate)); opt.mtu = q->mtu; opt.buffer = q->buffer; - RTA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt); - rta->rta_len = skb->tail - b; + NLA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt); + nla_nest_end(skb, nest); return skb->len; -rtattr_failure: - skb_trim(skb, b - skb->data); +nla_put_failure: + nla_nest_cancel(skb, nest); return -1; } @@ -476,7 +428,7 @@ static void tbf_put(struct Qdisc *sch, unsigned long arg) } static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid, - struct rtattr **tca, unsigned long *arg) + struct nlattr **tca, unsigned long *arg) { return -ENOSYS; } @@ -503,7 +455,7 @@ static struct tcf_proto **tbf_find_tcf(struct Qdisc *sch, unsigned long cl) return NULL; } -static struct Qdisc_class_ops tbf_class_ops = +static const struct Qdisc_class_ops tbf_class_ops = { .graft = tbf_graft, .leaf = tbf_leaf, @@ -516,7 +468,7 @@ static struct Qdisc_class_ops tbf_class_ops = .dump = tbf_dump_class, }; -static struct Qdisc_ops tbf_qdisc_ops = { +static struct Qdisc_ops tbf_qdisc_ops __read_mostly = { .next = NULL, .cl_ops = &tbf_class_ops, .id = "tbf",