libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/qdisc/cbq.c
00001 /*
00002  * lib/route/qdisc/cbq.c        Class Based Queueing
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 #include <netlink-local.h>
00013 #include <netlink-tc.h>
00014 #include <netlink/netlink.h>
00015 #include <netlink/utils.h>
00016 #include <netlink/route/tc-api.h>
00017 #include <netlink/route/qdisc.h>
00018 #include <netlink/route/class.h>
00019 #include <netlink/route/link.h>
00020 #include <netlink/route/qdisc/cbq.h>
00021 #include <netlink/route/cls/police.h>
00022 
00023 /**
00024  * @ingroup qdisc
00025  * @ingroup class
00026  * @defgroup qdisc_cbq Class Based Queueing (CBQ)
00027  * @{
00028  */
00029 
00030 static const struct trans_tbl ovl_strategies[] = {
00031         __ADD(TC_CBQ_OVL_CLASSIC,classic)
00032         __ADD(TC_CBQ_OVL_DELAY,delay)
00033         __ADD(TC_CBQ_OVL_LOWPRIO,lowprio)
00034         __ADD(TC_CBQ_OVL_DROP,drop)
00035         __ADD(TC_CBQ_OVL_RCLASSIC,rclassic)
00036 };
00037 
00038 /**
00039  * Convert a CBQ OVL strategy to a character string
00040  * @arg type            CBQ OVL strategy
00041  * @arg buf             destination buffer
00042  * @arg len             length of destination buffer
00043  *
00044  * Converts a CBQ OVL strategy to a character string and stores in the
00045  * provided buffer. Returns the destination buffer or the type
00046  * encoded in hex if no match was found.
00047  */
00048 char *nl_ovl_strategy2str(int type, char *buf, size_t len)
00049 {
00050         return __type2str(type, buf, len, ovl_strategies,
00051                             ARRAY_SIZE(ovl_strategies));
00052 }
00053 
00054 /**
00055  * Convert a string to a CBQ OVL strategy
00056  * @arg name            CBQ OVL stragegy name
00057  *
00058  * Converts a CBQ OVL stragegy name to it's corresponding CBQ OVL strategy
00059  * type. Returns the type or -1 if none was found.
00060  */
00061 int nl_str2ovl_strategy(const char *name)
00062 {
00063         return __str2type(name, ovl_strategies, ARRAY_SIZE(ovl_strategies));
00064 }
00065 
00066 static struct nla_policy cbq_policy[TCA_CBQ_MAX+1] = {
00067         [TCA_CBQ_LSSOPT]        = { .minlen = sizeof(struct tc_cbq_lssopt) },
00068         [TCA_CBQ_RATE]          = { .minlen = sizeof(struct tc_ratespec) },
00069         [TCA_CBQ_WRROPT]        = { .minlen = sizeof(struct tc_cbq_wrropt) },
00070         [TCA_CBQ_OVL_STRATEGY]  = { .minlen = sizeof(struct tc_cbq_ovl) },
00071         [TCA_CBQ_FOPT]          = { .minlen = sizeof(struct tc_cbq_fopt) },
00072         [TCA_CBQ_POLICE]        = { .minlen = sizeof(struct tc_cbq_police) },
00073 };
00074 
00075 static int cbq_msg_parser(struct rtnl_tc *tc, void *data)
00076 {
00077         struct nlattr *tb[TCA_CBQ_MAX + 1];
00078         struct rtnl_cbq *cbq = data;
00079         int err;
00080 
00081         err = tca_parse(tb, TCA_CBQ_MAX, tc, cbq_policy);
00082         if (err < 0)
00083                 return err;
00084 
00085         nla_memcpy(&cbq->cbq_lss, tb[TCA_CBQ_LSSOPT], sizeof(cbq->cbq_lss));
00086         nla_memcpy(&cbq->cbq_rate, tb[TCA_CBQ_RATE], sizeof(cbq->cbq_rate));
00087         nla_memcpy(&cbq->cbq_wrr, tb[TCA_CBQ_WRROPT], sizeof(cbq->cbq_wrr));
00088         nla_memcpy(&cbq->cbq_fopt, tb[TCA_CBQ_FOPT], sizeof(cbq->cbq_fopt));
00089         nla_memcpy(&cbq->cbq_ovl, tb[TCA_CBQ_OVL_STRATEGY],
00090                    sizeof(cbq->cbq_ovl));
00091         nla_memcpy(&cbq->cbq_police, tb[TCA_CBQ_POLICE],
00092                     sizeof(cbq->cbq_police));
00093         
00094         return 0;
00095 }
00096 
00097 static void cbq_dump_line(struct rtnl_tc *tc, void *data,
00098                           struct nl_dump_params *p)
00099 {
00100         struct rtnl_cbq *cbq = data;
00101         double r, rbit;
00102         char *ru, *rubit;
00103 
00104         if (!cbq)
00105                 return;
00106 
00107         r = nl_cancel_down_bytes(cbq->cbq_rate.rate, &ru);
00108         rbit = nl_cancel_down_bits(cbq->cbq_rate.rate * 8, &rubit);
00109 
00110         nl_dump(p, " rate %.2f%s/s (%.0f%s) prio %u",
00111                 r, ru, rbit, rubit, cbq->cbq_wrr.priority);
00112 }
00113 
00114 static void cbq_dump_details(struct rtnl_tc *tc, void *data,
00115                              struct nl_dump_params *p)
00116 {
00117         struct rtnl_cbq *cbq = data;
00118         char *unit, buf[32];
00119         double w;
00120         uint32_t el;
00121 
00122         if (!cbq)
00123                 return;
00124 
00125         w = nl_cancel_down_bits(cbq->cbq_wrr.weight * 8, &unit);
00126 
00127         nl_dump(p, "avgpkt %u mpu %u cell %u allot %u weight %.0f%s\n",
00128                 cbq->cbq_lss.avpkt,
00129                 cbq->cbq_rate.mpu,
00130                 1 << cbq->cbq_rate.cell_log,
00131                 cbq->cbq_wrr.allot, w, unit);
00132 
00133         el = cbq->cbq_lss.ewma_log;
00134         nl_dump_line(p, "  minidle %uus maxidle %uus offtime "
00135                                 "%uus level %u ewma_log %u\n",
00136                 nl_ticks2us(cbq->cbq_lss.minidle >> el),
00137                 nl_ticks2us(cbq->cbq_lss.maxidle >> el),
00138                 nl_ticks2us(cbq->cbq_lss.offtime >> el),
00139                 cbq->cbq_lss.level,
00140                 cbq->cbq_lss.ewma_log);
00141 
00142         nl_dump_line(p, "  penalty %uus strategy %s ",
00143                 nl_ticks2us(cbq->cbq_ovl.penalty),
00144                 nl_ovl_strategy2str(cbq->cbq_ovl.strategy, buf, sizeof(buf)));
00145 
00146         nl_dump(p, "split %s defmap 0x%08x ",
00147                 rtnl_tc_handle2str(cbq->cbq_fopt.split, buf, sizeof(buf)),
00148                 cbq->cbq_fopt.defmap);
00149         
00150         nl_dump(p, "police %s",
00151                 nl_police2str(cbq->cbq_police.police, buf, sizeof(buf)));
00152 }
00153 
00154 static void cbq_dump_stats(struct rtnl_tc *tc, void *data,
00155                            struct nl_dump_params *p)
00156 {
00157         struct tc_cbq_xstats *x;
00158         
00159         if (!(x = tca_xstats(tc)))
00160                 return;
00161 
00162         nl_dump_line(p, "            borrows    overact  "
00163                         "  avgidle  undertime\n");
00164         nl_dump_line(p, "         %10u %10u %10u %10u\n",
00165                      x->borrows, x->overactions, x->avgidle, x->undertime);
00166 }
00167 
00168 static struct rtnl_tc_ops cbq_qdisc_ops = {
00169         .to_kind                = "cbq",
00170         .to_type                = RTNL_TC_TYPE_QDISC,
00171         .to_size                = sizeof(struct rtnl_cbq),
00172         .to_msg_parser          = cbq_msg_parser,
00173         .to_dump = {
00174             [NL_DUMP_LINE]      = cbq_dump_line,
00175             [NL_DUMP_DETAILS]   = cbq_dump_details,
00176             [NL_DUMP_STATS]     = cbq_dump_stats,
00177         },
00178 };
00179 
00180 static struct rtnl_tc_ops cbq_class_ops = {
00181         .to_kind                = "cbq",
00182         .to_type                = RTNL_TC_TYPE_CLASS,
00183         .to_size                = sizeof(struct rtnl_cbq),
00184         .to_msg_parser          = cbq_msg_parser,
00185         .to_dump = {
00186             [NL_DUMP_LINE]      = cbq_dump_line,
00187             [NL_DUMP_DETAILS]   = cbq_dump_details,
00188             [NL_DUMP_STATS]     = cbq_dump_stats,
00189         },
00190 };
00191 
00192 static void __init cbq_init(void)
00193 {
00194         rtnl_tc_register(&cbq_qdisc_ops);
00195         rtnl_tc_register(&cbq_class_ops);
00196 }
00197 
00198 static void __exit cbq_exit(void)
00199 {
00200         rtnl_tc_unregister(&cbq_qdisc_ops);
00201         rtnl_tc_unregister(&cbq_class_ops);
00202 }
00203 
00204 /** @} */