Home | History | Annotate | Download | only in qdisc
      1 /*
      2  * lib/route/qdisc/cbq.c	Class Based Queueing
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2003-2011 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 #include <netlink-private/netlink.h>
     13 #include <netlink-private/tc.h>
     14 #include <netlink/netlink.h>
     15 #include <netlink/utils.h>
     16 #include <netlink-private/route/tc-api.h>
     17 #include <netlink/route/qdisc.h>
     18 #include <netlink/route/class.h>
     19 #include <netlink/route/link.h>
     20 #include <netlink/route/qdisc/cbq.h>
     21 #include <netlink/route/cls/police.h>
     22 
     23 /**
     24  * @ingroup qdisc
     25  * @ingroup class
     26  * @defgroup qdisc_cbq Class Based Queueing (CBQ)
     27  * @{
     28  */
     29 
     30 static const struct trans_tbl ovl_strategies[] = {
     31 	__ADD(TC_CBQ_OVL_CLASSIC,classic)
     32 	__ADD(TC_CBQ_OVL_DELAY,delay)
     33 	__ADD(TC_CBQ_OVL_LOWPRIO,lowprio)
     34 	__ADD(TC_CBQ_OVL_DROP,drop)
     35 	__ADD(TC_CBQ_OVL_RCLASSIC,rclassic)
     36 };
     37 
     38 /**
     39  * Convert a CBQ OVL strategy to a character string
     40  * @arg type		CBQ OVL strategy
     41  * @arg buf		destination buffer
     42  * @arg len		length of destination buffer
     43  *
     44  * Converts a CBQ OVL strategy to a character string and stores in the
     45  * provided buffer. Returns the destination buffer or the type
     46  * encoded in hex if no match was found.
     47  */
     48 char *nl_ovl_strategy2str(int type, char *buf, size_t len)
     49 {
     50 	return __type2str(type, buf, len, ovl_strategies,
     51 			    ARRAY_SIZE(ovl_strategies));
     52 }
     53 
     54 /**
     55  * Convert a string to a CBQ OVL strategy
     56  * @arg name		CBQ OVL stragegy name
     57  *
     58  * Converts a CBQ OVL stragegy name to it's corresponding CBQ OVL strategy
     59  * type. Returns the type or -1 if none was found.
     60  */
     61 int nl_str2ovl_strategy(const char *name)
     62 {
     63 	return __str2type(name, ovl_strategies, ARRAY_SIZE(ovl_strategies));
     64 }
     65 
     66 static struct nla_policy cbq_policy[TCA_CBQ_MAX+1] = {
     67 	[TCA_CBQ_LSSOPT]	= { .minlen = sizeof(struct tc_cbq_lssopt) },
     68 	[TCA_CBQ_RATE]		= { .minlen = sizeof(struct tc_ratespec) },
     69 	[TCA_CBQ_WRROPT]	= { .minlen = sizeof(struct tc_cbq_wrropt) },
     70 	[TCA_CBQ_OVL_STRATEGY]	= { .minlen = sizeof(struct tc_cbq_ovl) },
     71 	[TCA_CBQ_FOPT]		= { .minlen = sizeof(struct tc_cbq_fopt) },
     72 	[TCA_CBQ_POLICE]	= { .minlen = sizeof(struct tc_cbq_police) },
     73 };
     74 
     75 static int cbq_msg_parser(struct rtnl_tc *tc, void *data)
     76 {
     77 	struct nlattr *tb[TCA_CBQ_MAX + 1];
     78 	struct rtnl_cbq *cbq = data;
     79 	int err;
     80 
     81 	err = tca_parse(tb, TCA_CBQ_MAX, tc, cbq_policy);
     82 	if (err < 0)
     83 		return err;
     84 
     85 	nla_memcpy(&cbq->cbq_lss, tb[TCA_CBQ_LSSOPT], sizeof(cbq->cbq_lss));
     86 	nla_memcpy(&cbq->cbq_rate, tb[TCA_CBQ_RATE], sizeof(cbq->cbq_rate));
     87 	nla_memcpy(&cbq->cbq_wrr, tb[TCA_CBQ_WRROPT], sizeof(cbq->cbq_wrr));
     88 	nla_memcpy(&cbq->cbq_fopt, tb[TCA_CBQ_FOPT], sizeof(cbq->cbq_fopt));
     89 	nla_memcpy(&cbq->cbq_ovl, tb[TCA_CBQ_OVL_STRATEGY],
     90 		   sizeof(cbq->cbq_ovl));
     91 	nla_memcpy(&cbq->cbq_police, tb[TCA_CBQ_POLICE],
     92 		    sizeof(cbq->cbq_police));
     93 
     94 	return 0;
     95 }
     96 
     97 static void cbq_dump_line(struct rtnl_tc *tc, void *data,
     98 			  struct nl_dump_params *p)
     99 {
    100 	struct rtnl_cbq *cbq = data;
    101 	double r, rbit;
    102 	char *ru, *rubit;
    103 
    104 	if (!cbq)
    105 		return;
    106 
    107 	r = nl_cancel_down_bytes(cbq->cbq_rate.rate, &ru);
    108 	rbit = nl_cancel_down_bits(cbq->cbq_rate.rate * 8, &rubit);
    109 
    110 	nl_dump(p, " rate %.2f%s/s (%.0f%s) prio %u",
    111 		r, ru, rbit, rubit, cbq->cbq_wrr.priority);
    112 }
    113 
    114 static void cbq_dump_details(struct rtnl_tc *tc, void *data,
    115 			     struct nl_dump_params *p)
    116 {
    117 	struct rtnl_cbq *cbq = data;
    118 	char *unit, buf[32];
    119 	double w;
    120 	uint32_t el;
    121 
    122 	if (!cbq)
    123 		return;
    124 
    125 	w = nl_cancel_down_bits(cbq->cbq_wrr.weight * 8, &unit);
    126 
    127 	nl_dump(p, "avgpkt %u mpu %u cell %u allot %u weight %.0f%s\n",
    128 		cbq->cbq_lss.avpkt,
    129 		cbq->cbq_rate.mpu,
    130 		1 << cbq->cbq_rate.cell_log,
    131 		cbq->cbq_wrr.allot, w, unit);
    132 
    133 	el = cbq->cbq_lss.ewma_log;
    134 	nl_dump_line(p, "  minidle %uus maxidle %uus offtime "
    135 				"%uus level %u ewma_log %u\n",
    136 		nl_ticks2us(cbq->cbq_lss.minidle >> el),
    137 		nl_ticks2us(cbq->cbq_lss.maxidle >> el),
    138 		nl_ticks2us(cbq->cbq_lss.offtime >> el),
    139 		cbq->cbq_lss.level,
    140 		cbq->cbq_lss.ewma_log);
    141 
    142 	nl_dump_line(p, "  penalty %uus strategy %s ",
    143 		nl_ticks2us(cbq->cbq_ovl.penalty),
    144 		nl_ovl_strategy2str(cbq->cbq_ovl.strategy, buf, sizeof(buf)));
    145 
    146 	nl_dump(p, "split %s defmap 0x%08x ",
    147 		rtnl_tc_handle2str(cbq->cbq_fopt.split, buf, sizeof(buf)),
    148 		cbq->cbq_fopt.defmap);
    149 
    150 	nl_dump(p, "police %s",
    151 		nl_police2str(cbq->cbq_police.police, buf, sizeof(buf)));
    152 }
    153 
    154 static void cbq_dump_stats(struct rtnl_tc *tc, void *data,
    155 			   struct nl_dump_params *p)
    156 {
    157 	struct tc_cbq_xstats *x;
    158 
    159 	if (!(x = tca_xstats(tc)))
    160 		return;
    161 
    162 	nl_dump_line(p, "            borrows    overact  "
    163 			"  avgidle  undertime\n");
    164 	nl_dump_line(p, "         %10u %10u %10u %10u\n",
    165 		     x->borrows, x->overactions, x->avgidle, x->undertime);
    166 }
    167 
    168 static struct rtnl_tc_ops cbq_qdisc_ops = {
    169 	.to_kind		= "cbq",
    170 	.to_type		= RTNL_TC_TYPE_QDISC,
    171 	.to_size		= sizeof(struct rtnl_cbq),
    172 	.to_msg_parser		= cbq_msg_parser,
    173 	.to_dump = {
    174 	    [NL_DUMP_LINE]	= cbq_dump_line,
    175 	    [NL_DUMP_DETAILS]	= cbq_dump_details,
    176 	    [NL_DUMP_STATS]	= cbq_dump_stats,
    177 	},
    178 };
    179 
    180 static struct rtnl_tc_ops cbq_class_ops = {
    181 	.to_kind		= "cbq",
    182 	.to_type		= RTNL_TC_TYPE_CLASS,
    183 	.to_size		= sizeof(struct rtnl_cbq),
    184 	.to_msg_parser		= cbq_msg_parser,
    185 	.to_dump = {
    186 	    [NL_DUMP_LINE]	= cbq_dump_line,
    187 	    [NL_DUMP_DETAILS]	= cbq_dump_details,
    188 	    [NL_DUMP_STATS]	= cbq_dump_stats,
    189 	},
    190 };
    191 
    192 static void __init cbq_init(void)
    193 {
    194 	rtnl_tc_register(&cbq_qdisc_ops);
    195 	rtnl_tc_register(&cbq_class_ops);
    196 }
    197 
    198 static void __exit cbq_exit(void)
    199 {
    200 	rtnl_tc_unregister(&cbq_qdisc_ops);
    201 	rtnl_tc_unregister(&cbq_class_ops);
    202 }
    203 
    204 /** @} */
    205