xref: /aosp_15_r20/external/libnl/lib/route/qdisc.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) 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 tc
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup qdisc Queueing Disciplines
9*4dc78e53SAndroid Build Coastguard Worker  * @{
10*4dc78e53SAndroid Build Coastguard Worker  */
11*4dc78e53SAndroid Build Coastguard Worker 
12*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
13*4dc78e53SAndroid Build Coastguard Worker 
14*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
15*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
16*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
17*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/qdisc.h>
18*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/class.h>
19*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/classifier.h>
20*4dc78e53SAndroid Build Coastguard Worker 
21*4dc78e53SAndroid Build Coastguard Worker #include "tc-api.h"
22*4dc78e53SAndroid Build Coastguard Worker 
23*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_qdisc_ops;
24*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops qdisc_obj_ops;
25*4dc78e53SAndroid Build Coastguard Worker 
qdisc_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * n,struct nl_parser_param * pp)26*4dc78e53SAndroid Build Coastguard Worker static int qdisc_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
27*4dc78e53SAndroid Build Coastguard Worker 			    struct nlmsghdr *n, struct nl_parser_param *pp)
28*4dc78e53SAndroid Build Coastguard Worker {
29*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_qdisc *qdisc;
30*4dc78e53SAndroid Build Coastguard Worker 	int err;
31*4dc78e53SAndroid Build Coastguard Worker 
32*4dc78e53SAndroid Build Coastguard Worker 	if (!(qdisc = rtnl_qdisc_alloc()))
33*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
34*4dc78e53SAndroid Build Coastguard Worker 
35*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_tc_msg_parse(n, TC_CAST(qdisc))) < 0)
36*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
37*4dc78e53SAndroid Build Coastguard Worker 
38*4dc78e53SAndroid Build Coastguard Worker 	err = pp->pp_cb(OBJ_CAST(qdisc), pp);
39*4dc78e53SAndroid Build Coastguard Worker errout:
40*4dc78e53SAndroid Build Coastguard Worker 	rtnl_qdisc_put(qdisc);
41*4dc78e53SAndroid Build Coastguard Worker 
42*4dc78e53SAndroid Build Coastguard Worker 	return err;
43*4dc78e53SAndroid Build Coastguard Worker }
44*4dc78e53SAndroid Build Coastguard Worker 
qdisc_request_update(struct nl_cache * c,struct nl_sock * sk)45*4dc78e53SAndroid Build Coastguard Worker static int qdisc_request_update(struct nl_cache *c, struct nl_sock *sk)
46*4dc78e53SAndroid Build Coastguard Worker {
47*4dc78e53SAndroid Build Coastguard Worker 	struct tcmsg tchdr = {
48*4dc78e53SAndroid Build Coastguard Worker 		.tcm_family = AF_UNSPEC,
49*4dc78e53SAndroid Build Coastguard Worker 		.tcm_ifindex = c->c_iarg1,
50*4dc78e53SAndroid Build Coastguard Worker 	};
51*4dc78e53SAndroid Build Coastguard Worker 
52*4dc78e53SAndroid Build Coastguard Worker 	return nl_send_simple(sk, RTM_GETQDISC, NLM_F_DUMP, &tchdr,
53*4dc78e53SAndroid Build Coastguard Worker 			      sizeof(tchdr));
54*4dc78e53SAndroid Build Coastguard Worker }
55*4dc78e53SAndroid Build Coastguard Worker 
56*4dc78e53SAndroid Build Coastguard Worker /**
57*4dc78e53SAndroid Build Coastguard Worker  * @name Allocation/Freeing
58*4dc78e53SAndroid Build Coastguard Worker  * @{
59*4dc78e53SAndroid Build Coastguard Worker  */
60*4dc78e53SAndroid Build Coastguard Worker 
rtnl_qdisc_alloc(void)61*4dc78e53SAndroid Build Coastguard Worker struct rtnl_qdisc *rtnl_qdisc_alloc(void)
62*4dc78e53SAndroid Build Coastguard Worker {
63*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_tc *tc;
64*4dc78e53SAndroid Build Coastguard Worker 
65*4dc78e53SAndroid Build Coastguard Worker 	tc = TC_CAST(nl_object_alloc(&qdisc_obj_ops));
66*4dc78e53SAndroid Build Coastguard Worker 	if (tc)
67*4dc78e53SAndroid Build Coastguard Worker 		tc->tc_type = RTNL_TC_TYPE_QDISC;
68*4dc78e53SAndroid Build Coastguard Worker 
69*4dc78e53SAndroid Build Coastguard Worker 	return (struct rtnl_qdisc *) tc;
70*4dc78e53SAndroid Build Coastguard Worker }
71*4dc78e53SAndroid Build Coastguard Worker 
rtnl_qdisc_put(struct rtnl_qdisc * qdisc)72*4dc78e53SAndroid Build Coastguard Worker void rtnl_qdisc_put(struct rtnl_qdisc *qdisc)
73*4dc78e53SAndroid Build Coastguard Worker {
74*4dc78e53SAndroid Build Coastguard Worker 	nl_object_put((struct nl_object *) qdisc);
75*4dc78e53SAndroid Build Coastguard Worker }
76*4dc78e53SAndroid Build Coastguard Worker 
77*4dc78e53SAndroid Build Coastguard Worker /** @} */
78*4dc78e53SAndroid Build Coastguard Worker 
79*4dc78e53SAndroid Build Coastguard Worker /**
80*4dc78e53SAndroid Build Coastguard Worker  * @name Addition / Modification / Deletion
81*4dc78e53SAndroid Build Coastguard Worker  * @{
82*4dc78e53SAndroid Build Coastguard Worker  */
83*4dc78e53SAndroid Build Coastguard Worker 
build_qdisc_msg(struct rtnl_qdisc * qdisc,int type,int flags,struct nl_msg ** result)84*4dc78e53SAndroid Build Coastguard Worker static int build_qdisc_msg(struct rtnl_qdisc *qdisc, int type, int flags,
85*4dc78e53SAndroid Build Coastguard Worker 			   struct nl_msg **result)
86*4dc78e53SAndroid Build Coastguard Worker {
87*4dc78e53SAndroid Build Coastguard Worker 	if (!(qdisc->ce_mask & TCA_ATTR_IFINDEX)) {
88*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("ifindex must be specified");
89*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
90*4dc78e53SAndroid Build Coastguard Worker 	}
91*4dc78e53SAndroid Build Coastguard Worker 
92*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_tc_msg_build(TC_CAST(qdisc), type, flags, result);
93*4dc78e53SAndroid Build Coastguard Worker }
94*4dc78e53SAndroid Build Coastguard Worker 
95*4dc78e53SAndroid Build Coastguard Worker /**
96*4dc78e53SAndroid Build Coastguard Worker  * Build a netlink message requesting the addition of a qdisc
97*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		Qdisc to add
98*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Additional netlink message flags
99*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting netlink message
100*4dc78e53SAndroid Build Coastguard Worker  *
101*4dc78e53SAndroid Build Coastguard Worker  * The behaviour of this function is identical to rtnl_qdisc_add() with
102*4dc78e53SAndroid Build Coastguard Worker  * the exception that it will not send the message but return it int the
103*4dc78e53SAndroid Build Coastguard Worker  * provided return pointer instead.
104*4dc78e53SAndroid Build Coastguard Worker  *
105*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_qdisc_add()
106*4dc78e53SAndroid Build Coastguard Worker  *
107*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
108*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_build_add_request(struct rtnl_qdisc * qdisc,int flags,struct nl_msg ** result)109*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_build_add_request(struct rtnl_qdisc *qdisc, int flags,
110*4dc78e53SAndroid Build Coastguard Worker 				 struct nl_msg **result)
111*4dc78e53SAndroid Build Coastguard Worker {
112*4dc78e53SAndroid Build Coastguard Worker 	if (!(qdisc->ce_mask & (TCA_ATTR_HANDLE | TCA_ATTR_PARENT))) {
113*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("handle or parent must be specified");
114*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
115*4dc78e53SAndroid Build Coastguard Worker 	}
116*4dc78e53SAndroid Build Coastguard Worker 
117*4dc78e53SAndroid Build Coastguard Worker 	return build_qdisc_msg(qdisc, RTM_NEWQDISC, flags, result);
118*4dc78e53SAndroid Build Coastguard Worker }
119*4dc78e53SAndroid Build Coastguard Worker 
120*4dc78e53SAndroid Build Coastguard Worker /**
121*4dc78e53SAndroid Build Coastguard Worker  * Add qdisc
122*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
123*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		Qdisc to add
124*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Additional netlink message flags
125*4dc78e53SAndroid Build Coastguard Worker  *
126*4dc78e53SAndroid Build Coastguard Worker  * Builds a \c RTM_NEWQDISC netlink message requesting the addition
127*4dc78e53SAndroid Build Coastguard Worker  * of a new qdisc and sends the message to the kernel. The configuration
128*4dc78e53SAndroid Build Coastguard Worker  * of the qdisc is derived from the attributes of the specified qdisc.
129*4dc78e53SAndroid Build Coastguard Worker  *
130*4dc78e53SAndroid Build Coastguard Worker  * The following flags may be specified:
131*4dc78e53SAndroid Build Coastguard Worker  *  - \c NLM_F_CREATE:  Create qdisc if it does not exist, otherwise
132*4dc78e53SAndroid Build Coastguard Worker  *                      -NLE_OBJ_NOTFOUND is returned.
133*4dc78e53SAndroid Build Coastguard Worker  *  - \c NLM_F_REPLACE: If another qdisc is already attached to the
134*4dc78e53SAndroid Build Coastguard Worker  *                      parent, replace it even if the handles mismatch.
135*4dc78e53SAndroid Build Coastguard Worker  *  - \c NLM_F_EXCL:    Return -NLE_EXISTS if a qdisc with matching
136*4dc78e53SAndroid Build Coastguard Worker  *                      handle exists already.
137*4dc78e53SAndroid Build Coastguard Worker  *
138*4dc78e53SAndroid Build Coastguard Worker  * Existing qdiscs with matching handles will be updated, unless the
139*4dc78e53SAndroid Build Coastguard Worker  * flag \c NLM_F_EXCL is specified. If their handles do not match, the
140*4dc78e53SAndroid Build Coastguard Worker  * error -NLE_EXISTS is returned unless the flag \c NLM_F_REPLACE is
141*4dc78e53SAndroid Build Coastguard Worker  * specified in which case the existing qdisc is replaced with the new
142*4dc78e53SAndroid Build Coastguard Worker  * one.  If no matching qdisc exists, it will be created if the flag
143*4dc78e53SAndroid Build Coastguard Worker  * \c NLM_F_CREATE is set, otherwise the error -NLE_OBJ_NOTFOUND is
144*4dc78e53SAndroid Build Coastguard Worker  * returned.
145*4dc78e53SAndroid Build Coastguard Worker  *
146*4dc78e53SAndroid Build Coastguard Worker  * After sending, the function will wait for the ACK or an eventual
147*4dc78e53SAndroid Build Coastguard Worker  * error message to be received and will therefore block until the
148*4dc78e53SAndroid Build Coastguard Worker  * operation has been completed.
149*4dc78e53SAndroid Build Coastguard Worker  *
150*4dc78e53SAndroid Build Coastguard Worker  * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
151*4dc78e53SAndroid Build Coastguard Worker  *       this function to return immediately after sending. In this case,
152*4dc78e53SAndroid Build Coastguard Worker  *       it is the responsibility of the caller to handle any error
153*4dc78e53SAndroid Build Coastguard Worker  *       messages returned.
154*4dc78e53SAndroid Build Coastguard Worker  *
155*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
156*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_add(struct nl_sock * sk,struct rtnl_qdisc * qdisc,int flags)157*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_add(struct nl_sock *sk, struct rtnl_qdisc *qdisc, int flags)
158*4dc78e53SAndroid Build Coastguard Worker {
159*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
160*4dc78e53SAndroid Build Coastguard Worker 	int err;
161*4dc78e53SAndroid Build Coastguard Worker 
162*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_qdisc_build_add_request(qdisc, flags, &msg)) < 0)
163*4dc78e53SAndroid Build Coastguard Worker 		return err;
164*4dc78e53SAndroid Build Coastguard Worker 
165*4dc78e53SAndroid Build Coastguard Worker 	return nl_send_sync(sk, msg);
166*4dc78e53SAndroid Build Coastguard Worker }
167*4dc78e53SAndroid Build Coastguard Worker 
168*4dc78e53SAndroid Build Coastguard Worker /**
169*4dc78e53SAndroid Build Coastguard Worker  * Build netlink message requesting the update of a qdisc
170*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		Qdisc to update
171*4dc78e53SAndroid Build Coastguard Worker  * @arg new		Qdisc with updated attributes
172*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Additional netlink message flags
173*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting netlink message
174*4dc78e53SAndroid Build Coastguard Worker  *
175*4dc78e53SAndroid Build Coastguard Worker  * The behaviour of this function is identical to rtnl_qdisc_update() with
176*4dc78e53SAndroid Build Coastguard Worker  * the exception that it will not send the message but return it in the
177*4dc78e53SAndroid Build Coastguard Worker  * provided return pointer instead.
178*4dc78e53SAndroid Build Coastguard Worker  *
179*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_qdisc_update()
180*4dc78e53SAndroid Build Coastguard Worker  *
181*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
182*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_build_update_request(struct rtnl_qdisc * qdisc,struct rtnl_qdisc * new,int flags,struct nl_msg ** result)183*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_build_update_request(struct rtnl_qdisc *qdisc,
184*4dc78e53SAndroid Build Coastguard Worker 				    struct rtnl_qdisc *new, int flags,
185*4dc78e53SAndroid Build Coastguard Worker 				    struct nl_msg **result)
186*4dc78e53SAndroid Build Coastguard Worker {
187*4dc78e53SAndroid Build Coastguard Worker 	if (flags & (NLM_F_CREATE | NLM_F_EXCL)) {
188*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("NLM_F_CREATE and NLM_F_EXCL may not be used here, "
189*4dc78e53SAndroid Build Coastguard Worker 		       "use rtnl_qdisc_add()");
190*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
191*4dc78e53SAndroid Build Coastguard Worker 	}
192*4dc78e53SAndroid Build Coastguard Worker 
193*4dc78e53SAndroid Build Coastguard Worker 	if (!(qdisc->ce_mask & TCA_ATTR_IFINDEX)) {
194*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("ifindex must be specified");
195*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
196*4dc78e53SAndroid Build Coastguard Worker 	}
197*4dc78e53SAndroid Build Coastguard Worker 
198*4dc78e53SAndroid Build Coastguard Worker 	if (!(qdisc->ce_mask & (TCA_ATTR_HANDLE | TCA_ATTR_PARENT))) {
199*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("handle or parent must be specified");
200*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
201*4dc78e53SAndroid Build Coastguard Worker 	}
202*4dc78e53SAndroid Build Coastguard Worker 
203*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_set_ifindex(TC_CAST(new), qdisc->q_ifindex);
204*4dc78e53SAndroid Build Coastguard Worker 
205*4dc78e53SAndroid Build Coastguard Worker 	if (qdisc->ce_mask & TCA_ATTR_HANDLE)
206*4dc78e53SAndroid Build Coastguard Worker 		rtnl_tc_set_handle(TC_CAST(new), qdisc->q_handle);
207*4dc78e53SAndroid Build Coastguard Worker 
208*4dc78e53SAndroid Build Coastguard Worker 	if (qdisc->ce_mask & TCA_ATTR_PARENT)
209*4dc78e53SAndroid Build Coastguard Worker 		rtnl_tc_set_parent(TC_CAST(new), qdisc->q_parent);
210*4dc78e53SAndroid Build Coastguard Worker 
211*4dc78e53SAndroid Build Coastguard Worker 	return build_qdisc_msg(new, RTM_NEWQDISC, flags, result);
212*4dc78e53SAndroid Build Coastguard Worker }
213*4dc78e53SAndroid Build Coastguard Worker 
214*4dc78e53SAndroid Build Coastguard Worker /**
215*4dc78e53SAndroid Build Coastguard Worker  * Update qdisc
216*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
217*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		Qdisc to update
218*4dc78e53SAndroid Build Coastguard Worker  * @arg new		Qdisc with updated attributes
219*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Additional netlink message flags
220*4dc78e53SAndroid Build Coastguard Worker  *
221*4dc78e53SAndroid Build Coastguard Worker  * Builds a \c RTM_NEWQDISC netlink message requesting the update
222*4dc78e53SAndroid Build Coastguard Worker  * of an existing qdisc and sends the message to the kernel.
223*4dc78e53SAndroid Build Coastguard Worker  *
224*4dc78e53SAndroid Build Coastguard Worker  * This function is a varation of rtnl_qdisc_add() to update qdiscs
225*4dc78e53SAndroid Build Coastguard Worker  * if the qdisc to be updated is available as qdisc object. The
226*4dc78e53SAndroid Build Coastguard Worker  * behaviour is identical to the one of rtnl_qdisc_add except that
227*4dc78e53SAndroid Build Coastguard Worker  * before constructing the message, it copies the \c ifindex,
228*4dc78e53SAndroid Build Coastguard Worker  * \c handle, and \c parent from the original \p qdisc to the \p new
229*4dc78e53SAndroid Build Coastguard Worker  * qdisc.
230*4dc78e53SAndroid Build Coastguard Worker  *
231*4dc78e53SAndroid Build Coastguard Worker  * After sending, the function will wait for the ACK or an eventual
232*4dc78e53SAndroid Build Coastguard Worker  * error message to be received and will therefore block until the
233*4dc78e53SAndroid Build Coastguard Worker  * operation has been completed.
234*4dc78e53SAndroid Build Coastguard Worker  *
235*4dc78e53SAndroid Build Coastguard Worker  * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
236*4dc78e53SAndroid Build Coastguard Worker  *       this function to return immediately after sending. In this case,
237*4dc78e53SAndroid Build Coastguard Worker  *       it is the responsibility of the caller to handle any error
238*4dc78e53SAndroid Build Coastguard Worker  *       messages returned.
239*4dc78e53SAndroid Build Coastguard Worker  *
240*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
241*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_update(struct nl_sock * sk,struct rtnl_qdisc * qdisc,struct rtnl_qdisc * new,int flags)242*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_update(struct nl_sock *sk, struct rtnl_qdisc *qdisc,
243*4dc78e53SAndroid Build Coastguard Worker 		      struct rtnl_qdisc *new, int flags)
244*4dc78e53SAndroid Build Coastguard Worker {
245*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
246*4dc78e53SAndroid Build Coastguard Worker 	int err;
247*4dc78e53SAndroid Build Coastguard Worker 
248*4dc78e53SAndroid Build Coastguard Worker 	err = rtnl_qdisc_build_update_request(qdisc, new, flags, &msg);
249*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
250*4dc78e53SAndroid Build Coastguard Worker 		return err;
251*4dc78e53SAndroid Build Coastguard Worker 
252*4dc78e53SAndroid Build Coastguard Worker 	return nl_send_sync(sk, msg);
253*4dc78e53SAndroid Build Coastguard Worker }
254*4dc78e53SAndroid Build Coastguard Worker 
255*4dc78e53SAndroid Build Coastguard Worker /**
256*4dc78e53SAndroid Build Coastguard Worker  * Build netlink message requesting the deletion of a qdisc
257*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		Qdisc to delete
258*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting netlink message
259*4dc78e53SAndroid Build Coastguard Worker  *
260*4dc78e53SAndroid Build Coastguard Worker  * The behaviour of this function is identical to rtnl_qdisc_delete() with
261*4dc78e53SAndroid Build Coastguard Worker  * the exception that it will not send the message but return it in the
262*4dc78e53SAndroid Build Coastguard Worker  * provided return pointer instead.
263*4dc78e53SAndroid Build Coastguard Worker  *
264*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_qdisc_delete()
265*4dc78e53SAndroid Build Coastguard Worker  *
266*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
267*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_build_delete_request(struct rtnl_qdisc * qdisc,struct nl_msg ** result)268*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc,
269*4dc78e53SAndroid Build Coastguard Worker 				    struct nl_msg **result)
270*4dc78e53SAndroid Build Coastguard Worker {
271*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
272*4dc78e53SAndroid Build Coastguard Worker 	struct tcmsg tchdr;
273*4dc78e53SAndroid Build Coastguard Worker 	uint32_t required = TCA_ATTR_IFINDEX | TCA_ATTR_PARENT;
274*4dc78e53SAndroid Build Coastguard Worker 
275*4dc78e53SAndroid Build Coastguard Worker 	if ((qdisc->ce_mask & required) != required) {
276*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("ifindex and parent must be specified");
277*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
278*4dc78e53SAndroid Build Coastguard Worker 	}
279*4dc78e53SAndroid Build Coastguard Worker 
280*4dc78e53SAndroid Build Coastguard Worker 	if (!(msg = nlmsg_alloc_simple(RTM_DELQDISC, 0)))
281*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
282*4dc78e53SAndroid Build Coastguard Worker 
283*4dc78e53SAndroid Build Coastguard Worker 	memset(&tchdr, 0, sizeof(tchdr));
284*4dc78e53SAndroid Build Coastguard Worker 
285*4dc78e53SAndroid Build Coastguard Worker 	tchdr.tcm_family = AF_UNSPEC;
286*4dc78e53SAndroid Build Coastguard Worker 	tchdr.tcm_ifindex = qdisc->q_ifindex;
287*4dc78e53SAndroid Build Coastguard Worker 	tchdr.tcm_parent = qdisc->q_parent;
288*4dc78e53SAndroid Build Coastguard Worker 
289*4dc78e53SAndroid Build Coastguard Worker 	if (qdisc->ce_mask & TCA_ATTR_HANDLE)
290*4dc78e53SAndroid Build Coastguard Worker 		tchdr.tcm_handle = qdisc->q_handle;
291*4dc78e53SAndroid Build Coastguard Worker 
292*4dc78e53SAndroid Build Coastguard Worker 	if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0)
293*4dc78e53SAndroid Build Coastguard Worker 		goto nla_put_failure;
294*4dc78e53SAndroid Build Coastguard Worker 
295*4dc78e53SAndroid Build Coastguard Worker 	if (qdisc->ce_mask & TCA_ATTR_KIND)
296*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_STRING(msg, TCA_KIND, qdisc->q_kind);
297*4dc78e53SAndroid Build Coastguard Worker 
298*4dc78e53SAndroid Build Coastguard Worker 	*result = msg;
299*4dc78e53SAndroid Build Coastguard Worker 	return 0;
300*4dc78e53SAndroid Build Coastguard Worker 
301*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
302*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
303*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_MSGSIZE;
304*4dc78e53SAndroid Build Coastguard Worker }
305*4dc78e53SAndroid Build Coastguard Worker 
306*4dc78e53SAndroid Build Coastguard Worker /**
307*4dc78e53SAndroid Build Coastguard Worker  * Delete qdisc
308*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
309*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		Qdisc to add
310*4dc78e53SAndroid Build Coastguard Worker  *
311*4dc78e53SAndroid Build Coastguard Worker  * Builds a \c RTM_NEWQDISC netlink message requesting the deletion
312*4dc78e53SAndroid Build Coastguard Worker  * of a qdisc and sends the message to the kernel.
313*4dc78e53SAndroid Build Coastguard Worker  *
314*4dc78e53SAndroid Build Coastguard Worker  * The message is constructed out of the following attributes:
315*4dc78e53SAndroid Build Coastguard Worker  * - \c ifindex and \c parent
316*4dc78e53SAndroid Build Coastguard Worker  * - \c handle (optional, must match if provided)
317*4dc78e53SAndroid Build Coastguard Worker  * - \c kind (optional, must match if provided)
318*4dc78e53SAndroid Build Coastguard Worker  *
319*4dc78e53SAndroid Build Coastguard Worker  * All other qdisc attributes including all qdisc type specific
320*4dc78e53SAndroid Build Coastguard Worker  * attributes are ignored.
321*4dc78e53SAndroid Build Coastguard Worker  *
322*4dc78e53SAndroid Build Coastguard Worker  * After sending, the function will wait for the ACK or an eventual
323*4dc78e53SAndroid Build Coastguard Worker  * error message to be received and will therefore block until the
324*4dc78e53SAndroid Build Coastguard Worker  * operation has been completed.
325*4dc78e53SAndroid Build Coastguard Worker  *
326*4dc78e53SAndroid Build Coastguard Worker  * @note It is not possible to delete default qdiscs.
327*4dc78e53SAndroid Build Coastguard Worker  *
328*4dc78e53SAndroid Build Coastguard Worker  * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
329*4dc78e53SAndroid Build Coastguard Worker  *       this function to return immediately after sending. In this case,
330*4dc78e53SAndroid Build Coastguard Worker  *       it is the responsibility of the caller to handle any error
331*4dc78e53SAndroid Build Coastguard Worker  *       messages returned.
332*4dc78e53SAndroid Build Coastguard Worker  *
333*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
334*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_delete(struct nl_sock * sk,struct rtnl_qdisc * qdisc)335*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_delete(struct nl_sock *sk, struct rtnl_qdisc *qdisc)
336*4dc78e53SAndroid Build Coastguard Worker {
337*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
338*4dc78e53SAndroid Build Coastguard Worker 	int err;
339*4dc78e53SAndroid Build Coastguard Worker 
340*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_qdisc_build_delete_request(qdisc, &msg)) < 0)
341*4dc78e53SAndroid Build Coastguard Worker 		return err;
342*4dc78e53SAndroid Build Coastguard Worker 
343*4dc78e53SAndroid Build Coastguard Worker 	return nl_send_sync(sk, msg);
344*4dc78e53SAndroid Build Coastguard Worker }
345*4dc78e53SAndroid Build Coastguard Worker 
346*4dc78e53SAndroid Build Coastguard Worker /** @} */
347*4dc78e53SAndroid Build Coastguard Worker 
348*4dc78e53SAndroid Build Coastguard Worker /**
349*4dc78e53SAndroid Build Coastguard Worker  * @name Cache Related Functions
350*4dc78e53SAndroid Build Coastguard Worker  * @{
351*4dc78e53SAndroid Build Coastguard Worker  */
352*4dc78e53SAndroid Build Coastguard Worker 
353*4dc78e53SAndroid Build Coastguard Worker /**
354*4dc78e53SAndroid Build Coastguard Worker  * Allocate a cache and fill it with all configured qdiscs
355*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
356*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store the created cache
357*4dc78e53SAndroid Build Coastguard Worker  *
358*4dc78e53SAndroid Build Coastguard Worker  * Allocates a new qdisc cache and fills it with a list of all configured
359*4dc78e53SAndroid Build Coastguard Worker  * qdiscs on all network devices. Release the cache with nl_cache_free().
360*4dc78e53SAndroid Build Coastguard Worker  *
361*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
362*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_alloc_cache(struct nl_sock * sk,struct nl_cache ** result)363*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
364*4dc78e53SAndroid Build Coastguard Worker {
365*4dc78e53SAndroid Build Coastguard Worker 	return nl_cache_alloc_and_fill(&rtnl_qdisc_ops, sk, result);
366*4dc78e53SAndroid Build Coastguard Worker }
367*4dc78e53SAndroid Build Coastguard Worker 
368*4dc78e53SAndroid Build Coastguard Worker /**
369*4dc78e53SAndroid Build Coastguard Worker  * Search qdisc by interface index and parent
370*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		Qdisc cache
371*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index
372*4dc78e53SAndroid Build Coastguard Worker  * @arg parent		Handle of parent qdisc
373*4dc78e53SAndroid Build Coastguard Worker  *
374*4dc78e53SAndroid Build Coastguard Worker  * Searches a qdisc cache previously allocated with rtnl_qdisc_alloc_cache()
375*4dc78e53SAndroid Build Coastguard Worker  * and searches for a qdisc matching the interface index and parent qdisc.
376*4dc78e53SAndroid Build Coastguard Worker  *
377*4dc78e53SAndroid Build Coastguard Worker  * The reference counter is incremented before returning the qdisc, therefore
378*4dc78e53SAndroid Build Coastguard Worker  * the reference must be given back with rtnl_qdisc_put() after usage.
379*4dc78e53SAndroid Build Coastguard Worker  *
380*4dc78e53SAndroid Build Coastguard Worker  * @return pointer to qdisc inside the cache or NULL if no match was found.
381*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_get_by_parent(struct nl_cache * cache,int ifindex,uint32_t parent)382*4dc78e53SAndroid Build Coastguard Worker struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *cache,
383*4dc78e53SAndroid Build Coastguard Worker 					    int ifindex, uint32_t parent)
384*4dc78e53SAndroid Build Coastguard Worker {
385*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_qdisc *q;
386*4dc78e53SAndroid Build Coastguard Worker 
387*4dc78e53SAndroid Build Coastguard Worker 	if (cache->c_ops != &rtnl_qdisc_ops)
388*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
389*4dc78e53SAndroid Build Coastguard Worker 
390*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(q, &cache->c_items, ce_list) {
391*4dc78e53SAndroid Build Coastguard Worker 		if (q->q_parent == parent &&
392*4dc78e53SAndroid Build Coastguard Worker 		    q->q_ifindex == ((unsigned)ifindex)) {
393*4dc78e53SAndroid Build Coastguard Worker 			nl_object_get((struct nl_object *) q);
394*4dc78e53SAndroid Build Coastguard Worker 			return q;
395*4dc78e53SAndroid Build Coastguard Worker 		}
396*4dc78e53SAndroid Build Coastguard Worker 	}
397*4dc78e53SAndroid Build Coastguard Worker 
398*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
399*4dc78e53SAndroid Build Coastguard Worker }
400*4dc78e53SAndroid Build Coastguard Worker 
401*4dc78e53SAndroid Build Coastguard Worker /**
402*4dc78e53SAndroid Build Coastguard Worker  * Search qdisc by kind
403*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		Qdisc cache
404*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index
405*4dc78e53SAndroid Build Coastguard Worker  * @arg kind		Qdisc kind (tbf, htb, cbq, etc)
406*4dc78e53SAndroid Build Coastguard Worker  *
407*4dc78e53SAndroid Build Coastguard Worker  * Searches a qdisc cache previously allocated with rtnl_qdisc_alloc_cache()
408*4dc78e53SAndroid Build Coastguard Worker  * and searches for a qdisc matching the interface index and kind.
409*4dc78e53SAndroid Build Coastguard Worker  *
410*4dc78e53SAndroid Build Coastguard Worker  * The reference counter is incremented before returning the qdisc, therefore
411*4dc78e53SAndroid Build Coastguard Worker  * the reference must be given back with rtnl_qdisc_put() after usage.
412*4dc78e53SAndroid Build Coastguard Worker  *
413*4dc78e53SAndroid Build Coastguard Worker  * @return pointer to qdisc inside the cache or NULL if no match was found.
414*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_get_by_kind(struct nl_cache * cache,int ifindex,char * kind)415*4dc78e53SAndroid Build Coastguard Worker struct rtnl_qdisc *rtnl_qdisc_get_by_kind(struct nl_cache *cache,
416*4dc78e53SAndroid Build Coastguard Worker 					    int ifindex, char *kind)
417*4dc78e53SAndroid Build Coastguard Worker {
418*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_qdisc *q;
419*4dc78e53SAndroid Build Coastguard Worker 
420*4dc78e53SAndroid Build Coastguard Worker 	if (cache->c_ops != &rtnl_qdisc_ops)
421*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
422*4dc78e53SAndroid Build Coastguard Worker 
423*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(q, &cache->c_items, ce_list) {
424*4dc78e53SAndroid Build Coastguard Worker 		if ((q->q_ifindex == ((unsigned)ifindex)) &&
425*4dc78e53SAndroid Build Coastguard Worker 		    (!strcmp(q->q_kind, kind))) {
426*4dc78e53SAndroid Build Coastguard Worker 			nl_object_get((struct nl_object *) q);
427*4dc78e53SAndroid Build Coastguard Worker 			return q;
428*4dc78e53SAndroid Build Coastguard Worker 		}
429*4dc78e53SAndroid Build Coastguard Worker 	}
430*4dc78e53SAndroid Build Coastguard Worker 
431*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
432*4dc78e53SAndroid Build Coastguard Worker }
433*4dc78e53SAndroid Build Coastguard Worker 
434*4dc78e53SAndroid Build Coastguard Worker /**
435*4dc78e53SAndroid Build Coastguard Worker  * Search qdisc by interface index and handle
436*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		Qdisc cache
437*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index
438*4dc78e53SAndroid Build Coastguard Worker  * @arg handle		Handle
439*4dc78e53SAndroid Build Coastguard Worker  *
440*4dc78e53SAndroid Build Coastguard Worker  * Searches a qdisc cache previously allocated with rtnl_qdisc_alloc_cache()
441*4dc78e53SAndroid Build Coastguard Worker  * and searches for a qdisc matching the interface index and handle.
442*4dc78e53SAndroid Build Coastguard Worker  *
443*4dc78e53SAndroid Build Coastguard Worker  * The reference counter is incremented before returning the qdisc, therefore
444*4dc78e53SAndroid Build Coastguard Worker  * the reference must be given back with rtnl_qdisc_put() after usage.
445*4dc78e53SAndroid Build Coastguard Worker  *
446*4dc78e53SAndroid Build Coastguard Worker  * @return Qdisc or NULL if no match was found.
447*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_get(struct nl_cache * cache,int ifindex,uint32_t handle)448*4dc78e53SAndroid Build Coastguard Worker struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int ifindex,
449*4dc78e53SAndroid Build Coastguard Worker 				  uint32_t handle)
450*4dc78e53SAndroid Build Coastguard Worker {
451*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_qdisc *q;
452*4dc78e53SAndroid Build Coastguard Worker 
453*4dc78e53SAndroid Build Coastguard Worker 	if (cache->c_ops != &rtnl_qdisc_ops)
454*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
455*4dc78e53SAndroid Build Coastguard Worker 
456*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(q, &cache->c_items, ce_list) {
457*4dc78e53SAndroid Build Coastguard Worker 		if (q->q_handle == handle &&
458*4dc78e53SAndroid Build Coastguard Worker 		    q->q_ifindex == ((unsigned)ifindex)) {
459*4dc78e53SAndroid Build Coastguard Worker 			nl_object_get((struct nl_object *) q);
460*4dc78e53SAndroid Build Coastguard Worker 			return q;
461*4dc78e53SAndroid Build Coastguard Worker 		}
462*4dc78e53SAndroid Build Coastguard Worker 	}
463*4dc78e53SAndroid Build Coastguard Worker 
464*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
465*4dc78e53SAndroid Build Coastguard Worker }
466*4dc78e53SAndroid Build Coastguard Worker 
467*4dc78e53SAndroid Build Coastguard Worker /** @} */
468*4dc78e53SAndroid Build Coastguard Worker 
469*4dc78e53SAndroid Build Coastguard Worker /**
470*4dc78e53SAndroid Build Coastguard Worker  * @name Deprecated Functions
471*4dc78e53SAndroid Build Coastguard Worker  * @{
472*4dc78e53SAndroid Build Coastguard Worker  */
473*4dc78e53SAndroid Build Coastguard Worker 
474*4dc78e53SAndroid Build Coastguard Worker /**
475*4dc78e53SAndroid Build Coastguard Worker  * Call a callback for each child class of a qdisc (deprecated)
476*4dc78e53SAndroid Build Coastguard Worker  *
477*4dc78e53SAndroid Build Coastguard Worker  * @deprecated Use of this function is deprecated, it does not allow
478*4dc78e53SAndroid Build Coastguard Worker  *             to handle the out of memory situation that can occur.
479*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_foreach_child(struct rtnl_qdisc * qdisc,struct nl_cache * cache,void (* cb)(struct nl_object *,void *),void * arg)480*4dc78e53SAndroid Build Coastguard Worker void rtnl_qdisc_foreach_child(struct rtnl_qdisc *qdisc, struct nl_cache *cache,
481*4dc78e53SAndroid Build Coastguard Worker 			      void (*cb)(struct nl_object *, void *), void *arg)
482*4dc78e53SAndroid Build Coastguard Worker {
483*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_class *filter;
484*4dc78e53SAndroid Build Coastguard Worker 
485*4dc78e53SAndroid Build Coastguard Worker 	filter = rtnl_class_alloc();
486*4dc78e53SAndroid Build Coastguard Worker 	if (!filter)
487*4dc78e53SAndroid Build Coastguard Worker 		return;
488*4dc78e53SAndroid Build Coastguard Worker 
489*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_set_parent(TC_CAST(filter), qdisc->q_handle);
490*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_set_ifindex(TC_CAST(filter), qdisc->q_ifindex);
491*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_set_kind(TC_CAST(filter), qdisc->q_kind);
492*4dc78e53SAndroid Build Coastguard Worker 
493*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_foreach_filter(cache, OBJ_CAST(filter), cb, arg);
494*4dc78e53SAndroid Build Coastguard Worker 
495*4dc78e53SAndroid Build Coastguard Worker 	rtnl_class_put(filter);
496*4dc78e53SAndroid Build Coastguard Worker }
497*4dc78e53SAndroid Build Coastguard Worker 
498*4dc78e53SAndroid Build Coastguard Worker /**
499*4dc78e53SAndroid Build Coastguard Worker  * Call a callback for each filter attached to the qdisc (deprecated)
500*4dc78e53SAndroid Build Coastguard Worker  *
501*4dc78e53SAndroid Build Coastguard Worker  * @deprecated Use of this function is deprecated, it does not allow
502*4dc78e53SAndroid Build Coastguard Worker  *             to handle the out of memory situation that can occur.
503*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_foreach_cls(struct rtnl_qdisc * qdisc,struct nl_cache * cache,void (* cb)(struct nl_object *,void *),void * arg)504*4dc78e53SAndroid Build Coastguard Worker void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache,
505*4dc78e53SAndroid Build Coastguard Worker 			    void (*cb)(struct nl_object *, void *), void *arg)
506*4dc78e53SAndroid Build Coastguard Worker {
507*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_cls *filter;
508*4dc78e53SAndroid Build Coastguard Worker 
509*4dc78e53SAndroid Build Coastguard Worker 	if (!(filter = rtnl_cls_alloc()))
510*4dc78e53SAndroid Build Coastguard Worker 		return;
511*4dc78e53SAndroid Build Coastguard Worker 
512*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_set_ifindex(TC_CAST(filter), qdisc->q_ifindex);
513*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_set_parent(TC_CAST(filter), qdisc->q_parent);
514*4dc78e53SAndroid Build Coastguard Worker 
515*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_foreach_filter(cache, OBJ_CAST(filter), cb, arg);
516*4dc78e53SAndroid Build Coastguard Worker 	rtnl_cls_put(filter);
517*4dc78e53SAndroid Build Coastguard Worker }
518*4dc78e53SAndroid Build Coastguard Worker 
519*4dc78e53SAndroid Build Coastguard Worker /**
520*4dc78e53SAndroid Build Coastguard Worker  * Build a netlink message requesting the update of a qdisc
521*4dc78e53SAndroid Build Coastguard Worker  *
522*4dc78e53SAndroid Build Coastguard Worker  * @deprecated Use of this function is deprecated in favour of
523*4dc78e53SAndroid Build Coastguard Worker  *             rtnl_qdisc_build_update_request() due to the missing
524*4dc78e53SAndroid Build Coastguard Worker  *             possibility of specifying additional flags.
525*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_build_change_request(struct rtnl_qdisc * qdisc,struct rtnl_qdisc * new,struct nl_msg ** result)526*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_build_change_request(struct rtnl_qdisc *qdisc,
527*4dc78e53SAndroid Build Coastguard Worker 				    struct rtnl_qdisc *new,
528*4dc78e53SAndroid Build Coastguard Worker 				    struct nl_msg **result)
529*4dc78e53SAndroid Build Coastguard Worker {
530*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_qdisc_build_update_request(qdisc, new, NLM_F_REPLACE,
531*4dc78e53SAndroid Build Coastguard Worker 					       result);
532*4dc78e53SAndroid Build Coastguard Worker }
533*4dc78e53SAndroid Build Coastguard Worker 
534*4dc78e53SAndroid Build Coastguard Worker /**
535*4dc78e53SAndroid Build Coastguard Worker  * Change attributes of a qdisc
536*4dc78e53SAndroid Build Coastguard Worker  *
537*4dc78e53SAndroid Build Coastguard Worker  * @deprecated Use of this function is deprecated in favour of
538*4dc78e53SAndroid Build Coastguard Worker  *             rtnl_qdisc_update() due to the missing possibility of
539*4dc78e53SAndroid Build Coastguard Worker  *             specifying additional flags.
540*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_qdisc_change(struct nl_sock * sk,struct rtnl_qdisc * qdisc,struct rtnl_qdisc * new)541*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_change(struct nl_sock *sk, struct rtnl_qdisc *qdisc,
542*4dc78e53SAndroid Build Coastguard Worker 		      struct rtnl_qdisc *new)
543*4dc78e53SAndroid Build Coastguard Worker {
544*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_qdisc_update(sk, qdisc, new, NLM_F_REPLACE);
545*4dc78e53SAndroid Build Coastguard Worker }
546*4dc78e53SAndroid Build Coastguard Worker 
547*4dc78e53SAndroid Build Coastguard Worker /** @} */
548*4dc78e53SAndroid Build Coastguard Worker 
qdisc_dump_details(struct rtnl_tc * tc,struct nl_dump_params * p)549*4dc78e53SAndroid Build Coastguard Worker static void qdisc_dump_details(struct rtnl_tc *tc, struct nl_dump_params *p)
550*4dc78e53SAndroid Build Coastguard Worker {
551*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
552*4dc78e53SAndroid Build Coastguard Worker 
553*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "refcnt %u", qdisc->q_info);
554*4dc78e53SAndroid Build Coastguard Worker }
555*4dc78e53SAndroid Build Coastguard Worker 
556*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_type_ops qdisc_ops = {
557*4dc78e53SAndroid Build Coastguard Worker 	.tt_type		= RTNL_TC_TYPE_QDISC,
558*4dc78e53SAndroid Build Coastguard Worker 	.tt_dump_prefix		= "qdisc",
559*4dc78e53SAndroid Build Coastguard Worker 	.tt_dump = {
560*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_DETAILS]	= qdisc_dump_details,
561*4dc78e53SAndroid Build Coastguard Worker 	},
562*4dc78e53SAndroid Build Coastguard Worker };
563*4dc78e53SAndroid Build Coastguard Worker 
564*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_qdisc_ops = {
565*4dc78e53SAndroid Build Coastguard Worker 	.co_name		= "route/qdisc",
566*4dc78e53SAndroid Build Coastguard Worker 	.co_hdrsize		= sizeof(struct tcmsg),
567*4dc78e53SAndroid Build Coastguard Worker 	.co_msgtypes		= {
568*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_NEWQDISC, NL_ACT_NEW, "new" },
569*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_DELQDISC, NL_ACT_DEL, "del" },
570*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_GETQDISC, NL_ACT_GET, "get" },
571*4dc78e53SAndroid Build Coastguard Worker 					END_OF_MSGTYPES_LIST,
572*4dc78e53SAndroid Build Coastguard Worker 				  },
573*4dc78e53SAndroid Build Coastguard Worker 	.co_protocol		= NETLINK_ROUTE,
574*4dc78e53SAndroid Build Coastguard Worker 	.co_groups		= tc_groups,
575*4dc78e53SAndroid Build Coastguard Worker 	.co_request_update	= qdisc_request_update,
576*4dc78e53SAndroid Build Coastguard Worker 	.co_msg_parser		= qdisc_msg_parser,
577*4dc78e53SAndroid Build Coastguard Worker 	.co_obj_ops		= &qdisc_obj_ops,
578*4dc78e53SAndroid Build Coastguard Worker };
579*4dc78e53SAndroid Build Coastguard Worker 
580*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops qdisc_obj_ops = {
581*4dc78e53SAndroid Build Coastguard Worker 	.oo_name		= "route/qdisc",
582*4dc78e53SAndroid Build Coastguard Worker 	.oo_size		= sizeof(struct rtnl_qdisc),
583*4dc78e53SAndroid Build Coastguard Worker 	.oo_free_data		= rtnl_tc_free_data,
584*4dc78e53SAndroid Build Coastguard Worker 	.oo_clone		= rtnl_tc_clone,
585*4dc78e53SAndroid Build Coastguard Worker 	.oo_dump = {
586*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_LINE]	= rtnl_tc_dump_line,
587*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_DETAILS]	= rtnl_tc_dump_details,
588*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_STATS]	= rtnl_tc_dump_stats,
589*4dc78e53SAndroid Build Coastguard Worker 	},
590*4dc78e53SAndroid Build Coastguard Worker 	.oo_compare		= rtnl_tc_compare,
591*4dc78e53SAndroid Build Coastguard Worker 	.oo_id_attrs		= (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
592*4dc78e53SAndroid Build Coastguard Worker };
593*4dc78e53SAndroid Build Coastguard Worker 
qdisc_init(void)594*4dc78e53SAndroid Build Coastguard Worker static void _nl_init qdisc_init(void)
595*4dc78e53SAndroid Build Coastguard Worker {
596*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_type_register(&qdisc_ops);
597*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_register(&rtnl_qdisc_ops);
598*4dc78e53SAndroid Build Coastguard Worker }
599*4dc78e53SAndroid Build Coastguard Worker 
qdisc_exit(void)600*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit qdisc_exit(void)
601*4dc78e53SAndroid Build Coastguard Worker {
602*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_unregister(&rtnl_qdisc_ops);
603*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_type_unregister(&qdisc_ops);
604*4dc78e53SAndroid Build Coastguard Worker }
605*4dc78e53SAndroid Build Coastguard Worker 
606*4dc78e53SAndroid Build Coastguard Worker /** @} */
607