fifo.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * lib/route/sch/fifo.c (p|b)fifo
  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 fifo Packet/Bytes FIFO (pfifo/bfifo)
  14. * @brief
  15. *
  16. * The FIFO qdisc comes in two flavours:
  17. * @par bfifo (Byte FIFO)
  18. * Allows enqueuing until the currently queued volume in bytes exceeds
  19. * the configured limit.backlog contains currently enqueued volume in bytes.
  20. *
  21. * @par pfifo (Packet FIFO)
  22. * Allows enquueing until the currently queued number of packets
  23. * exceeds the configured limit.
  24. *
  25. * The configuration is exactly the same, the decision which of
  26. * the two variations is going to be used is made based on the
  27. * kind of the qdisc (rtnl_qdisc_set_kind()).
  28. * @{
  29. */
  30. #include <netlink-local.h>
  31. #include <netlink-tc.h>
  32. #include <netlink/netlink.h>
  33. #include <netlink/route/qdisc.h>
  34. #include <netlink/route/qdisc-modules.h>
  35. #include <netlink/route/sch/fifo.h>
  36. #include <netlink/utils.h>
  37. /** @cond SKIP */
  38. #define SCH_FIFO_ATTR_LIMIT 1
  39. /** @endcond */
  40. static inline struct rtnl_fifo *fifo_qdisc(struct rtnl_qdisc *qdisc)
  41. {
  42. return (struct rtnl_fifo *) qdisc->q_subdata;
  43. }
  44. static inline struct rtnl_fifo *fifo_alloc(struct rtnl_qdisc *qdisc)
  45. {
  46. if (!qdisc->q_subdata)
  47. qdisc->q_subdata = calloc(1, sizeof(struct rtnl_fifo));
  48. return fifo_qdisc(qdisc);
  49. }
  50. static int fifo_msg_parser(struct rtnl_qdisc *qdisc)
  51. {
  52. struct rtnl_fifo *fifo;
  53. struct tc_fifo_qopt *opt;
  54. if (qdisc->q_opts->d_size < sizeof(struct tc_fifo_qopt))
  55. return nl_error(EINVAL, "FIFO options size mismatch");
  56. fifo = fifo_alloc(qdisc);
  57. if (!fifo)
  58. return nl_errno(ENOMEM);
  59. opt = (struct tc_fifo_qopt *) qdisc->q_opts->d_data;
  60. fifo->qf_limit = opt->limit;
  61. fifo->qf_mask = SCH_FIFO_ATTR_LIMIT;
  62. return 0;
  63. }
  64. static void fifo_free_data(struct rtnl_qdisc *qdisc)
  65. {
  66. free(qdisc->q_subdata);
  67. }
  68. static int pfifo_dump_brief(struct rtnl_qdisc *qdisc,
  69. struct nl_dump_params *p, int line)
  70. {
  71. struct rtnl_fifo *fifo = fifo_qdisc(qdisc);
  72. if (fifo)
  73. dp_dump(p, " limit %u packets", fifo->qf_limit);
  74. return line;
  75. }
  76. static int bfifo_dump_brief(struct rtnl_qdisc *qdisc,
  77. struct nl_dump_params *p, int line)
  78. {
  79. struct rtnl_fifo *fifo = fifo_qdisc(qdisc);
  80. if (fifo) {
  81. char *unit;
  82. double r;
  83. r = nl_cancel_down_bytes(fifo->qf_limit, &unit);
  84. dp_dump(p, " limit %.1f%s", r, unit);
  85. }
  86. return line;
  87. }
  88. static struct nl_msg *fifo_get_opts(struct rtnl_qdisc *qdisc)
  89. {
  90. struct rtnl_fifo *fifo;
  91. struct tc_fifo_qopt opts;
  92. struct nl_msg *msg;
  93. fifo = fifo_qdisc(qdisc);
  94. if (!fifo || !(fifo->qf_mask & SCH_FIFO_ATTR_LIMIT))
  95. return NULL;
  96. msg = nlmsg_alloc();
  97. if (!msg)
  98. goto errout;
  99. memset(&opts, 0, sizeof(opts));
  100. opts.limit = fifo->qf_limit;
  101. if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0)
  102. goto errout;
  103. return msg;
  104. errout:
  105. nlmsg_free(msg);
  106. return NULL;
  107. }
  108. /**
  109. * @name Attribute Modification
  110. * @{
  111. */
  112. /**
  113. * Set limit of FIFO qdisc.
  114. * @arg qdisc FIFO qdisc to be modified.
  115. * @arg limit New limit.
  116. * @return 0 on success or a negative error code.
  117. */
  118. int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *qdisc, int limit)
  119. {
  120. struct rtnl_fifo *fifo;
  121. fifo = fifo_alloc(qdisc);
  122. if (!fifo)
  123. return nl_errno(ENOMEM);
  124. fifo->qf_limit = limit;
  125. fifo->qf_mask |= SCH_FIFO_ATTR_LIMIT;
  126. return 0;
  127. }
  128. /**
  129. * Get limit of a FIFO qdisc.
  130. * @arg qdisc FIFO qdisc.
  131. * @return Numeric limit or a negative error code.
  132. */
  133. int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc)
  134. {
  135. struct rtnl_fifo *fifo;
  136. fifo = fifo_qdisc(qdisc);
  137. if (fifo && fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)
  138. return fifo->qf_limit;
  139. else
  140. return nl_errno(ENOMEM);
  141. }
  142. /** @} */
  143. static struct rtnl_qdisc_ops pfifo_ops = {
  144. .qo_kind = "pfifo",
  145. .qo_msg_parser = fifo_msg_parser,
  146. .qo_free_data = fifo_free_data,
  147. .qo_dump[NL_DUMP_BRIEF] = pfifo_dump_brief,
  148. .qo_get_opts = fifo_get_opts,
  149. };
  150. static struct rtnl_qdisc_ops bfifo_ops = {
  151. .qo_kind = "bfifo",
  152. .qo_msg_parser = fifo_msg_parser,
  153. .qo_free_data = fifo_free_data,
  154. .qo_dump[NL_DUMP_BRIEF] = bfifo_dump_brief,
  155. .qo_get_opts = fifo_get_opts,
  156. };
  157. static void __init fifo_init(void)
  158. {
  159. rtnl_qdisc_register(&pfifo_ops);
  160. rtnl_qdisc_register(&bfifo_ops);
  161. }
  162. static void __exit fifo_exit(void)
  163. {
  164. rtnl_qdisc_unregister(&pfifo_ops);
  165. rtnl_qdisc_unregister(&bfifo_ops);
  166. }
  167. /** @} */