libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/qdisc/fifo.c
00001 /*
00002  * lib/route/qdisc/fifo.c               (p|b)fifo
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup qdisc
00014  * @defgroup qdisc_fifo Packet/Bytes FIFO (pfifo/bfifo)
00015  * @brief
00016  *
00017  * The FIFO qdisc comes in two flavours:
00018  * @par bfifo (Byte FIFO)
00019  * Allows enqueuing until the currently queued volume in bytes exceeds
00020  * the configured limit.backlog contains currently enqueued volume in bytes.
00021  *
00022  * @par pfifo (Packet FIFO)
00023  * Allows enquueing until the currently queued number of packets
00024  * exceeds the configured limit.
00025  *
00026  * The configuration is exactly the same, the decision which of
00027  * the two variations is going to be used is made based on the
00028  * kind of the qdisc (rtnl_tc_set_kind()).
00029  * @{
00030  */
00031 
00032 #include <netlink-local.h>
00033 #include <netlink-tc.h>
00034 #include <netlink/netlink.h>
00035 #include <netlink/route/tc-api.h>
00036 #include <netlink/route/qdisc.h>
00037 #include <netlink/route/qdisc/fifo.h>
00038 #include <netlink/utils.h>
00039 
00040 /** @cond SKIP */
00041 #define SCH_FIFO_ATTR_LIMIT 1
00042 /** @endcond */
00043 
00044 static int fifo_msg_parser(struct rtnl_tc *tc, void *data)
00045 {
00046         struct rtnl_fifo *fifo = data;
00047         struct tc_fifo_qopt *opt;
00048 
00049         if (tc->tc_opts->d_size < sizeof(struct tc_fifo_qopt))
00050                 return -NLE_INVAL;
00051 
00052         opt = (struct tc_fifo_qopt *) tc->tc_opts->d_data;
00053         fifo->qf_limit = opt->limit;
00054         fifo->qf_mask = SCH_FIFO_ATTR_LIMIT;
00055 
00056         return 0;
00057 }
00058 
00059 static void pfifo_dump_line(struct rtnl_tc *tc, void *data,
00060                             struct nl_dump_params *p)
00061 {
00062         struct rtnl_fifo *fifo = data;
00063 
00064         if (fifo)
00065                 nl_dump(p, " limit %u packets", fifo->qf_limit);
00066 }
00067 
00068 static void bfifo_dump_line(struct rtnl_tc *tc, void *data,
00069                             struct nl_dump_params *p)
00070 {
00071         struct rtnl_fifo *fifo = data;
00072         char *unit;
00073         double r;
00074 
00075         if (!fifo)
00076                 return;
00077 
00078         r = nl_cancel_down_bytes(fifo->qf_limit, &unit);
00079         nl_dump(p, " limit %.1f%s", r, unit);
00080 }
00081 
00082 static int fifo_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
00083 {
00084         struct rtnl_fifo *fifo = data;
00085         struct tc_fifo_qopt opts = {0};
00086 
00087         if (!fifo || !(fifo->qf_mask & SCH_FIFO_ATTR_LIMIT))
00088                 return -NLE_INVAL;
00089 
00090         opts.limit = fifo->qf_limit;
00091 
00092         return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
00093 }
00094 
00095 /**
00096  * @name Attribute Modification
00097  * @{
00098  */
00099 
00100 /**
00101  * Set limit of FIFO qdisc.
00102  * @arg qdisc           FIFO qdisc to be modified.
00103  * @arg limit           New limit.
00104  * @return 0 on success or a negative error code.
00105  */
00106 int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *qdisc, int limit)
00107 {
00108         struct rtnl_fifo *fifo;
00109         
00110         if (!(fifo = rtnl_tc_data(TC_CAST(qdisc))))
00111                 return -NLE_NOMEM;
00112                 
00113         fifo->qf_limit = limit;
00114         fifo->qf_mask |= SCH_FIFO_ATTR_LIMIT;
00115 
00116         return 0;
00117 }
00118 
00119 /**
00120  * Get limit of a FIFO qdisc.
00121  * @arg qdisc           FIFO qdisc.
00122  * @return Numeric limit or a negative error code.
00123  */
00124 int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc)
00125 {
00126         struct rtnl_fifo *fifo;
00127         
00128         if (!(fifo = rtnl_tc_data(TC_CAST(qdisc))))
00129                 return -NLE_NOMEM;
00130         
00131         if (fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)
00132                 return fifo->qf_limit;
00133         else
00134                 return -NLE_NOATTR;
00135 }
00136 
00137 /** @} */
00138 
00139 static struct rtnl_tc_ops pfifo_ops = {
00140         .to_kind                = "pfifo",
00141         .to_type                = RTNL_TC_TYPE_QDISC,
00142         .to_size                = sizeof(struct rtnl_fifo),
00143         .to_msg_parser          = fifo_msg_parser,
00144         .to_dump[NL_DUMP_LINE]  = pfifo_dump_line,
00145         .to_msg_fill            = fifo_msg_fill,
00146 };
00147 
00148 static struct rtnl_tc_ops bfifo_ops = {
00149         .to_kind                = "bfifo",
00150         .to_type                = RTNL_TC_TYPE_QDISC,
00151         .to_size                = sizeof(struct rtnl_fifo),
00152         .to_msg_parser          = fifo_msg_parser,
00153         .to_dump[NL_DUMP_LINE]  = bfifo_dump_line,
00154         .to_msg_fill            = fifo_msg_fill,
00155 };
00156 
00157 static void __init fifo_init(void)
00158 {
00159         rtnl_tc_register(&pfifo_ops);
00160         rtnl_tc_register(&bfifo_ops);
00161 }
00162 
00163 static void __exit fifo_exit(void)
00164 {
00165         rtnl_tc_unregister(&pfifo_ops);
00166         rtnl_tc_unregister(&bfifo_ops);
00167 }
00168 
00169 /** @} */