X-Git-Url: http://git.onelab.eu/?p=libnl.git;a=blobdiff_plain;f=lib%2Froute%2Fsch%2Fhtb.c;fp=lib%2Froute%2Fsch%2Fhtb.c;h=0000000000000000000000000000000000000000;hp=df641bc78c1edf26bae4c193715ff4892f1b31fb;hb=332c8b7561dcac7ac95cc0d07328b1cb22d780a6;hpb=eabdd897b75ecc1fac5e255229a899126085e57a diff --git a/lib/route/sch/htb.c b/lib/route/sch/htb.c deleted file mode 100644 index df641bc..0000000 --- a/lib/route/sch/htb.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * lib/route/sch/htb.c HTB Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2006 Thomas Graf - * Copyright (c) 2005-2006 Petr Gotthard - * Copyright (c) 2005-2006 Siemens AG Oesterreich - */ - -/** - * @ingroup qdisc - * @ingroup class - * @defgroup htb Hierachical Token Bucket (HTB) - * @{ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** @cond SKIP */ -#define SCH_HTB_HAS_RATE2QUANTUM 0x01 -#define SCH_HTB_HAS_DEFCLS 0x02 - -#define SCH_HTB_HAS_PRIO 0x01 -#define SCH_HTB_HAS_MTU 0x02 -#define SCH_HTB_HAS_RATE 0x04 -#define SCH_HTB_HAS_CEIL 0x08 -#define SCH_HTB_HAS_RBUFFER 0x10 -#define SCH_HTB_HAS_CBUFFER 0x20 -/** @endcond */ - -static inline struct rtnl_htb_qdisc *htb_qdisc(struct rtnl_qdisc *qdisc) -{ - if (qdisc->q_subdata == NULL) - qdisc->q_subdata = calloc(1, sizeof(struct rtnl_htb_qdisc)); - - return (struct rtnl_htb_qdisc *) qdisc->q_subdata; -} - -static struct nla_policy htb_policy[TCA_HTB_MAX+1] = { - [TCA_HTB_INIT] = { .minlen = sizeof(struct tc_htb_glob) }, - [TCA_HTB_PARMS] = { .minlen = sizeof(struct tc_htb_opt) }, -}; - -static int htb_qdisc_msg_parser(struct rtnl_qdisc *qdisc) -{ - int err; - struct nlattr *tb[TCA_HTB_MAX + 1]; - struct rtnl_htb_qdisc *d; - - err = tca_parse(tb, TCA_HTB_MAX, (struct rtnl_tca *) qdisc, htb_policy); - if (err < 0) - return err; - - d = htb_qdisc(qdisc); - - if (tb[TCA_HTB_INIT]) { - struct tc_htb_glob opts; - - nla_memcpy(&opts, tb[TCA_HTB_INIT], sizeof(opts)); - d->qh_rate2quantum = opts.rate2quantum; - d->qh_defcls = opts.defcls; - - d->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS); - } - - return 0; -} - -static void htb_qdisc_free_data(struct rtnl_qdisc *qdisc) -{ - free(qdisc->q_subdata); -} - -static inline struct rtnl_htb_class *htb_class(struct rtnl_class *class) -{ - if (class->c_subdata == NULL) - class->c_subdata = calloc(1, sizeof(struct rtnl_htb_class)); - - return (struct rtnl_htb_class *) class->c_subdata; -} - -static int htb_class_msg_parser(struct rtnl_class *class) -{ - int err; - struct nlattr *tb[TCA_HTB_MAX + 1]; - struct rtnl_htb_class *d; - - err = tca_parse(tb, TCA_HTB_MAX, (struct rtnl_tca *) class, htb_policy); - if (err < 0) - return err; - - d = htb_class(class); - - if (tb[TCA_HTB_PARMS]) { - struct tc_htb_opt opts; - - nla_memcpy(&opts, tb[TCA_HTB_PARMS], sizeof(opts)); - d->ch_prio = opts.prio; - rtnl_copy_ratespec(&d->ch_rate, &opts.rate); - rtnl_copy_ratespec(&d->ch_ceil, &opts.ceil); - d->ch_rbuffer = opts.buffer; - d->ch_cbuffer = opts.cbuffer; - - d->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE | - SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER | - SCH_HTB_HAS_CBUFFER); - } - - return 0; -} - -static void htb_class_free_data(struct rtnl_class *class) -{ - free(class->c_subdata); -} - -static int htb_qdisc_dump_brief(struct rtnl_qdisc *qdisc, - struct nl_dump_params *p, int line) -{ - struct rtnl_htb_qdisc *d = (struct rtnl_htb_qdisc *) qdisc->q_subdata; - - if (d == NULL) - goto ignore; - - if (d->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) - dp_dump(p, " r2q %u", d->qh_rate2quantum); - - if (d->qh_mask & SCH_HTB_HAS_DEFCLS) { - char buf[32]; - dp_dump(p, " default %s", - rtnl_tc_handle2str(d->qh_defcls, buf, sizeof(buf))); - } - -ignore: - return line; -} - -static int htb_class_dump_brief(struct rtnl_class *class, - struct nl_dump_params *p, int line) -{ - struct rtnl_htb_class *d = (struct rtnl_htb_class *) class->c_subdata; - - if (d == NULL) - goto ignore; - - if (d->ch_mask & SCH_HTB_HAS_RATE) { - double r, rbit; - char *ru, *rubit; - - r = nl_cancel_down_bytes(d->ch_rate.rs_rate, &ru); - rbit = nl_cancel_down_bits(d->ch_rate.rs_rate*8, &rubit); - - dp_dump(p, " rate %.2f%s/s (%.0f%s) log %u", - r, ru, rbit, rubit, 1<ch_rate.rs_cell_log); - } - -ignore: - return line; -} - -static int htb_class_dump_full(struct rtnl_class *class, - struct nl_dump_params *p, int line) -{ - struct rtnl_htb_class *d = (struct rtnl_htb_class *) class->c_subdata; - - if (d == NULL) - goto ignore; - - /* line 1 */ - if (d->ch_mask & SCH_HTB_HAS_CEIL) { - double r, rbit; - char *ru, *rubit; - - r = nl_cancel_down_bytes(d->ch_ceil.rs_rate, &ru); - rbit = nl_cancel_down_bits(d->ch_ceil.rs_rate*8, &rubit); - - dp_dump(p, " ceil %.2f%s/s (%.0f%s) log %u", - r, ru, rbit, rubit, 1<ch_ceil.rs_cell_log); - } - - if (d->ch_mask & SCH_HTB_HAS_PRIO) - dp_dump(p, " prio %u", d->ch_prio); - if (d->ch_mask & SCH_HTB_HAS_RBUFFER) - dp_dump(p, " rbuffer %u", d->ch_rbuffer); - if (d->ch_mask & SCH_HTB_HAS_CBUFFER) - dp_dump(p, " cbuffer %u", d->ch_cbuffer); - -ignore: - return line; -} - -static struct nl_msg *htb_qdisc_get_opts(struct rtnl_qdisc *qdisc) -{ - struct rtnl_htb_qdisc *d = (struct rtnl_htb_qdisc *) qdisc->q_subdata; - struct tc_htb_glob opts; - struct nl_msg *msg; - - if (d == NULL) - return NULL; - - msg = nlmsg_build(NULL); - if (msg == NULL) - return NULL; - - memset(&opts, 0, sizeof(opts)); - opts.version = TC_HTB_PROTOVER; - - if (d->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) - opts.rate2quantum = d->qh_rate2quantum; - if (d->qh_mask & SCH_HTB_HAS_DEFCLS) - opts.defcls = d->qh_defcls; - - nla_put(msg, TCA_HTB_INIT, sizeof(opts), &opts); - - return msg; -} - -static inline uint32_t compute_burst(uint32_t rate, uint32_t mtu) -{ - return rtnl_tc_calc_txtime(rate / nl_get_hz() + mtu, rate); -} - -static uint8_t compute_cell(uint32_t rate, uint32_t mtu) -{ - uint8_t cell_log = 0; - while (mtu > 255) { - mtu >>= 1; - cell_log++; - } - - return cell_log; -} - -static struct nl_msg *htb_class_get_opts(struct rtnl_class *class) -{ - struct rtnl_htb_class *d = (struct rtnl_htb_class *) class->c_subdata; - uint32_t rtable[256], ctable[256]; - struct tc_htb_opt opts; - struct nl_msg *msg; - - - if (d == NULL) - return NULL; - - msg = nlmsg_build(NULL); - memset(&opts, 0, sizeof(opts)); - - /* if not set, zero (0) is used as priority */ - if (d->ch_mask & SCH_HTB_HAS_PRIO) - opts.prio = d->ch_prio; - - if (!(d->ch_mask & SCH_HTB_HAS_RATE)) - BUG(); - - rtnl_rcopy_ratespec(&opts.rate, &d->ch_rate); - /* if cell_log not set, compute default value */ - if (opts.rate.cell_log == UINT8_MAX) - { - if(!(d->ch_mask & SCH_HTB_HAS_MTU)) - BUG(); - opts.rate.cell_log = compute_cell(opts.rate.rate, d->ch_mtu); - } - - /* if not set, configured rate is used as ceil, which implies no borrowing */ - if (d->ch_mask & SCH_HTB_HAS_CEIL) - rtnl_rcopy_ratespec(&opts.ceil, &d->ch_ceil); - else - memcpy(&opts.ceil, &opts.rate, sizeof(struct tc_ratespec)); - /* if cell_log not set, compute default value */ - if (opts.ceil.cell_log == UINT8_MAX) - { - if(!(d->ch_mask & SCH_HTB_HAS_MTU)) - BUG(); - opts.ceil.cell_log = compute_cell(opts.ceil.rate, d->ch_mtu); - } - - if (d->ch_mask & SCH_HTB_HAS_RBUFFER) - opts.buffer = d->ch_rbuffer; - else - { - if(!(d->ch_mask & SCH_HTB_HAS_MTU)) - BUG(); - opts.buffer = compute_burst(opts.rate.rate, d->ch_mtu); - } - - if (d->ch_mask & SCH_HTB_HAS_CBUFFER) - opts.cbuffer = d->ch_cbuffer; - else - { - if(!(d->ch_mask & SCH_HTB_HAS_MTU)) - BUG(); - opts.cbuffer = compute_burst(opts.ceil.rate, d->ch_mtu); - } - - nla_put(msg, TCA_HTB_PARMS, sizeof(opts), &opts); - rtnl_tc_build_rate_table(rtable, opts.rate.mpu & 0xff, - opts.rate.mpu >> 8, 1 << opts.rate.cell_log, - opts.rate.rate); - nla_put(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable); - rtnl_tc_build_rate_table(ctable, opts.ceil.mpu & 0xff, - opts.ceil.mpu >> 8, 1 << opts.ceil.cell_log, - opts.ceil.rate); - nla_put(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable); - - return msg; -} - -/** - * @name Attribute Modifications - * @{ - */ - -void rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum) -{ - struct rtnl_htb_qdisc *d = htb_qdisc(qdisc); - if (d == NULL) - return; - - d->qh_rate2quantum = rate2quantum; - d->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM; -} - -/** - * Set default class of the htb qdisc to the specified value - * @arg qdisc qdisc to change - * @arg defcls new default class - */ -void rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls) -{ - struct rtnl_htb_qdisc *d = htb_qdisc(qdisc); - if (d == NULL) - return; - - d->qh_defcls = defcls; - d->qh_mask |= SCH_HTB_HAS_DEFCLS; -} - -void rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio) -{ - struct rtnl_htb_class *d = htb_class(class); - if (d == NULL) - return; - - d->ch_prio = prio; - d->ch_mask |= SCH_HTB_HAS_PRIO; -} - -void rtnl_htb_set_mtu(struct rtnl_class *class, uint32_t mtu) -{ - struct rtnl_htb_class *d = htb_class(class); - if (d == NULL) - return; - - d->ch_mtu = mtu; - d->ch_mask |= SCH_HTB_HAS_MTU; -} - -void rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) -{ - struct rtnl_htb_class *d = htb_class(class); - if (d == NULL) - return; - - d->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */ - d->ch_rate.rs_rate = rate; - d->ch_mask |= SCH_HTB_HAS_RATE; -} - -void rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil) -{ - struct rtnl_htb_class *d = htb_class(class); - if (d == NULL) - return; - - d->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */ - d->ch_ceil.rs_rate = ceil; - d->ch_mask |= SCH_HTB_HAS_CEIL; -} - -/** @} */ - -static struct rtnl_qdisc_ops htb_qdisc_ops = { - .qo_kind = "htb", - .qo_msg_parser = htb_qdisc_msg_parser, - .qo_free_data = htb_qdisc_free_data, - .qo_dump[NL_DUMP_BRIEF] = htb_qdisc_dump_brief, - .qo_get_opts = htb_qdisc_get_opts, -}; - -static struct rtnl_class_ops htb_class_ops = { - .co_kind = "htb", - .co_msg_parser = htb_class_msg_parser, - .co_free_data = htb_class_free_data, - .co_dump[NL_DUMP_BRIEF] = htb_class_dump_brief, - .co_dump[NL_DUMP_FULL] = htb_class_dump_full, - .co_get_opts = htb_class_get_opts, -}; - -static void __init htb_init(void) -{ - rtnl_qdisc_register(&htb_qdisc_ops); - rtnl_class_register(&htb_class_ops); -} - -static void __exit htb_exit(void) -{ - rtnl_qdisc_unregister(&htb_qdisc_ops); - rtnl_class_unregister(&htb_class_ops); -} - -/** @} */