libnl
3.2.3
|
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 /** @} */