144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/sch/tbf.c TBF Qdisc 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup qdisc_api 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup tbf Token Bucket Filter (TBF) 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-tc.h> 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/cache.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/tc.h> 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/qdisc.h> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/qdisc-modules.h> 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/class.h> 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/class-modules.h> 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/link.h> 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/sch/tbf.h> 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define TBF_ATTR_LIMIT 0x01 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define TBF_ATTR_RATE 0x02 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define TBF_ATTR_PEAKRATE 0x10 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define TBF_ATTR_MPU 0x80 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf 3844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline struct rtnl_tbf *tbf_qdisc(struct rtnl_qdisc *qdisc) 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf return (struct rtnl_tbf *) qdisc->q_subdata; 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf 4344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline struct rtnl_tbf *tbf_alloc(struct rtnl_qdisc *qdisc) 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!qdisc->q_subdata) 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf qdisc->q_subdata = calloc(1, sizeof(struct rtnl_tbf)); 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf return tbf_qdisc(qdisc); 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf 5144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy tbf_policy[TCA_TBF_MAX+1] = { 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_TBF_PARMS] = { .minlen = sizeof(struct tc_tbf_qopt) }, 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf 5544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int tbf_msg_parser(struct rtnl_qdisc *q) 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[TCA_TBF_MAX + 1]; 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf err = tca_parse(tb, TCA_TBF_MAX, (struct rtnl_tca *) q, tbf_policy); 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf 65241b2b83ba5672f5c86154d29eeb8ef4c7c6e9b4Tad Kollar tbf = tbf_alloc(q); 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 678a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_TBF_PARMS]) { 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_tbf_qopt opts; 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf int bufsize; 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_memcpy(&opts, tb[TCA_TBF_PARMS], sizeof(opts)); 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_limit = opts.limit; 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mpu = opts.rate.mpu; 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_copy_ratespec(&tbf->qt_rate, &opts.rate); 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_rate_txtime = opts.buffer; 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer), 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf opts.rate.rate); 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_rate_bucket = bufsize; 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_copy_ratespec(&tbf->qt_peakrate, &opts.peakrate); 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate_txtime = opts.mtu; 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.mtu), 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf opts.peakrate.rate); 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate_bucket = bufsize; 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mask = (TBF_ATTR_LIMIT | TBF_ATTR_MPU | TBF_ATTR_RATE | 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf TBF_ATTR_PEAKRATE); 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf 9686b6f6f6291eaaec542a2f4028087fa823122082Denys Fedorysychenkostatic void tbf_free_data(struct rtnl_qdisc *qdisc) 9786b6f6f6291eaaec542a2f4028087fa823122082Denys Fedorysychenko{ 9886b6f6f6291eaaec542a2f4028087fa823122082Denys Fedorysychenko free(qdisc->q_subdata); 9986b6f6f6291eaaec542a2f4028087fa823122082Denys Fedorysychenko} 10086b6f6f6291eaaec542a2f4028087fa823122082Denys Fedorysychenko 101d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void tbf_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p) 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf double r, rbit, lim; 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf char *ru, *rubit, *limu; 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf = tbf_qdisc(qdisc); 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 108d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf return; 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf r = nl_cancel_down_bytes(tbf->qt_rate.rs_rate, &ru); 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf rbit = nl_cancel_down_bits(tbf->qt_rate.rs_rate*8, &rubit); 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf lim = nl_cancel_down_bytes(tbf->qt_limit, &limu); 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf 114d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " rate %.2f%s/s (%.0f%s) limit %.2f%s", 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf r, ru, rbit, rubit, lim, limu); 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf 118d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void tbf_dump_details(struct rtnl_qdisc *qdisc, struct nl_dump_params *p) 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf = tbf_qdisc(qdisc); 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 123d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf return; 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (1) { 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf char *bu, *cu; 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf double bs = nl_cancel_down_bytes(tbf->qt_rate_bucket, &bu); 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf double cl = nl_cancel_down_bytes(1 << tbf->qt_rate.rs_cell_log, 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf &cu); 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf 131d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "mpu %u rate-bucket-size %1.f%s " 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf "rate-cell-size %.1f%s\n", 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mpu, bs, bu, cl, cu); 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf char *pru, *prbu, *bsu, *clu; 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf double pr, prb, bs, cl; 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf pr = nl_cancel_down_bytes(tbf->qt_peakrate.rs_rate, &pru); 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf prb = nl_cancel_down_bits(tbf->qt_peakrate.rs_rate * 8, &prbu); 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf bs = nl_cancel_down_bits(tbf->qt_peakrate_bucket, &bsu); 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf cl = nl_cancel_down_bits(1 << tbf->qt_peakrate.rs_cell_log, 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf &clu); 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf 147d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " peak-rate %.2f%s/s (%.0f%s) " 14852510e7d394a1c8ee0a3aaf046db6199f0558c78Denys Fedoryschenko "bucket-size %.1f%s cell-size %.1f%s" 149d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf "latency %.1f%s", 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf pr, pru, prb, prbu, bs, bsu, cl, clu); 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf 15444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_msg *tbf_get_opts(struct rtnl_qdisc *qdisc) 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_tbf_qopt opts; 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t rtab[RTNL_TC_RTABLE_SIZE]; 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t ptab[RTNL_TC_RTABLE_SIZE]; 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf int required = TBF_ATTR_RATE | TBF_ATTR_LIMIT; 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf memset(&opts, 0, sizeof(opts)); 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(tbf->qt_mask & required) != required) 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf opts.limit = tbf->qt_limit; 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf opts.buffer = tbf->qt_rate_txtime; 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_rate.rs_mpu = tbf->qt_mpu; 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_rcopy_ratespec(&opts.rate, &tbf->qt_rate); 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_tc_build_rate_table(rtab, tbf->qt_mpu & 0xff, tbf->qt_mpu >> 8, 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf 1 << tbf->qt_rate.rs_cell_log, 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_rate.rs_rate); 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf opts.mtu = tbf->qt_peakrate_txtime; 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate.rs_mpu = tbf->qt_mpu; 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_rcopy_ratespec(&opts.peakrate, &tbf->qt_peakrate); 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_tc_build_rate_table(ptab, tbf->qt_mpu & 0xff, 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mpu >> 8, 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf 1 << tbf->qt_peakrate.rs_cell_log, 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate.rs_rate); 19044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf msg = nlmsg_alloc(); 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!msg) 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf goto nla_put_failure; 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT(msg, TCA_TBF_PARMS, sizeof(opts), &opts); 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT(msg, TCA_TBF_RTAB, sizeof(rtab), rtab); 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf->qt_mask & TBF_ATTR_PEAKRATE) 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT(msg, TCA_TBF_PTAB, sizeof(ptab), ptab); 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf return msg; 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf 20444d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure: 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(msg); 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attribute Access 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set limit of TBF qdisc. 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc to be modified. 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg limit New limit in bytes. 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 22044d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *qdisc, int limit) 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_alloc(qdisc); 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 2268a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_limit = limit; 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mask |= TBF_ATTR_LIMIT; 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf 23444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline double calc_limit(struct rtnl_ratespec *spec, int latency, 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf int bucket) 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf double limit; 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf limit = (double) spec->rs_rate * ((double) latency / 1000000.); 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf limit += bucket; 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf return limit; 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set limit of TBF qdisc by latency. 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc to be modified. 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg latency Latency in micro seconds. 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Calculates and sets the limit based on the desired latency and the 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf * configured rate and peak rate. In order for this operation to succeed, 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf * the rate and if required the peak rate must have been set in advance. 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @f[ 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf * limit_n = \frac{{rate_n} \times {latency}}{10^6}+{bucketsize}_n 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @f] 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @f[ 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf * limit = min(limit_{rate},limit_{peak}) 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @f] 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 26344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_set_limit_by_latency(struct rtnl_qdisc *qdisc, int latency) 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf double limit, limit2; 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_alloc(qdisc); 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 2708a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(tbf->qt_mask & TBF_ATTR_RATE)) 2738a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MISSING_ATTR; 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf 27544d362409d5469aed47d19e7908d19bd194493aThomas Graf limit = calc_limit(&tbf->qt_rate, latency, tbf->qt_rate_bucket); 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf limit2 = calc_limit(&tbf->qt_peakrate, latency, 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate_bucket); 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (limit2 < limit) 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf limit = limit2; 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf 28544d362409d5469aed47d19e7908d19bd194493aThomas Graf return rtnl_qdisc_tbf_set_limit(qdisc, (int) limit); 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get limit of TBF qdisc. 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc. 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Limit in bytes or a negative error code. 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 29344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_get_limit(struct rtnl_qdisc *qdisc) 29444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf 29744d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf && (tbf->qt_mask & TBF_ATTR_LIMIT)) 29944d362409d5469aed47d19e7908d19bd194493aThomas Graf return tbf->qt_limit; 3008a3efffa5b3fde252675239914118664d36a2c24Thomas Graf else 3018a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOATTR; 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set MPU of TBF qdisc. 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc to be modified. 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg mpu New MPU in bytes. 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 31044d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_set_mpu(struct rtnl_qdisc *qdisc, int mpu) 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_alloc(qdisc); 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 3168a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mpu = mpu; 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mask |= TBF_ATTR_MPU; 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf 32144d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 32244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf 32444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 32544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get MPU of TBF qdisc. 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc. 32744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return MPU in bytes or a negative error code. 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 32944d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_get_mpu(struct rtnl_qdisc *qdisc) 33044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 33144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 33244d362409d5469aed47d19e7908d19bd194493aThomas Graf 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 33444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf && (tbf->qt_mask & TBF_ATTR_MPU)) 33544d362409d5469aed47d19e7908d19bd194493aThomas Graf return tbf->qt_mpu; 3368a3efffa5b3fde252675239914118664d36a2c24Thomas Graf else 3378a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOATTR; 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 33944d362409d5469aed47d19e7908d19bd194493aThomas Graf 34044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int calc_cell_log(int cell, int bucket) 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 34244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cell > 0) 34344d362409d5469aed47d19e7908d19bd194493aThomas Graf cell = rtnl_tc_calc_cell_log(cell); 34444d362409d5469aed47d19e7908d19bd194493aThomas Graf else { 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf cell = 0; 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!bucket) 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf bucket = 2047; /* defaults to cell_log=3 */ 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf 35044d362409d5469aed47d19e7908d19bd194493aThomas Graf while ((bucket >> cell) > 255) 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf cell++; 35244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf return cell; 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf 35744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set rate of TBF qdisc. 35944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc to be modified. 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rate New rate in bytes per second. 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg bucket Size of bucket in bytes. 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cell Size of a rate cell or 0 to get default value. 36344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 36444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 36544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket, 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf int cell) 36744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf int cell_log; 37044d362409d5469aed47d19e7908d19bd194493aThomas Graf 37144d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_alloc(qdisc); 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 3738a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf 37544d362409d5469aed47d19e7908d19bd194493aThomas Graf cell_log = calc_cell_log(cell, bucket); 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cell_log < 0) 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf return cell_log; 37844d362409d5469aed47d19e7908d19bd194493aThomas Graf 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_rate.rs_rate = rate; 38044d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_rate_bucket = bucket; 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_rate.rs_cell_log = cell_log; 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_rate_txtime = rtnl_tc_calc_txtime(bucket, rate); 38344d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mask |= TBF_ATTR_RATE; 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf 38544d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 38644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 38744d362409d5469aed47d19e7908d19bd194493aThomas Graf 38844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 38944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get rate of TBF qdisc. 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc. 39144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Rate in bytes per seconds or a negative error code. 39244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 39344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *qdisc) 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 39544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 39644d362409d5469aed47d19e7908d19bd194493aThomas Graf 39744d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 39844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf && (tbf->qt_mask & TBF_ATTR_RATE)) 39944d362409d5469aed47d19e7908d19bd194493aThomas Graf return tbf->qt_rate.rs_rate; 40044d362409d5469aed47d19e7908d19bd194493aThomas Graf else 40144d362409d5469aed47d19e7908d19bd194493aThomas Graf return -1; 40244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 40344d362409d5469aed47d19e7908d19bd194493aThomas Graf 40444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 40544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get rate bucket size of TBF qdisc. 40644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc. 40744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Size of rate bucket or a negative error code. 40844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 40944d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_get_rate_bucket(struct rtnl_qdisc *qdisc) 41044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 41144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 41244d362409d5469aed47d19e7908d19bd194493aThomas Graf 41344d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 41444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf && (tbf->qt_mask & TBF_ATTR_RATE)) 41544d362409d5469aed47d19e7908d19bd194493aThomas Graf return tbf->qt_rate_bucket; 41644d362409d5469aed47d19e7908d19bd194493aThomas Graf else 41744d362409d5469aed47d19e7908d19bd194493aThomas Graf return -1; 41844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 41944d362409d5469aed47d19e7908d19bd194493aThomas Graf 42044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 42144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get rate cell size of TBF qdisc. 42244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc. 42344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Size of rate cell in bytes or a negative error code. 42444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 42544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_get_rate_cell(struct rtnl_qdisc *qdisc) 42644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 42744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 42844d362409d5469aed47d19e7908d19bd194493aThomas Graf 42944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 43044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf && (tbf->qt_mask & TBF_ATTR_RATE)) 43144d362409d5469aed47d19e7908d19bd194493aThomas Graf return (1 << tbf->qt_rate.rs_cell_log); 43244d362409d5469aed47d19e7908d19bd194493aThomas Graf else 43344d362409d5469aed47d19e7908d19bd194493aThomas Graf return -1; 43444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 43544d362409d5469aed47d19e7908d19bd194493aThomas Graf 43644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 43744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set peak rate of TBF qdisc. 43844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc to be modified. 43944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rate New peak rate in bytes per second. 44044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg bucket Size of peakrate bucket. 44144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cell Size of a peakrate cell or 0 to get default value. 44244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 44344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 44444d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket, 44544d362409d5469aed47d19e7908d19bd194493aThomas Graf int cell) 44644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 44744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 44844d362409d5469aed47d19e7908d19bd194493aThomas Graf int cell_log; 44944d362409d5469aed47d19e7908d19bd194493aThomas Graf 45044d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_alloc(qdisc); 45144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tbf) 4528a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 45344d362409d5469aed47d19e7908d19bd194493aThomas Graf 45444d362409d5469aed47d19e7908d19bd194493aThomas Graf cell_log = calc_cell_log(cell, bucket); 45544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cell_log < 0) 45644d362409d5469aed47d19e7908d19bd194493aThomas Graf return cell_log; 45744d362409d5469aed47d19e7908d19bd194493aThomas Graf 45844d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate.rs_rate = rate; 45944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate_bucket = bucket; 46044d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate.rs_cell_log = cell_log; 46144d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_peakrate_txtime = rtnl_tc_calc_txtime(bucket, rate); 46244d362409d5469aed47d19e7908d19bd194493aThomas Graf 46344d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf->qt_mask |= TBF_ATTR_PEAKRATE; 46444d362409d5469aed47d19e7908d19bd194493aThomas Graf 46544d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 46644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 46744d362409d5469aed47d19e7908d19bd194493aThomas Graf 46844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 46944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get peak rate of TBF qdisc. 47044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc. 47144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Peak rate in bytes per seconds or a negative error code. 47244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 47344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_get_peakrate(struct rtnl_qdisc *qdisc) 47444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 47544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 47644d362409d5469aed47d19e7908d19bd194493aThomas Graf 47744d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 47844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf && (tbf->qt_mask & TBF_ATTR_PEAKRATE)) 47944d362409d5469aed47d19e7908d19bd194493aThomas Graf return tbf->qt_peakrate.rs_rate; 48044d362409d5469aed47d19e7908d19bd194493aThomas Graf else 48144d362409d5469aed47d19e7908d19bd194493aThomas Graf return -1; 48244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 48344d362409d5469aed47d19e7908d19bd194493aThomas Graf 48444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 48544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get peak rate bucket size of TBF qdisc. 48644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc. 48744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Size of peak rate bucket or a negative error code. 48844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 48944d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_get_peakrate_bucket(struct rtnl_qdisc *qdisc) 49044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 49144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 49244d362409d5469aed47d19e7908d19bd194493aThomas Graf 49344d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 49444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf && (tbf->qt_mask & TBF_ATTR_PEAKRATE)) 49544d362409d5469aed47d19e7908d19bd194493aThomas Graf return tbf->qt_peakrate_bucket; 49644d362409d5469aed47d19e7908d19bd194493aThomas Graf else 49744d362409d5469aed47d19e7908d19bd194493aThomas Graf return -1; 49844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 49944d362409d5469aed47d19e7908d19bd194493aThomas Graf 50044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 50144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get peak rate cell size of TBF qdisc. 50244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg qdisc TBF qdisc. 50344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Size of peak rate cell in bytes or a negative error code. 50444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 50544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_qdisc_tbf_get_peakrate_cell(struct rtnl_qdisc *qdisc) 50644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 50744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tbf *tbf; 50844d362409d5469aed47d19e7908d19bd194493aThomas Graf 50944d362409d5469aed47d19e7908d19bd194493aThomas Graf tbf = tbf_qdisc(qdisc); 51044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbf && (tbf->qt_mask & TBF_ATTR_PEAKRATE)) 51144d362409d5469aed47d19e7908d19bd194493aThomas Graf return (1 << tbf->qt_peakrate.rs_cell_log); 51244d362409d5469aed47d19e7908d19bd194493aThomas Graf else 51344d362409d5469aed47d19e7908d19bd194493aThomas Graf return -1; 51444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 51544d362409d5469aed47d19e7908d19bd194493aThomas Graf 51644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 51744d362409d5469aed47d19e7908d19bd194493aThomas Graf 51844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct rtnl_qdisc_ops tbf_qdisc_ops = { 51944d362409d5469aed47d19e7908d19bd194493aThomas Graf .qo_kind = "tbf", 52044d362409d5469aed47d19e7908d19bd194493aThomas Graf .qo_msg_parser = tbf_msg_parser, 521d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf .qo_dump = { 522d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_LINE] = tbf_dump_line, 523d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_DETAILS] = tbf_dump_details, 524d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf }, 52586b6f6f6291eaaec542a2f4028087fa823122082Denys Fedorysychenko .qo_free_data = tbf_free_data, 52644d362409d5469aed47d19e7908d19bd194493aThomas Graf .qo_get_opts = tbf_get_opts, 52744d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 52844d362409d5469aed47d19e7908d19bd194493aThomas Graf 52944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init tbf_init(void) 53044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 53144d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_qdisc_register(&tbf_qdisc_ops); 53244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 53344d362409d5469aed47d19e7908d19bd194493aThomas Graf 53444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit tbf_exit(void) 53544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 53644d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_qdisc_unregister(&tbf_qdisc_ops); 53744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 53844d362409d5469aed47d19e7908d19bd194493aThomas Graf 53944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 540