sfq.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * lib/route/qdisc/sfq.c SFQ Qdisc
  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. /**
  12. * @ingroup qdisc
  13. * @defgroup qdisc_sfq Stochastic Fairness Queueing (SFQ)
  14. * @brief
  15. *
  16. * @par Parameter Description
  17. * - \b Quantum: Number of bytes to send out per slot and round.
  18. * - \b Perturbation: Timer period between changing the hash function.
  19. * - \b Limit: Upper limit of queue in number of packets before SFQ starts
  20. * dropping packets.
  21. * - \b Divisor: Hash table divisor, i.e. size of hash table.
  22. * @{
  23. */
  24. #include <netlink-private/netlink.h>
  25. #include <netlink-private/tc.h>
  26. #include <netlink/netlink.h>
  27. #include <netlink/utils.h>
  28. #include <netlink-private/route/tc-api.h>
  29. #include <netlink/route/qdisc.h>
  30. #include <netlink/route/qdisc/sfq.h>
  31. /** @cond SKIP */
  32. #define SCH_SFQ_ATTR_QUANTUM 0x01
  33. #define SCH_SFQ_ATTR_PERTURB 0x02
  34. #define SCH_SFQ_ATTR_LIMIT 0x04
  35. #define SCH_SFQ_ATTR_DIVISOR 0x08
  36. #define SCH_SFQ_ATTR_FLOWS 0x10
  37. /** @endcond */
  38. static int sfq_msg_parser(struct rtnl_tc *tc, void *data)
  39. {
  40. struct rtnl_sfq *sfq = data;
  41. struct tc_sfq_qopt *opts;
  42. if (!(tc->ce_mask & TCA_ATTR_OPTS))
  43. return 0;
  44. if (tc->tc_opts->d_size < sizeof(*opts))
  45. return -NLE_INVAL;
  46. opts = (struct tc_sfq_qopt *) tc->tc_opts->d_data;
  47. sfq->qs_quantum = opts->quantum;
  48. sfq->qs_perturb = opts->perturb_period;
  49. sfq->qs_limit = opts->limit;
  50. sfq->qs_divisor = opts->divisor;
  51. sfq->qs_flows = opts->flows;
  52. sfq->qs_mask = (SCH_SFQ_ATTR_QUANTUM | SCH_SFQ_ATTR_PERTURB |
  53. SCH_SFQ_ATTR_LIMIT | SCH_SFQ_ATTR_DIVISOR |
  54. SCH_SFQ_ATTR_FLOWS);
  55. return 0;
  56. }
  57. static void sfq_dump_line(struct rtnl_tc *tc, void *data,
  58. struct nl_dump_params *p)
  59. {
  60. struct rtnl_sfq *sfq = data;
  61. if (sfq)
  62. nl_dump(p, " quantum %u perturb %us", sfq->qs_quantum,
  63. sfq->qs_perturb);
  64. }
  65. static void sfq_dump_details(struct rtnl_tc *tc, void *data,
  66. struct nl_dump_params *p)
  67. {
  68. struct rtnl_sfq *sfq = data;
  69. if (sfq)
  70. nl_dump(p, "limit %u divisor %u",
  71. sfq->qs_limit, sfq->qs_divisor);
  72. }
  73. static int sfq_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
  74. {
  75. struct rtnl_sfq *sfq = data;
  76. struct tc_sfq_qopt opts = {0};
  77. if (!sfq)
  78. BUG();
  79. opts.quantum = sfq->qs_quantum;
  80. opts.perturb_period = sfq->qs_perturb;
  81. opts.limit = sfq->qs_limit;
  82. return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
  83. }
  84. /**
  85. * @name Attribute Access
  86. * @{
  87. */
  88. /**
  89. * Set quantum of SFQ qdisc.
  90. * @arg qdisc SFQ qdisc to be modified.
  91. * @arg quantum New quantum in bytes.
  92. * @return 0 on success or a negative error code.
  93. */
  94. void rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
  95. {
  96. struct rtnl_sfq *sfq;
  97. if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
  98. BUG();
  99. sfq->qs_quantum = quantum;
  100. sfq->qs_mask |= SCH_SFQ_ATTR_QUANTUM;
  101. }
  102. /**
  103. * Get quantum of SFQ qdisc.
  104. * @arg qdisc SFQ qdisc.
  105. * @return Quantum in bytes or a negative error code.
  106. */
  107. int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc)
  108. {
  109. struct rtnl_sfq *sfq;
  110. if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
  111. BUG();
  112. if (sfq->qs_mask & SCH_SFQ_ATTR_QUANTUM)
  113. return sfq->qs_quantum;
  114. else
  115. return -NLE_NOATTR;
  116. }
  117. /**
  118. * Set limit of SFQ qdisc.
  119. * @arg qdisc SFQ qdisc to be modified.
  120. * @arg limit New limit in number of packets.
  121. * @return 0 on success or a negative error code.
  122. */
  123. void rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
  124. {
  125. struct rtnl_sfq *sfq;
  126. if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
  127. BUG();
  128. sfq->qs_limit = limit;
  129. sfq->qs_mask |= SCH_SFQ_ATTR_LIMIT;
  130. }
  131. /**
  132. * Get limit of SFQ qdisc.
  133. * @arg qdisc SFQ qdisc.
  134. * @return Limit or a negative error code.
  135. */
  136. int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc)
  137. {
  138. struct rtnl_sfq *sfq;
  139. if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
  140. BUG();
  141. if (sfq->qs_mask & SCH_SFQ_ATTR_LIMIT)
  142. return sfq->qs_limit;
  143. else
  144. return -NLE_NOATTR;
  145. }
  146. /**
  147. * Set perturbation interval of SFQ qdisc.
  148. * @arg qdisc SFQ qdisc to be modified.
  149. * @arg perturb New perturbation interval in seconds.
  150. * @note A value of 0 disables perturbation altogether.
  151. * @return 0 on success or a negative error code.
  152. */
  153. void rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
  154. {
  155. struct rtnl_sfq *sfq;
  156. if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
  157. BUG();
  158. sfq->qs_perturb = perturb;
  159. sfq->qs_mask |= SCH_SFQ_ATTR_PERTURB;
  160. }
  161. /**
  162. * Get perturbation interval of SFQ qdisc.
  163. * @arg qdisc SFQ qdisc.
  164. * @return Perturbation interval in seconds or a negative error code.
  165. */
  166. int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc)
  167. {
  168. struct rtnl_sfq *sfq;
  169. if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
  170. BUG();
  171. if (sfq->qs_mask & SCH_SFQ_ATTR_PERTURB)
  172. return sfq->qs_perturb;
  173. else
  174. return -NLE_NOATTR;
  175. }
  176. /**
  177. * Get divisor of SFQ qdisc.
  178. * @arg qdisc SFQ qdisc.
  179. * @return Divisor in number of entries or a negative error code.
  180. */
  181. int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc)
  182. {
  183. struct rtnl_sfq *sfq;
  184. if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
  185. BUG();
  186. if (sfq->qs_mask & SCH_SFQ_ATTR_DIVISOR)
  187. return sfq->qs_divisor;
  188. else
  189. return -NLE_NOATTR;
  190. }
  191. /** @} */
  192. static struct rtnl_tc_ops sfq_ops = {
  193. .to_kind = "sfq",
  194. .to_type = RTNL_TC_TYPE_QDISC,
  195. .to_size = sizeof(struct rtnl_sfq),
  196. .to_msg_parser = sfq_msg_parser,
  197. .to_dump = {
  198. [NL_DUMP_LINE] = sfq_dump_line,
  199. [NL_DUMP_DETAILS] = sfq_dump_details,
  200. },
  201. .to_msg_fill = sfq_msg_fill,
  202. };
  203. static void __init sfq_init(void)
  204. {
  205. rtnl_tc_register(&sfq_ops);
  206. }
  207. static void __exit sfq_exit(void)
  208. {
  209. rtnl_tc_unregister(&sfq_ops);
  210. }
  211. /** @} */