cbq.c 5.5 KB

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