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