red.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * lib/route/sch/red.c RED 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 red Random Early Detection (RED)
  14. * @brief
  15. * @{
  16. */
  17. #include <netlink-local.h>
  18. #include <netlink-tc.h>
  19. #include <netlink/netlink.h>
  20. #include <netlink/utils.h>
  21. #include <netlink/route/qdisc.h>
  22. #include <netlink/route/qdisc-modules.h>
  23. #include <netlink/route/sch/red.h>
  24. /** @cond SKIP */
  25. #define RED_ATTR_LIMIT 0x01
  26. #define RED_ATTR_QTH_MIN 0x02
  27. #define RED_ATTR_QTH_MAX 0x04
  28. #define RED_ATTR_FLAGS 0x08
  29. #define RED_ATTR_WLOG 0x10
  30. #define RED_ATTR_PLOG 0x20
  31. #define RED_ATTR_SCELL_LOG 0x40
  32. /** @endcond */
  33. static inline struct rtnl_red *red_qdisc(struct rtnl_qdisc *qdisc)
  34. {
  35. return (struct rtnl_red *) qdisc->q_subdata;
  36. }
  37. static inline struct rtnl_red *red_alloc(struct rtnl_qdisc *qdisc)
  38. {
  39. if (!qdisc->q_subdata)
  40. qdisc->q_subdata = calloc(1, sizeof(struct rtnl_red));
  41. return red_qdisc(qdisc);
  42. }
  43. static struct nla_policy red_policy[TCA_RED_MAX+1] = {
  44. [TCA_RED_PARMS] = { .minlen = sizeof(struct tc_red_qopt) },
  45. };
  46. static int red_msg_parser(struct rtnl_qdisc *qdisc)
  47. {
  48. struct nlattr *tb[TCA_RED_MAX+1];
  49. struct rtnl_red *red;
  50. struct tc_red_qopt *opts;
  51. int err;
  52. if (!(qdisc->ce_mask & TCA_ATTR_OPTS))
  53. return 0;
  54. err = tca_parse(tb, TCA_RED_MAX, (struct rtnl_tca *) qdisc, red_policy);
  55. if (err < 0)
  56. return err;
  57. if (!tb[TCA_RED_PARMS])
  58. return nl_error(EINVAL, "Missing TCA_RED_PARMS");
  59. red = red_alloc(qdisc);
  60. if (!red)
  61. return nl_errno(ENOMEM);
  62. opts = nla_data(tb[TCA_RED_PARMS]);
  63. red->qr_limit = opts->limit;
  64. red->qr_qth_min = opts->qth_min;
  65. red->qr_qth_max = opts->qth_max;
  66. red->qr_flags = opts->flags;
  67. red->qr_wlog = opts->Wlog;
  68. red->qr_plog = opts->Plog;
  69. red->qr_scell_log = opts->Scell_log;
  70. red->qr_mask = (RED_ATTR_LIMIT | RED_ATTR_QTH_MIN | RED_ATTR_QTH_MAX |
  71. RED_ATTR_FLAGS | RED_ATTR_WLOG | RED_ATTR_PLOG |
  72. RED_ATTR_SCELL_LOG);
  73. return 0;
  74. }
  75. static int red_dump_brief(struct rtnl_qdisc *qdisc, struct nl_dump_params *p,
  76. int line)
  77. {
  78. struct rtnl_red *red = red_qdisc(qdisc);
  79. if (red) {
  80. /* XXX: limit, min, max, flags */
  81. }
  82. return line;
  83. }
  84. static int red_dump_full(struct rtnl_qdisc *qdisc, struct nl_dump_params *p,
  85. int line)
  86. {
  87. struct rtnl_red *red = red_qdisc(qdisc);
  88. if (red) {
  89. /* XXX: wlog, plog, scell_log */
  90. }
  91. return line;
  92. }
  93. static int red_dump_stats(struct rtnl_qdisc *qdisc, struct nl_dump_params *p,
  94. int line)
  95. {
  96. struct rtnl_red *red = red_qdisc(qdisc);
  97. if (red) {
  98. /* XXX: xstats */
  99. }
  100. return line;
  101. }
  102. static struct nl_msg *red_get_opts(struct rtnl_qdisc *qdisc)
  103. {
  104. struct rtnl_red *red;
  105. struct nl_msg *msg;
  106. red = red_qdisc(qdisc);
  107. if (!red)
  108. return NULL;
  109. msg = nlmsg_alloc();
  110. if (!msg)
  111. goto errout;
  112. #if 0
  113. memset(&opts, 0, sizeof(opts));
  114. opts.quantum = sfq->qs_quantum;
  115. opts.perturb_period = sfq->qs_perturb;
  116. opts.limit = sfq->qs_limit;
  117. if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0)
  118. goto errout;
  119. #endif
  120. return msg;
  121. errout:
  122. nlmsg_free(msg);
  123. return NULL;
  124. }
  125. /**
  126. * @name Attribute Access
  127. * @{
  128. */
  129. /**
  130. * Set limit of RED qdisc.
  131. * @arg qdisc RED qdisc to be modified.
  132. * @arg limit New limit in number of packets.
  133. * @return 0 on success or a negative error code.
  134. */
  135. int rtnl_red_set_limit(struct rtnl_qdisc *qdisc, int limit)
  136. {
  137. struct rtnl_red *red;
  138. red = red_alloc(qdisc);
  139. if (!red)
  140. return nl_errno(ENOMEM);
  141. red->qr_limit = limit;
  142. red->qr_mask |= RED_ATTR_LIMIT;
  143. return 0;
  144. }
  145. /**
  146. * Get limit of RED qdisc.
  147. * @arg qdisc RED qdisc.
  148. * @return Limit or a negative error code.
  149. */
  150. int rtnl_red_get_limit(struct rtnl_qdisc *qdisc)
  151. {
  152. struct rtnl_red *red;
  153. red = red_qdisc(qdisc);
  154. if (red && (red->qr_mask & RED_ATTR_LIMIT))
  155. return red->qr_limit;
  156. else
  157. return nl_errno(ENOENT);
  158. }
  159. /** @} */
  160. static struct rtnl_qdisc_ops red_ops = {
  161. .qo_kind = "red",
  162. .qo_msg_parser = red_msg_parser,
  163. .qo_dump[NL_DUMP_BRIEF] = red_dump_brief,
  164. .qo_dump[NL_DUMP_FULL] = red_dump_full,
  165. .qo_dump[NL_DUMP_STATS] = red_dump_stats,
  166. .qo_get_opts = red_get_opts,
  167. };
  168. static void __init red_init(void)
  169. {
  170. rtnl_qdisc_register(&red_ops);
  171. }
  172. static void __exit red_exit(void)
  173. {
  174. rtnl_qdisc_unregister(&red_ops);
  175. }
  176. /** @} */