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