Home | History | Annotate | Download | only in qdisc
      1 /*
      2  * lib/route/qdisc/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-2011 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup qdisc
     14  * @defgroup qdisc_fifo Packet/Bytes FIFO (pfifo/bfifo)
     15  * @brief
     16  *
     17  * The FIFO qdisc comes in two flavours:
     18  * @par bfifo (Byte FIFO)
     19  * Allows enqueuing until the currently queued volume in bytes exceeds
     20  * the configured limit.backlog contains currently enqueued volume in bytes.
     21  *
     22  * @par pfifo (Packet FIFO)
     23  * Allows enquueing until the currently queued number of packets
     24  * exceeds the configured limit.
     25  *
     26  * The configuration is exactly the same, the decision which of
     27  * the two variations is going to be used is made based on the
     28  * kind of the qdisc (rtnl_tc_set_kind()).
     29  * @{
     30  */
     31 
     32 #include <netlink-private/netlink.h>
     33 #include <netlink-private/tc.h>
     34 #include <netlink/netlink.h>
     35 #include <netlink-private/route/tc-api.h>
     36 #include <netlink/route/qdisc.h>
     37 #include <netlink/route/qdisc/fifo.h>
     38 #include <netlink/utils.h>
     39 
     40 /** @cond SKIP */
     41 #define SCH_FIFO_ATTR_LIMIT 1
     42 /** @endcond */
     43 
     44 static int fifo_msg_parser(struct rtnl_tc *tc, void *data)
     45 {
     46 	struct rtnl_fifo *fifo = data;
     47 	struct tc_fifo_qopt *opt;
     48 
     49 	if (tc->tc_opts->d_size < sizeof(struct tc_fifo_qopt))
     50 		return -NLE_INVAL;
     51 
     52 	opt = (struct tc_fifo_qopt *) tc->tc_opts->d_data;
     53 	fifo->qf_limit = opt->limit;
     54 	fifo->qf_mask = SCH_FIFO_ATTR_LIMIT;
     55 
     56 	return 0;
     57 }
     58 
     59 static void pfifo_dump_line(struct rtnl_tc *tc, void *data,
     60 			    struct nl_dump_params *p)
     61 {
     62 	struct rtnl_fifo *fifo = data;
     63 
     64 	if (fifo)
     65 		nl_dump(p, " limit %u packets", fifo->qf_limit);
     66 }
     67 
     68 static void bfifo_dump_line(struct rtnl_tc *tc, void *data,
     69 			    struct nl_dump_params *p)
     70 {
     71 	struct rtnl_fifo *fifo = data;
     72 	char *unit;
     73 	double r;
     74 
     75 	if (!fifo)
     76 		return;
     77 
     78 	r = nl_cancel_down_bytes(fifo->qf_limit, &unit);
     79 	nl_dump(p, " limit %.1f%s", r, unit);
     80 }
     81 
     82 static int fifo_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
     83 {
     84 	struct rtnl_fifo *fifo = data;
     85 	struct tc_fifo_qopt opts = {0};
     86 
     87 	if (!fifo || !(fifo->qf_mask & SCH_FIFO_ATTR_LIMIT))
     88 		return -NLE_INVAL;
     89 
     90 	opts.limit = fifo->qf_limit;
     91 
     92 	return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
     93 }
     94 
     95 /**
     96  * @name Attribute Modification
     97  * @{
     98  */
     99 
    100 /**
    101  * Set limit of FIFO qdisc.
    102  * @arg qdisc		FIFO qdisc to be modified.
    103  * @arg limit		New limit.
    104  * @return 0 on success or a negative error code.
    105  */
    106 int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *qdisc, int limit)
    107 {
    108 	struct rtnl_fifo *fifo;
    109 
    110 	if (!(fifo = rtnl_tc_data(TC_CAST(qdisc))))
    111 		return -NLE_NOMEM;
    112 
    113 	fifo->qf_limit = limit;
    114 	fifo->qf_mask |= SCH_FIFO_ATTR_LIMIT;
    115 
    116 	return 0;
    117 }
    118 
    119 /**
    120  * Get limit of a FIFO qdisc.
    121  * @arg qdisc		FIFO qdisc.
    122  * @return Numeric limit or a negative error code.
    123  */
    124 int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc)
    125 {
    126 	struct rtnl_fifo *fifo;
    127 
    128 	if (!(fifo = rtnl_tc_data(TC_CAST(qdisc))))
    129 		return -NLE_NOMEM;
    130 
    131 	if (fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)
    132 		return fifo->qf_limit;
    133 	else
    134 		return -NLE_NOATTR;
    135 }
    136 
    137 /** @} */
    138 
    139 static struct rtnl_tc_ops pfifo_ops = {
    140 	.to_kind		= "pfifo",
    141 	.to_type		= RTNL_TC_TYPE_QDISC,
    142 	.to_size		= sizeof(struct rtnl_fifo),
    143 	.to_msg_parser		= fifo_msg_parser,
    144 	.to_dump[NL_DUMP_LINE]	= pfifo_dump_line,
    145 	.to_msg_fill		= fifo_msg_fill,
    146 };
    147 
    148 static struct rtnl_tc_ops bfifo_ops = {
    149 	.to_kind		= "bfifo",
    150 	.to_type		= RTNL_TC_TYPE_QDISC,
    151 	.to_size		= sizeof(struct rtnl_fifo),
    152 	.to_msg_parser		= fifo_msg_parser,
    153 	.to_dump[NL_DUMP_LINE]	= bfifo_dump_line,
    154 	.to_msg_fill		= fifo_msg_fill,
    155 };
    156 
    157 static void __init fifo_init(void)
    158 {
    159 	rtnl_tc_register(&pfifo_ops);
    160 	rtnl_tc_register(&bfifo_ops);
    161 }
    162 
    163 static void __exit fifo_exit(void)
    164 {
    165 	rtnl_tc_unregister(&pfifo_ops);
    166 	rtnl_tc_unregister(&bfifo_ops);
    167 }
    168 
    169 /** @} */
    170