sfq.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * lib/route/sch/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-2006 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup qdisc_api
  13. * @defgroup 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-local.h>
  25. #include <netlink-tc.h>
  26. #include <netlink/netlink.h>
  27. #include <netlink/utils.h>
  28. #include <netlink/route/qdisc.h>
  29. #include <netlink/route/qdisc-modules.h>
  30. #include <netlink/route/sch/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 inline struct rtnl_sfq *sfq_qdisc(struct rtnl_qdisc *qdisc)
  39. {
  40. return (struct rtnl_sfq *) qdisc->q_subdata;
  41. }
  42. static inline struct rtnl_sfq *sfq_alloc(struct rtnl_qdisc *qdisc)
  43. {
  44. if (!qdisc->q_subdata)
  45. qdisc->q_subdata = calloc(1, sizeof(struct rtnl_sfq));
  46. return sfq_qdisc(qdisc);
  47. }
  48. static int sfq_msg_parser(struct rtnl_qdisc *qdisc)
  49. {
  50. struct rtnl_sfq *sfq;
  51. struct tc_sfq_qopt *opts;
  52. if (!(qdisc->ce_mask & TCA_ATTR_OPTS))
  53. return 0;
  54. if (qdisc->q_opts->d_size < sizeof(*opts))
  55. return nl_error(EINVAL, "SFQ specific options size mismatch");
  56. sfq = sfq_alloc(qdisc);
  57. if (!sfq)
  58. return nl_errno(ENOMEM);
  59. opts = (struct tc_sfq_qopt *) qdisc->q_opts->d_data;
  60. sfq->qs_quantum = opts->quantum;
  61. sfq->qs_perturb = opts->perturb_period;
  62. sfq->qs_limit = opts->limit;
  63. sfq->qs_divisor = opts->divisor;
  64. sfq->qs_flows = opts->flows;
  65. sfq->qs_mask = (SCH_SFQ_ATTR_QUANTUM | SCH_SFQ_ATTR_PERTURB |
  66. SCH_SFQ_ATTR_LIMIT | SCH_SFQ_ATTR_DIVISOR |
  67. SCH_SFQ_ATTR_FLOWS);
  68. return 0;
  69. }
  70. static void sfq_free_data(struct rtnl_qdisc *qdisc)
  71. {
  72. free(qdisc->q_subdata);
  73. }
  74. static int sfq_dump_brief(struct rtnl_qdisc *qdisc, struct nl_dump_params *p,
  75. int line)
  76. {
  77. struct rtnl_sfq *sfq = sfq_qdisc(qdisc);
  78. if (sfq)
  79. dp_dump(p, " quantum %u perturb %us",
  80. sfq->qs_quantum,
  81. nl_ticks2us(sfq->qs_perturb * nl_get_hz()));
  82. return line;
  83. }
  84. static int sfq_dump_full(struct rtnl_qdisc *qdisc, struct nl_dump_params *p,
  85. int line)
  86. {
  87. struct rtnl_sfq *sfq = sfq_qdisc(qdisc);
  88. if (sfq)
  89. dp_dump(p, "limit %u divisor %u",
  90. sfq->qs_limit, sfq->qs_divisor);
  91. return line;
  92. }
  93. static struct nl_msg *sfq_get_opts(struct rtnl_qdisc *qdisc)
  94. {
  95. struct rtnl_sfq *sfq;
  96. struct tc_sfq_qopt opts;
  97. struct nl_msg *msg;
  98. sfq = sfq_qdisc(qdisc);
  99. if (!sfq)
  100. return NULL;
  101. msg = nlmsg_alloc();
  102. if (!msg)
  103. goto errout;
  104. memset(&opts, 0, sizeof(opts));
  105. opts.quantum = sfq->qs_quantum;
  106. opts.perturb_period = sfq->qs_perturb;
  107. opts.limit = sfq->qs_limit;
  108. if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0)
  109. goto errout;
  110. return msg;
  111. errout:
  112. nlmsg_free(msg);
  113. return NULL;
  114. }
  115. /**
  116. * @name Attribute Access
  117. * @{
  118. */
  119. /**
  120. * Set quantum of SFQ qdisc.
  121. * @arg qdisc SFQ qdisc to be modified.
  122. * @arg quantum New quantum in bytes.
  123. * @return 0 on success or a negative error code.
  124. */
  125. int rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
  126. {
  127. struct rtnl_sfq *sfq;
  128. sfq = sfq_alloc(qdisc);
  129. if (!sfq)
  130. return nl_errno(ENOMEM);
  131. sfq->qs_quantum = quantum;
  132. sfq->qs_mask |= SCH_SFQ_ATTR_QUANTUM;
  133. return 0;
  134. }
  135. /**
  136. * Get quantum of SFQ qdisc.
  137. * @arg qdisc SFQ qdisc.
  138. * @return Quantum in bytes or a negative error code.
  139. */
  140. int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc)
  141. {
  142. struct rtnl_sfq *sfq;
  143. sfq = sfq_qdisc(qdisc);
  144. if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_QUANTUM)
  145. return sfq->qs_quantum;
  146. else
  147. return nl_errno(ENOENT);
  148. }
  149. /**
  150. * Set limit of SFQ qdisc.
  151. * @arg qdisc SFQ qdisc to be modified.
  152. * @arg limit New limit in number of packets.
  153. * @return 0 on success or a negative error code.
  154. */
  155. int rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
  156. {
  157. struct rtnl_sfq *sfq;
  158. sfq = sfq_alloc(qdisc);
  159. if (!sfq)
  160. return nl_errno(ENOMEM);
  161. sfq->qs_limit = limit;
  162. sfq->qs_mask |= SCH_SFQ_ATTR_LIMIT;
  163. return 0;
  164. }
  165. /**
  166. * Get limit of SFQ qdisc.
  167. * @arg qdisc SFQ qdisc.
  168. * @return Limit or a negative error code.
  169. */
  170. int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc)
  171. {
  172. struct rtnl_sfq *sfq;
  173. sfq = sfq_qdisc(qdisc);
  174. if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_LIMIT)
  175. return sfq->qs_limit;
  176. else
  177. return nl_errno(ENOENT);
  178. }
  179. /**
  180. * Set perturbation interval of SFQ qdisc.
  181. * @arg qdisc SFQ qdisc to be modified.
  182. * @arg perturb New perturbation interval in seconds.
  183. * @note A value of 0 disables perturbation altogether.
  184. * @return 0 on success or a negative error code.
  185. */
  186. int rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
  187. {
  188. struct rtnl_sfq *sfq;
  189. sfq = sfq_alloc(qdisc);
  190. if (!sfq)
  191. return nl_errno(ENOMEM);
  192. sfq->qs_perturb = perturb;
  193. sfq->qs_mask |= SCH_SFQ_ATTR_PERTURB;
  194. return 0;
  195. }
  196. /**
  197. * Get perturbation interval of SFQ qdisc.
  198. * @arg qdisc SFQ qdisc.
  199. * @return Perturbation interval in seconds or a negative error code.
  200. */
  201. int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc)
  202. {
  203. struct rtnl_sfq *sfq;
  204. sfq = sfq_qdisc(qdisc);
  205. if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_PERTURB)
  206. return sfq->qs_perturb;
  207. else
  208. return nl_errno(ENOENT);
  209. }
  210. /**
  211. * Get divisor of SFQ qdisc.
  212. * @arg qdisc SFQ qdisc.
  213. * @return Divisor in number of entries or a negative error code.
  214. */
  215. int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc)
  216. {
  217. struct rtnl_sfq *sfq;
  218. sfq = sfq_qdisc(qdisc);
  219. if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_DIVISOR)
  220. return sfq->qs_divisor;
  221. else
  222. return nl_errno(ENOENT);
  223. }
  224. /** @} */
  225. static struct rtnl_qdisc_ops sfq_ops = {
  226. .qo_kind = "sfq",
  227. .qo_msg_parser = sfq_msg_parser,
  228. .qo_free_data = sfq_free_data,
  229. .qo_dump[NL_DUMP_BRIEF] = sfq_dump_brief,
  230. .qo_dump[NL_DUMP_FULL] = sfq_dump_full,
  231. .qo_get_opts = sfq_get_opts,
  232. };
  233. static void __init sfq_init(void)
  234. {
  235. rtnl_qdisc_register(&sfq_ops);
  236. }
  237. static void __exit sfq_exit(void)
  238. {
  239. rtnl_qdisc_unregister(&sfq_ops);
  240. }
  241. /** @} */