21 #include <netlink-private/netlink.h> 
   22 #include <netlink-private/tc.h> 
   23 #include <netlink/netlink.h> 
   24 #include <netlink/cache.h> 
   25 #include <netlink/utils.h> 
   26 #include <netlink-private/route/tc-api.h> 
   27 #include <netlink/route/qdisc.h> 
   28 #include <netlink/route/class.h> 
   29 #include <netlink/route/link.h> 
   30 #include <netlink/route/qdisc/htb.h> 
   33 #define SCH_HTB_HAS_RATE2QUANTUM        0x01 
   34 #define SCH_HTB_HAS_DEFCLS              0x02 
   36 #define SCH_HTB_HAS_PRIO                0x001 
   37 #define SCH_HTB_HAS_RATE                0x002 
   38 #define SCH_HTB_HAS_CEIL                0x004 
   39 #define SCH_HTB_HAS_RBUFFER             0x008 
   40 #define SCH_HTB_HAS_CBUFFER             0x010 
   41 #define SCH_HTB_HAS_QUANTUM             0x020 
   42 #define SCH_HTB_HAS_LEVEL               0x040 
   45 static struct nla_policy htb_policy[TCA_HTB_MAX+1] = {
 
   46         [TCA_HTB_INIT]  = { .
minlen = 
sizeof(
struct tc_htb_glob) },
 
   47         [TCA_HTB_PARMS] = { .minlen = 
sizeof(
struct tc_htb_opt) },
 
   50 static int htb_qdisc_msg_parser(
struct rtnl_tc *tc, 
void *data)
 
   52         struct nlattr *tb[TCA_HTB_MAX + 1];
 
   53         struct rtnl_htb_qdisc *htb = data;
 
   56         if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
 
   59         if (tb[TCA_HTB_INIT]) {
 
   60                 struct tc_htb_glob opts;
 
   62                 nla_memcpy(&opts, tb[TCA_HTB_INIT], 
sizeof(opts));
 
   63                 htb->qh_rate2quantum = opts.rate2quantum;
 
   64                 htb->qh_defcls = opts.defcls;
 
   65                 htb->qh_direct_pkts = opts.direct_pkts;
 
   67                 htb->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS);
 
   73 static int htb_class_msg_parser(
struct rtnl_tc *tc, 
void *data)
 
   75         struct nlattr *tb[TCA_HTB_MAX + 1];
 
   76         struct rtnl_htb_class *htb = data;
 
   79         if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
 
   82         if (tb[TCA_HTB_PARMS]) {
 
   83                 struct tc_htb_opt opts;
 
   85                 nla_memcpy(&opts, tb[TCA_HTB_PARMS], 
sizeof(opts));
 
   86                 htb->ch_prio = opts.prio;
 
   87                 rtnl_copy_ratespec(&htb->ch_rate, &opts.rate);
 
   88                 rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil);
 
   93                 htb->ch_quantum = opts.quantum;
 
   94                 htb->ch_level = opts.level;
 
   99                 htb->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE |
 
  100                                 SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER |
 
  101                                 SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM |
 
  108 static void htb_qdisc_dump_line(
struct rtnl_tc *tc, 
void *data,
 
  111         struct rtnl_htb_qdisc *htb = data;
 
  116         if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
 
  117                 nl_dump(p, 
" r2q %u", htb->qh_rate2quantum);
 
  119         if (htb->qh_mask & SCH_HTB_HAS_DEFCLS) {
 
  121                 nl_dump(p, 
" default-class %s",
 
  126 static void htb_class_dump_line(
struct rtnl_tc *tc, 
void *data,
 
  129         struct rtnl_htb_class *htb = data;
 
  134         if (htb->ch_mask & SCH_HTB_HAS_RATE) {
 
  141                 nl_dump(p, 
" rate %.2f%s/s (%.0f%s) log %u",
 
  142                         r, ru, rbit, rubit, 1<<htb->ch_rate.rs_cell_log);
 
  146 static void htb_class_dump_details(
struct rtnl_tc *tc, 
void *data,
 
  149         struct rtnl_htb_class *htb = data;
 
  155         if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
 
  162                 nl_dump(p, 
" ceil %.2f%s/s (%.0f%s) log %u",
 
  163                         r, ru, rbit, rubit, 1<<htb->ch_ceil.rs_cell_log);
 
  166         if (htb->ch_mask & SCH_HTB_HAS_PRIO)
 
  167                 nl_dump(p, 
" prio %u", htb->ch_prio);
 
  169         if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) {
 
  174                 nl_dump(p, 
" rbuffer %.2f%s", b, bu);
 
  177         if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) {
 
  182                 nl_dump(p, 
" cbuffer %.2f%s", b, bu);
 
  185         if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
 
  186                 nl_dump(p, 
" quantum %u", htb->ch_quantum);
 
  189 static int htb_qdisc_msg_fill(
struct rtnl_tc *tc, 
void *data,
 
  192         struct rtnl_htb_qdisc *htb = data;
 
  193         struct tc_htb_glob opts = {
 
  194                 .version = TC_HTB_PROTOVER,
 
  199                 if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
 
  200                         opts.rate2quantum = htb->qh_rate2quantum;
 
  202                 if (htb->qh_mask & SCH_HTB_HAS_DEFCLS)
 
  203                         opts.defcls = htb->qh_defcls;
 
  206         return nla_put(msg, TCA_HTB_INIT, 
sizeof(opts), &opts);
 
  209 static int htb_class_msg_fill(
struct rtnl_tc *tc, 
void *data,
 
  212         struct rtnl_htb_class *htb = data;
 
  213         uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE];
 
  214         struct tc_htb_opt opts;
 
  217         if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE))
 
  220         memset(&opts, 0, 
sizeof(opts));
 
  223         if (htb->ch_mask & SCH_HTB_HAS_PRIO)
 
  224                 opts.prio = htb->ch_prio;
 
  229         rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate);
 
  231         if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
 
  233                 rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil);
 
  239                 memcpy(&opts.ceil, &opts.rate, 
sizeof(
struct tc_ratespec));
 
  242         if (htb->ch_mask & SCH_HTB_HAS_RBUFFER)
 
  243                 buffer = htb->ch_rbuffer;
 
  249         if (htb->ch_mask & SCH_HTB_HAS_CBUFFER)
 
  250                 cbuffer = htb->ch_cbuffer;
 
  256         if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
 
  257                 opts.quantum = htb->ch_quantum;
 
  259         NLA_PUT(msg, TCA_HTB_PARMS, 
sizeof(opts), &opts);
 
  260         NLA_PUT(msg, TCA_HTB_RTAB, 
sizeof(rtable), &rtable);
 
  261         NLA_PUT(msg, TCA_HTB_CTAB, 
sizeof(ctable), &ctable);
 
  269 static struct rtnl_tc_ops htb_qdisc_ops;
 
  270 static struct rtnl_tc_ops htb_class_ops;
 
  272 static struct rtnl_htb_qdisc *htb_qdisc_data(
struct rtnl_qdisc *qdisc)
 
  277 static struct rtnl_htb_class *htb_class_data(
struct rtnl_class *
class)
 
  295         struct rtnl_htb_qdisc *htb;
 
  297         if ((htb = htb_qdisc_data(qdisc)) &&
 
  298             htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
 
  299                 return htb->qh_rate2quantum;
 
  304 int rtnl_htb_set_rate2quantum(
struct rtnl_qdisc *qdisc, uint32_t rate2quantum)
 
  306         struct rtnl_htb_qdisc *htb;
 
  308         if (!(htb = htb_qdisc_data(qdisc)))
 
  309                 return -NLE_OPNOTSUPP;
 
  311         htb->qh_rate2quantum = rate2quantum;
 
  312         htb->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM;
 
  328         struct rtnl_htb_qdisc *htb;
 
  330         if ((htb = htb_qdisc_data(qdisc)) &&
 
  331             htb->qh_mask & SCH_HTB_HAS_DEFCLS)
 
  332                 return htb->qh_defcls;
 
  344         struct rtnl_htb_qdisc *htb;
 
  346         if (!(htb = htb_qdisc_data(qdisc)))
 
  347                 return -NLE_OPNOTSUPP;
 
  349         htb->qh_defcls = defcls;
 
  350         htb->qh_mask |= SCH_HTB_HAS_DEFCLS;
 
  355 uint32_t rtnl_htb_get_prio(
struct rtnl_class *
class)
 
  357         struct rtnl_htb_class *htb;
 
  359         if ((htb = htb_class_data(
class)) && htb->ch_mask & SCH_HTB_HAS_PRIO)
 
  365 int rtnl_htb_set_prio(
struct rtnl_class *
class, uint32_t prio)
 
  367         struct rtnl_htb_class *htb;
 
  369         if (!(htb = htb_class_data(
class)))
 
  370                 return -NLE_OPNOTSUPP;
 
  373         htb->ch_mask |= SCH_HTB_HAS_PRIO;
 
  386         struct rtnl_htb_class *htb;
 
  388         if ((htb = htb_class_data(
class)) && htb->ch_mask & SCH_HTB_HAS_RATE)
 
  389                 return htb->ch_rate.rs_rate;
 
  403         struct rtnl_htb_class *htb;
 
  405         if (!(htb = htb_class_data(
class)))
 
  406                 return -NLE_OPNOTSUPP;
 
  408         htb->ch_rate.rs_cell_log = UINT8_MAX; 
 
  409         htb->ch_rate.rs_rate = rate;
 
  410         htb->ch_mask |= SCH_HTB_HAS_RATE;
 
  423         struct rtnl_htb_class *htb;
 
  425         if ((htb = htb_class_data(
class)) && htb->ch_mask & SCH_HTB_HAS_CEIL)
 
  426                 return htb->ch_ceil.rs_rate;
 
  440         struct rtnl_htb_class *htb;
 
  442         if (!(htb = htb_class_data(
class)))
 
  443                 return -NLE_OPNOTSUPP;
 
  445         htb->ch_ceil.rs_cell_log = UINT8_MAX; 
 
  446         htb->ch_ceil.rs_rate = ceil;
 
  447         htb->ch_mask |= SCH_HTB_HAS_CEIL;
 
  460         struct rtnl_htb_class *htb;
 
  462         if ((htb = htb_class_data(
class)) &&
 
  463              htb->ch_mask & SCH_HTB_HAS_RBUFFER)
 
  464                 return htb->ch_rbuffer;
 
  476         struct rtnl_htb_class *htb;
 
  478         if (!(htb = htb_class_data(
class)))
 
  479                 return -NLE_OPNOTSUPP;
 
  481         htb->ch_rbuffer = rbuffer;
 
  482         htb->ch_mask |= SCH_HTB_HAS_RBUFFER;
 
  495         struct rtnl_htb_class *htb;
 
  497         if ((htb = htb_class_data(
class)) &&
 
  498              htb->ch_mask & SCH_HTB_HAS_CBUFFER)
 
  499                 return htb->ch_cbuffer;
 
  511         struct rtnl_htb_class *htb;
 
  513         if (!(htb = htb_class_data(
class)))
 
  514                 return -NLE_OPNOTSUPP;
 
  516         htb->ch_cbuffer = cbuffer;
 
  517         htb->ch_mask |= SCH_HTB_HAS_CBUFFER;
 
  532         struct rtnl_htb_class *htb;
 
  534         if ((htb = htb_class_data(
class)) &&
 
  535             htb->ch_mask & SCH_HTB_HAS_QUANTUM)
 
  536                 return htb->ch_quantum;
 
  552         struct rtnl_htb_class *htb;
 
  554         if (!(htb = htb_class_data(
class)))
 
  555                 return -NLE_OPNOTSUPP;
 
  557         htb->ch_quantum = quantum;
 
  558         htb->ch_mask |= SCH_HTB_HAS_QUANTUM;
 
  575         struct rtnl_htb_class *htb;
 
  577         if ((htb = htb_class_data(
class)) && htb->ch_mask & SCH_HTB_HAS_LEVEL)
 
  578                 return htb->ch_level;
 
  580         return -NLE_OPNOTSUPP;
 
  597         struct rtnl_htb_class *htb;
 
  599         if (!(htb = htb_class_data(
class)))
 
  600                 return -NLE_OPNOTSUPP;
 
  602         htb->ch_level = level;
 
  603         htb->ch_mask |= SCH_HTB_HAS_LEVEL;
 
  610 static struct rtnl_tc_ops htb_qdisc_ops = {
 
  612         .to_type                = RTNL_TC_TYPE_QDISC,
 
  613         .to_size                = 
sizeof(
struct rtnl_htb_qdisc),
 
  614         .to_msg_parser          = htb_qdisc_msg_parser,
 
  616         .to_msg_fill            = htb_qdisc_msg_fill,
 
  619 static struct rtnl_tc_ops htb_class_ops = {
 
  621         .to_type                = RTNL_TC_TYPE_CLASS,
 
  622         .to_size                = 
sizeof(
struct rtnl_htb_class),
 
  623         .to_msg_parser          = htb_class_msg_parser,
 
  628         .to_msg_fill            = htb_class_msg_fill,
 
  631 static void __init htb_init(
void)
 
  637 static void __exit htb_exit(
void)