xref: /aosp_15_r20/external/libnl/lib/route/qdisc/plug.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2012 Shriram Rajagopalan <[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_plug Plug/Unplug Traffic (PLUG)
9*4dc78e53SAndroid Build Coastguard Worker  * @brief
10*4dc78e53SAndroid Build Coastguard Worker  *
11*4dc78e53SAndroid Build Coastguard Worker  * Queue traffic until an explicit release command.
12*4dc78e53SAndroid Build Coastguard Worker  *
13*4dc78e53SAndroid Build Coastguard Worker  * There are two ways to use this qdisc:
14*4dc78e53SAndroid Build Coastguard Worker  * 1. A simple "instantaneous" plug/unplug operation, by issuing an alternating
15*4dc78e53SAndroid Build Coastguard Worker  *    sequence of TCQ_PLUG_BUFFER & TCQ_PLUG_RELEASE_INDEFINITE commands.
16*4dc78e53SAndroid Build Coastguard Worker  *
17*4dc78e53SAndroid Build Coastguard Worker  * 2. For network output buffering (a.k.a output commit) functionality.
18*4dc78e53SAndroid Build Coastguard Worker  *    Output commit property is commonly used by applications using checkpoint
19*4dc78e53SAndroid Build Coastguard Worker  *    based fault-tolerance to ensure that the checkpoint from which a system
20*4dc78e53SAndroid Build Coastguard Worker  *    is being restored is consistent w.r.t outside world.
21*4dc78e53SAndroid Build Coastguard Worker  *
22*4dc78e53SAndroid Build Coastguard Worker  *    Consider for e.g. Remus - a Virtual Machine checkpointing system,
23*4dc78e53SAndroid Build Coastguard Worker  *    wherein a VM is checkpointed, say every 50ms. The checkpoint is replicated
24*4dc78e53SAndroid Build Coastguard Worker  *    asynchronously to the backup host, while the VM continues executing the
25*4dc78e53SAndroid Build Coastguard Worker  *    next epoch speculatively.
26*4dc78e53SAndroid Build Coastguard Worker  *
27*4dc78e53SAndroid Build Coastguard Worker  *    The following is a typical sequence of output buffer operations:
28*4dc78e53SAndroid Build Coastguard Worker  *       1.At epoch i, start_buffer(i)
29*4dc78e53SAndroid Build Coastguard Worker  *       2. At end of epoch i (i.e. after 50ms):
30*4dc78e53SAndroid Build Coastguard Worker  *          2.1 Stop VM and take checkpoint(i).
31*4dc78e53SAndroid Build Coastguard Worker  *          2.2 start_buffer(i+1) and Resume VM
32*4dc78e53SAndroid Build Coastguard Worker  *       3. While speculatively executing epoch(i+1), asynchronously replicate
33*4dc78e53SAndroid Build Coastguard Worker  *          checkpoint(i) to backup host.
34*4dc78e53SAndroid Build Coastguard Worker  *       4. When checkpoint_ack(i) is received from backup, release_buffer(i)
35*4dc78e53SAndroid Build Coastguard Worker  *    Thus, this Qdisc would receive the following sequence of commands:
36*4dc78e53SAndroid Build Coastguard Worker  *       TCQ_PLUG_BUFFER (epoch i)
37*4dc78e53SAndroid Build Coastguard Worker  *       .. TCQ_PLUG_BUFFER (epoch i+1)
38*4dc78e53SAndroid Build Coastguard Worker  *       ....TCQ_PLUG_RELEASE_ONE (epoch i)
39*4dc78e53SAndroid Build Coastguard Worker  *       ......TCQ_PLUG_BUFFER (epoch i+2)
40*4dc78e53SAndroid Build Coastguard Worker  *       ........
41*4dc78e53SAndroid Build Coastguard Worker  *
42*4dc78e53SAndroid Build Coastguard Worker  *
43*4dc78e53SAndroid Build Coastguard Worker  * State of the queue, when used for network output buffering:
44*4dc78e53SAndroid Build Coastguard Worker  *
45*4dc78e53SAndroid Build Coastguard Worker  *                 plug(i+1)            plug(i)          head
46*4dc78e53SAndroid Build Coastguard Worker  * ------------------+--------------------+---------------->
47*4dc78e53SAndroid Build Coastguard Worker  *                   |                    |
48*4dc78e53SAndroid Build Coastguard Worker  *                   |                    |
49*4dc78e53SAndroid Build Coastguard Worker  * pkts_current_epoch| pkts_last_epoch    |pkts_to_release
50*4dc78e53SAndroid Build Coastguard Worker  * ----------------->|<--------+--------->|+--------------->
51*4dc78e53SAndroid Build Coastguard Worker  *                   v                    v
52*4dc78e53SAndroid Build Coastguard Worker  *
53*4dc78e53SAndroid Build Coastguard Worker  *
54*4dc78e53SAndroid Build Coastguard Worker  * @{
55*4dc78e53SAndroid Build Coastguard Worker  */
56*4dc78e53SAndroid Build Coastguard Worker 
57*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
58*4dc78e53SAndroid Build Coastguard Worker 
59*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
60*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
61*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/qdisc/plug.h>
62*4dc78e53SAndroid Build Coastguard Worker 
63*4dc78e53SAndroid Build Coastguard Worker #include "tc-api.h"
64*4dc78e53SAndroid Build Coastguard Worker 
65*4dc78e53SAndroid Build Coastguard Worker struct rtnl_plug {
66*4dc78e53SAndroid Build Coastguard Worker 	int action;
67*4dc78e53SAndroid Build Coastguard Worker 	uint32_t limit;
68*4dc78e53SAndroid Build Coastguard Worker };
69*4dc78e53SAndroid Build Coastguard Worker 
plug_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)70*4dc78e53SAndroid Build Coastguard Worker static int plug_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
71*4dc78e53SAndroid Build Coastguard Worker {
72*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_plug *plug = data;
73*4dc78e53SAndroid Build Coastguard Worker 	struct tc_plug_qopt opts;
74*4dc78e53SAndroid Build Coastguard Worker 
75*4dc78e53SAndroid Build Coastguard Worker 	if (!plug)
76*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
77*4dc78e53SAndroid Build Coastguard Worker 
78*4dc78e53SAndroid Build Coastguard Worker 	opts.action = plug->action;
79*4dc78e53SAndroid Build Coastguard Worker 	opts.limit  = plug->limit;
80*4dc78e53SAndroid Build Coastguard Worker 
81*4dc78e53SAndroid Build Coastguard Worker 	return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
82*4dc78e53SAndroid Build Coastguard Worker }
83*4dc78e53SAndroid Build Coastguard Worker 
84*4dc78e53SAndroid Build Coastguard Worker /**
85*4dc78e53SAndroid Build Coastguard Worker  * @name Attribute Modification
86*4dc78e53SAndroid Build Coastguard Worker  * @{
87*4dc78e53SAndroid Build Coastguard Worker  */
88*4dc78e53SAndroid Build Coastguard Worker 
89*4dc78e53SAndroid Build Coastguard Worker /**
90*4dc78e53SAndroid Build Coastguard Worker  * Insert a plug into the qdisc and buffer any incoming
91*4dc78e53SAndroid Build Coastguard Worker  * network traffic.
92*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		PLUG qdisc to be modified.
93*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_plug_buffer(struct rtnl_qdisc * qdisc)94*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_plug_buffer(struct rtnl_qdisc *qdisc)
95*4dc78e53SAndroid Build Coastguard Worker {
96*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_plug *plug;
97*4dc78e53SAndroid Build Coastguard Worker 
98*4dc78e53SAndroid Build Coastguard Worker 	if (!(plug = rtnl_tc_data(TC_CAST(qdisc))))
99*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
100*4dc78e53SAndroid Build Coastguard Worker 
101*4dc78e53SAndroid Build Coastguard Worker 	plug->action = TCQ_PLUG_BUFFER;
102*4dc78e53SAndroid Build Coastguard Worker 	return 0;
103*4dc78e53SAndroid Build Coastguard Worker }
104*4dc78e53SAndroid Build Coastguard Worker 
105*4dc78e53SAndroid Build Coastguard Worker /**
106*4dc78e53SAndroid Build Coastguard Worker  * Unplug the qdisc, releasing packets from queue head
107*4dc78e53SAndroid Build Coastguard Worker  * to the last complete buffer, while new traffic
108*4dc78e53SAndroid Build Coastguard Worker  * continues to be buffered.
109*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		PLUG qdisc to be modified.
110*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_plug_release_one(struct rtnl_qdisc * qdisc)111*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_plug_release_one(struct rtnl_qdisc *qdisc)
112*4dc78e53SAndroid Build Coastguard Worker {
113*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_plug *plug;
114*4dc78e53SAndroid Build Coastguard Worker 
115*4dc78e53SAndroid Build Coastguard Worker 	if (!(plug = rtnl_tc_data(TC_CAST(qdisc))))
116*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
117*4dc78e53SAndroid Build Coastguard Worker 
118*4dc78e53SAndroid Build Coastguard Worker 	plug->action = TCQ_PLUG_RELEASE_ONE;
119*4dc78e53SAndroid Build Coastguard Worker 	return 0;
120*4dc78e53SAndroid Build Coastguard Worker }
121*4dc78e53SAndroid Build Coastguard Worker 
122*4dc78e53SAndroid Build Coastguard Worker /**
123*4dc78e53SAndroid Build Coastguard Worker  * Indefinitely unplug the qdisc, releasing all packets.
124*4dc78e53SAndroid Build Coastguard Worker  * Network traffic will not be buffered until the next
125*4dc78e53SAndroid Build Coastguard Worker  * buffer command is issued.
126*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		PLUG qdisc to be modified.
127*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_plug_release_indefinite(struct rtnl_qdisc * qdisc)128*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_plug_release_indefinite(struct rtnl_qdisc *qdisc)
129*4dc78e53SAndroid Build Coastguard Worker {
130*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_plug *plug;
131*4dc78e53SAndroid Build Coastguard Worker 
132*4dc78e53SAndroid Build Coastguard Worker 	if (!(plug = rtnl_tc_data(TC_CAST(qdisc))))
133*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
134*4dc78e53SAndroid Build Coastguard Worker 
135*4dc78e53SAndroid Build Coastguard Worker 	plug->action = TCQ_PLUG_RELEASE_INDEFINITE;
136*4dc78e53SAndroid Build Coastguard Worker 	return 0;
137*4dc78e53SAndroid Build Coastguard Worker }
138*4dc78e53SAndroid Build Coastguard Worker 
139*4dc78e53SAndroid Build Coastguard Worker /**
140*4dc78e53SAndroid Build Coastguard Worker  * Set limit of PLUG qdisc.
141*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		PLUG qdisc to be modified.
142*4dc78e53SAndroid Build Coastguard Worker  * @arg limit		New limit.
143*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
144*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_plug_set_limit(struct rtnl_qdisc * qdisc,int limit)145*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_plug_set_limit(struct rtnl_qdisc *qdisc, int limit)
146*4dc78e53SAndroid Build Coastguard Worker {
147*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_plug *plug;
148*4dc78e53SAndroid Build Coastguard Worker 
149*4dc78e53SAndroid Build Coastguard Worker 	if (!(plug = rtnl_tc_data(TC_CAST(qdisc))))
150*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
151*4dc78e53SAndroid Build Coastguard Worker 
152*4dc78e53SAndroid Build Coastguard Worker 	plug->action = TCQ_PLUG_LIMIT;
153*4dc78e53SAndroid Build Coastguard Worker 	plug->limit  = limit;
154*4dc78e53SAndroid Build Coastguard Worker 
155*4dc78e53SAndroid Build Coastguard Worker 	return 0;
156*4dc78e53SAndroid Build Coastguard Worker }
157*4dc78e53SAndroid Build Coastguard Worker 
158*4dc78e53SAndroid Build Coastguard Worker /** @} */
159*4dc78e53SAndroid Build Coastguard Worker 
160*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops plug_ops = {
161*4dc78e53SAndroid Build Coastguard Worker 	.to_kind		= "plug",
162*4dc78e53SAndroid Build Coastguard Worker 	.to_type		= RTNL_TC_TYPE_QDISC,
163*4dc78e53SAndroid Build Coastguard Worker 	.to_size		= sizeof(struct rtnl_plug),
164*4dc78e53SAndroid Build Coastguard Worker 	.to_msg_fill		= plug_msg_fill,
165*4dc78e53SAndroid Build Coastguard Worker };
166*4dc78e53SAndroid Build Coastguard Worker 
plug_init(void)167*4dc78e53SAndroid Build Coastguard Worker static void _nl_init plug_init(void)
168*4dc78e53SAndroid Build Coastguard Worker {
169*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_register(&plug_ops);
170*4dc78e53SAndroid Build Coastguard Worker }
171*4dc78e53SAndroid Build Coastguard Worker 
plug_exit(void)172*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit plug_exit(void)
173*4dc78e53SAndroid Build Coastguard Worker {
174*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_unregister(&plug_ops);
175*4dc78e53SAndroid Build Coastguard Worker }
176*4dc78e53SAndroid Build Coastguard Worker 
177*4dc78e53SAndroid Build Coastguard Worker /** @} */
178