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-2013 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 cls Classifiers
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 <linux/ethtool.h>
15*4dc78e53SAndroid Build Coastguard Worker
16*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
17*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
18*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/classifier.h>
19*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
20*4dc78e53SAndroid Build Coastguard Worker
21*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
22*4dc78e53SAndroid Build Coastguard Worker #include "tc-api.h"
23*4dc78e53SAndroid Build Coastguard Worker
24*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
25*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cls {
26*4dc78e53SAndroid Build Coastguard Worker NL_TC_GENERIC(c);
27*4dc78e53SAndroid Build Coastguard Worker uint16_t c_prio;
28*4dc78e53SAndroid Build Coastguard Worker uint16_t c_protocol;
29*4dc78e53SAndroid Build Coastguard Worker };
30*4dc78e53SAndroid Build Coastguard Worker
31*4dc78e53SAndroid Build Coastguard Worker #define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1)
32*4dc78e53SAndroid Build Coastguard Worker #define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2)
33*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
34*4dc78e53SAndroid Build Coastguard Worker
35*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops cls_obj_ops;
36*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_cls_ops;
37*4dc78e53SAndroid Build Coastguard Worker
38*4dc78e53SAndroid Build Coastguard Worker
cls_build(struct rtnl_cls * cls,int type,int flags,struct nl_msg ** result)39*4dc78e53SAndroid Build Coastguard Worker static int cls_build(struct rtnl_cls *cls, int type, int flags,
40*4dc78e53SAndroid Build Coastguard Worker struct nl_msg **result)
41*4dc78e53SAndroid Build Coastguard Worker {
42*4dc78e53SAndroid Build Coastguard Worker int err, prio, proto;
43*4dc78e53SAndroid Build Coastguard Worker struct tcmsg *tchdr;
44*4dc78e53SAndroid Build Coastguard Worker uint32_t required = TCA_ATTR_IFINDEX;
45*4dc78e53SAndroid Build Coastguard Worker
46*4dc78e53SAndroid Build Coastguard Worker if ((cls->ce_mask & required) != required) {
47*4dc78e53SAndroid Build Coastguard Worker APPBUG("ifindex must be specified");
48*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
49*4dc78e53SAndroid Build Coastguard Worker }
50*4dc78e53SAndroid Build Coastguard Worker
51*4dc78e53SAndroid Build Coastguard Worker err = rtnl_tc_msg_build(TC_CAST(cls), type, flags, result);
52*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
53*4dc78e53SAndroid Build Coastguard Worker return err;
54*4dc78e53SAndroid Build Coastguard Worker
55*4dc78e53SAndroid Build Coastguard Worker tchdr = nlmsg_data(nlmsg_hdr(*result));
56*4dc78e53SAndroid Build Coastguard Worker prio = rtnl_cls_get_prio(cls);
57*4dc78e53SAndroid Build Coastguard Worker proto = rtnl_cls_get_protocol(cls);
58*4dc78e53SAndroid Build Coastguard Worker tchdr->tcm_info = TC_H_MAKE(prio << 16, htons(proto));
59*4dc78e53SAndroid Build Coastguard Worker
60*4dc78e53SAndroid Build Coastguard Worker return 0;
61*4dc78e53SAndroid Build Coastguard Worker }
62*4dc78e53SAndroid Build Coastguard Worker
63*4dc78e53SAndroid Build Coastguard Worker /**
64*4dc78e53SAndroid Build Coastguard Worker * @name Allocation/Freeing
65*4dc78e53SAndroid Build Coastguard Worker * @{
66*4dc78e53SAndroid Build Coastguard Worker */
67*4dc78e53SAndroid Build Coastguard Worker
rtnl_cls_alloc(void)68*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cls *rtnl_cls_alloc(void)
69*4dc78e53SAndroid Build Coastguard Worker {
70*4dc78e53SAndroid Build Coastguard Worker struct rtnl_tc *tc;
71*4dc78e53SAndroid Build Coastguard Worker
72*4dc78e53SAndroid Build Coastguard Worker tc = TC_CAST(nl_object_alloc(&cls_obj_ops));
73*4dc78e53SAndroid Build Coastguard Worker if (tc)
74*4dc78e53SAndroid Build Coastguard Worker tc->tc_type = RTNL_TC_TYPE_CLS;
75*4dc78e53SAndroid Build Coastguard Worker
76*4dc78e53SAndroid Build Coastguard Worker return (struct rtnl_cls *) tc;
77*4dc78e53SAndroid Build Coastguard Worker }
78*4dc78e53SAndroid Build Coastguard Worker
rtnl_cls_put(struct rtnl_cls * cls)79*4dc78e53SAndroid Build Coastguard Worker void rtnl_cls_put(struct rtnl_cls *cls)
80*4dc78e53SAndroid Build Coastguard Worker {
81*4dc78e53SAndroid Build Coastguard Worker nl_object_put((struct nl_object *) cls);
82*4dc78e53SAndroid Build Coastguard Worker }
83*4dc78e53SAndroid Build Coastguard Worker
84*4dc78e53SAndroid Build Coastguard Worker /** @} */
85*4dc78e53SAndroid Build Coastguard Worker
86*4dc78e53SAndroid Build Coastguard Worker /**
87*4dc78e53SAndroid Build Coastguard Worker * @name Attributes
88*4dc78e53SAndroid Build Coastguard Worker * @{
89*4dc78e53SAndroid Build Coastguard Worker */
90*4dc78e53SAndroid Build Coastguard Worker
rtnl_cls_set_prio(struct rtnl_cls * cls,uint16_t prio)91*4dc78e53SAndroid Build Coastguard Worker void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio)
92*4dc78e53SAndroid Build Coastguard Worker {
93*4dc78e53SAndroid Build Coastguard Worker cls->c_prio = prio;
94*4dc78e53SAndroid Build Coastguard Worker cls->ce_mask |= CLS_ATTR_PRIO;
95*4dc78e53SAndroid Build Coastguard Worker }
96*4dc78e53SAndroid Build Coastguard Worker
rtnl_cls_get_prio(struct rtnl_cls * cls)97*4dc78e53SAndroid Build Coastguard Worker uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls)
98*4dc78e53SAndroid Build Coastguard Worker {
99*4dc78e53SAndroid Build Coastguard Worker if (cls->ce_mask & CLS_ATTR_PRIO)
100*4dc78e53SAndroid Build Coastguard Worker return cls->c_prio;
101*4dc78e53SAndroid Build Coastguard Worker else
102*4dc78e53SAndroid Build Coastguard Worker return 0;
103*4dc78e53SAndroid Build Coastguard Worker }
104*4dc78e53SAndroid Build Coastguard Worker
rtnl_cls_set_protocol(struct rtnl_cls * cls,uint16_t protocol)105*4dc78e53SAndroid Build Coastguard Worker void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol)
106*4dc78e53SAndroid Build Coastguard Worker {
107*4dc78e53SAndroid Build Coastguard Worker cls->c_protocol = protocol;
108*4dc78e53SAndroid Build Coastguard Worker cls->ce_mask |= CLS_ATTR_PROTOCOL;
109*4dc78e53SAndroid Build Coastguard Worker }
110*4dc78e53SAndroid Build Coastguard Worker
rtnl_cls_get_protocol(struct rtnl_cls * cls)111*4dc78e53SAndroid Build Coastguard Worker uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls)
112*4dc78e53SAndroid Build Coastguard Worker {
113*4dc78e53SAndroid Build Coastguard Worker if (cls->ce_mask & CLS_ATTR_PROTOCOL)
114*4dc78e53SAndroid Build Coastguard Worker return cls->c_protocol;
115*4dc78e53SAndroid Build Coastguard Worker else
116*4dc78e53SAndroid Build Coastguard Worker return ETH_P_ALL;
117*4dc78e53SAndroid Build Coastguard Worker }
118*4dc78e53SAndroid Build Coastguard Worker
119*4dc78e53SAndroid Build Coastguard Worker /** @} */
120*4dc78e53SAndroid Build Coastguard Worker
121*4dc78e53SAndroid Build Coastguard Worker
122*4dc78e53SAndroid Build Coastguard Worker /**
123*4dc78e53SAndroid Build Coastguard Worker * @name Addition/Modification/Deletion
124*4dc78e53SAndroid Build Coastguard Worker * @{
125*4dc78e53SAndroid Build Coastguard Worker */
126*4dc78e53SAndroid Build Coastguard Worker
127*4dc78e53SAndroid Build Coastguard Worker /**
128*4dc78e53SAndroid Build Coastguard Worker * Build a netlink message requesting the addition of a classifier
129*4dc78e53SAndroid Build Coastguard Worker * @arg cls Classifier to add
130*4dc78e53SAndroid Build Coastguard Worker * @arg flags Additional netlink message flags
131*4dc78e53SAndroid Build Coastguard Worker * @arg result Pointer to store resulting netlink message
132*4dc78e53SAndroid Build Coastguard Worker *
133*4dc78e53SAndroid Build Coastguard Worker * The behaviour of this function is identical to rtnl_cls_add() with
134*4dc78e53SAndroid Build Coastguard Worker * the exception that it will not send the message but return it int the
135*4dc78e53SAndroid Build Coastguard Worker * provided return pointer instead.
136*4dc78e53SAndroid Build Coastguard Worker *
137*4dc78e53SAndroid Build Coastguard Worker * @see rtnl_cls_add()
138*4dc78e53SAndroid Build Coastguard Worker *
139*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
140*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_build_add_request(struct rtnl_cls * cls,int flags,struct nl_msg ** result)141*4dc78e53SAndroid Build Coastguard Worker int rtnl_cls_build_add_request(struct rtnl_cls *cls, int flags,
142*4dc78e53SAndroid Build Coastguard Worker struct nl_msg **result)
143*4dc78e53SAndroid Build Coastguard Worker {
144*4dc78e53SAndroid Build Coastguard Worker if (!(flags & NLM_F_CREATE) && !(cls->ce_mask & CLS_ATTR_PRIO)) {
145*4dc78e53SAndroid Build Coastguard Worker APPBUG("prio must be specified if not a new classifier");
146*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
147*4dc78e53SAndroid Build Coastguard Worker }
148*4dc78e53SAndroid Build Coastguard Worker
149*4dc78e53SAndroid Build Coastguard Worker return cls_build(cls, RTM_NEWTFILTER, flags, result);
150*4dc78e53SAndroid Build Coastguard Worker }
151*4dc78e53SAndroid Build Coastguard Worker
152*4dc78e53SAndroid Build Coastguard Worker /**
153*4dc78e53SAndroid Build Coastguard Worker * Add/Update classifier
154*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket
155*4dc78e53SAndroid Build Coastguard Worker * @arg cls Classifier to add/update
156*4dc78e53SAndroid Build Coastguard Worker * @arg flags Additional netlink message flags
157*4dc78e53SAndroid Build Coastguard Worker *
158*4dc78e53SAndroid Build Coastguard Worker * Builds a \c RTM_NEWTFILTER netlink message requesting the addition
159*4dc78e53SAndroid Build Coastguard Worker * of a new classifier and sends the message to the kernel. The
160*4dc78e53SAndroid Build Coastguard Worker * configuration of the classifier is derived from the attributes of
161*4dc78e53SAndroid Build Coastguard Worker * the specified traffic class.
162*4dc78e53SAndroid Build Coastguard Worker *
163*4dc78e53SAndroid Build Coastguard Worker * The following flags may be specified:
164*4dc78e53SAndroid Build Coastguard Worker * - \c NLM_F_CREATE: Create classifier if it does not exist,
165*4dc78e53SAndroid Build Coastguard Worker * otherwise -NLE_OBJ_NOTFOUND is returned.
166*4dc78e53SAndroid Build Coastguard Worker * - \c NLM_F_EXCL: Return -NLE_EXISTS if a classifier with
167*4dc78e53SAndroid Build Coastguard Worker * matching handle exists already.
168*4dc78e53SAndroid Build Coastguard Worker *
169*4dc78e53SAndroid Build Coastguard Worker * Existing classifiers with matching handles will be updated, unless
170*4dc78e53SAndroid Build Coastguard Worker * the flag \c NLM_F_EXCL is specified. If no matching classifier
171*4dc78e53SAndroid Build Coastguard Worker * exists, it will be created if the flag \c NLM_F_CREATE is set,
172*4dc78e53SAndroid Build Coastguard Worker * otherwise the error -NLE_OBJ_NOTFOUND is returned.
173*4dc78e53SAndroid Build Coastguard Worker *
174*4dc78e53SAndroid Build Coastguard Worker * If the parent qdisc does not support classes, the error
175*4dc78e53SAndroid Build Coastguard Worker * \c NLE_OPNOTSUPP is returned.
176*4dc78e53SAndroid Build Coastguard Worker *
177*4dc78e53SAndroid Build Coastguard Worker * After sending, the function will wait for the ACK or an eventual
178*4dc78e53SAndroid Build Coastguard Worker * error message to be received and will therefore block until the
179*4dc78e53SAndroid Build Coastguard Worker * operation has been completed.
180*4dc78e53SAndroid Build Coastguard Worker *
181*4dc78e53SAndroid Build Coastguard Worker * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
182*4dc78e53SAndroid Build Coastguard Worker * this function to return immediately after sending. In this case,
183*4dc78e53SAndroid Build Coastguard Worker * it is the responsibility of the caller to handle any error
184*4dc78e53SAndroid Build Coastguard Worker * messages returned.
185*4dc78e53SAndroid Build Coastguard Worker *
186*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
187*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_add(struct nl_sock * sk,struct rtnl_cls * cls,int flags)188*4dc78e53SAndroid Build Coastguard Worker int rtnl_cls_add(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
189*4dc78e53SAndroid Build Coastguard Worker {
190*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg;
191*4dc78e53SAndroid Build Coastguard Worker int err;
192*4dc78e53SAndroid Build Coastguard Worker
193*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_cls_build_add_request(cls, flags, &msg)) < 0)
194*4dc78e53SAndroid Build Coastguard Worker return err;
195*4dc78e53SAndroid Build Coastguard Worker
196*4dc78e53SAndroid Build Coastguard Worker return nl_send_sync(sk, msg);
197*4dc78e53SAndroid Build Coastguard Worker }
198*4dc78e53SAndroid Build Coastguard Worker
199*4dc78e53SAndroid Build Coastguard Worker /**
200*4dc78e53SAndroid Build Coastguard Worker * Build a netlink message to change classifier attributes
201*4dc78e53SAndroid Build Coastguard Worker * @arg cls classifier to change
202*4dc78e53SAndroid Build Coastguard Worker * @arg flags additional netlink message flags
203*4dc78e53SAndroid Build Coastguard Worker * @arg result Pointer to store resulting message.
204*4dc78e53SAndroid Build Coastguard Worker *
205*4dc78e53SAndroid Build Coastguard Worker * Builds a new netlink message requesting a change of a neigh
206*4dc78e53SAndroid Build Coastguard Worker * attributes. The netlink message header isn't fully equipped with
207*4dc78e53SAndroid Build Coastguard Worker * all relevant fields and must thus be sent out via nl_send_auto_complete()
208*4dc78e53SAndroid Build Coastguard Worker * or supplemented as needed.
209*4dc78e53SAndroid Build Coastguard Worker *
210*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
211*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_build_change_request(struct rtnl_cls * cls,int flags,struct nl_msg ** result)212*4dc78e53SAndroid Build Coastguard Worker int rtnl_cls_build_change_request(struct rtnl_cls *cls, int flags,
213*4dc78e53SAndroid Build Coastguard Worker struct nl_msg **result)
214*4dc78e53SAndroid Build Coastguard Worker {
215*4dc78e53SAndroid Build Coastguard Worker return cls_build(cls, RTM_NEWTFILTER, NLM_F_REPLACE | flags, result);
216*4dc78e53SAndroid Build Coastguard Worker }
217*4dc78e53SAndroid Build Coastguard Worker
218*4dc78e53SAndroid Build Coastguard Worker /**
219*4dc78e53SAndroid Build Coastguard Worker * Change a classifier
220*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket.
221*4dc78e53SAndroid Build Coastguard Worker * @arg cls classifier to change
222*4dc78e53SAndroid Build Coastguard Worker * @arg flags additional netlink message flags
223*4dc78e53SAndroid Build Coastguard Worker *
224*4dc78e53SAndroid Build Coastguard Worker * Builds a netlink message by calling rtnl_cls_build_change_request(),
225*4dc78e53SAndroid Build Coastguard Worker * sends the request to the kernel and waits for the next ACK to be
226*4dc78e53SAndroid Build Coastguard Worker * received and thus blocks until the request has been processed.
227*4dc78e53SAndroid Build Coastguard Worker *
228*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error if an error occured.
229*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_change(struct nl_sock * sk,struct rtnl_cls * cls,int flags)230*4dc78e53SAndroid Build Coastguard Worker int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
231*4dc78e53SAndroid Build Coastguard Worker {
232*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg;
233*4dc78e53SAndroid Build Coastguard Worker int err;
234*4dc78e53SAndroid Build Coastguard Worker
235*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_cls_build_change_request(cls, flags, &msg)) < 0)
236*4dc78e53SAndroid Build Coastguard Worker return err;
237*4dc78e53SAndroid Build Coastguard Worker
238*4dc78e53SAndroid Build Coastguard Worker return nl_send_sync(sk, msg);
239*4dc78e53SAndroid Build Coastguard Worker }
240*4dc78e53SAndroid Build Coastguard Worker
241*4dc78e53SAndroid Build Coastguard Worker /**
242*4dc78e53SAndroid Build Coastguard Worker * Build netlink message requesting the deletion of a classifier
243*4dc78e53SAndroid Build Coastguard Worker * @arg cls Classifier to delete
244*4dc78e53SAndroid Build Coastguard Worker * @arg flags Additional netlink message flags
245*4dc78e53SAndroid Build Coastguard Worker * @arg result Pointer to store resulting netlink message
246*4dc78e53SAndroid Build Coastguard Worker *
247*4dc78e53SAndroid Build Coastguard Worker * The behaviour of this function is identical to rtnl_cls_delete() with
248*4dc78e53SAndroid Build Coastguard Worker * the exception that it will not send the message but return it in the
249*4dc78e53SAndroid Build Coastguard Worker * provided return pointer instead.
250*4dc78e53SAndroid Build Coastguard Worker *
251*4dc78e53SAndroid Build Coastguard Worker * @see rtnl_cls_delete()
252*4dc78e53SAndroid Build Coastguard Worker *
253*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
254*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_build_delete_request(struct rtnl_cls * cls,int flags,struct nl_msg ** result)255*4dc78e53SAndroid Build Coastguard Worker int rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags,
256*4dc78e53SAndroid Build Coastguard Worker struct nl_msg **result)
257*4dc78e53SAndroid Build Coastguard Worker {
258*4dc78e53SAndroid Build Coastguard Worker uint32_t required = CLS_ATTR_PRIO;
259*4dc78e53SAndroid Build Coastguard Worker
260*4dc78e53SAndroid Build Coastguard Worker if ((cls->ce_mask & required) != required) {
261*4dc78e53SAndroid Build Coastguard Worker APPBUG("prio must be specified");
262*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
263*4dc78e53SAndroid Build Coastguard Worker }
264*4dc78e53SAndroid Build Coastguard Worker
265*4dc78e53SAndroid Build Coastguard Worker return cls_build(cls, RTM_DELTFILTER, flags, result);
266*4dc78e53SAndroid Build Coastguard Worker }
267*4dc78e53SAndroid Build Coastguard Worker
268*4dc78e53SAndroid Build Coastguard Worker /**
269*4dc78e53SAndroid Build Coastguard Worker * Delete classifier
270*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket
271*4dc78e53SAndroid Build Coastguard Worker * @arg cls Classifier to delete
272*4dc78e53SAndroid Build Coastguard Worker * @arg flags Additional netlink message flags
273*4dc78e53SAndroid Build Coastguard Worker *
274*4dc78e53SAndroid Build Coastguard Worker * Builds a \c RTM_DELTFILTER netlink message requesting the deletion
275*4dc78e53SAndroid Build Coastguard Worker * of a classifier and sends the message to the kernel.
276*4dc78e53SAndroid Build Coastguard Worker *
277*4dc78e53SAndroid Build Coastguard Worker * The message is constructed out of the following attributes:
278*4dc78e53SAndroid Build Coastguard Worker * - \c ifindex (required)
279*4dc78e53SAndroid Build Coastguard Worker * - \c prio (required)
280*4dc78e53SAndroid Build Coastguard Worker * - \c protocol (required)
281*4dc78e53SAndroid Build Coastguard Worker * - \c handle (required)
282*4dc78e53SAndroid Build Coastguard Worker * - \c parent (optional, if not specified parent equals root-qdisc)
283*4dc78e53SAndroid Build Coastguard Worker * - \c kind (optional, must match if provided)
284*4dc78e53SAndroid Build Coastguard Worker *
285*4dc78e53SAndroid Build Coastguard Worker * All other classifier attributes including all class type specific
286*4dc78e53SAndroid Build Coastguard Worker * attributes are ignored.
287*4dc78e53SAndroid Build Coastguard Worker *
288*4dc78e53SAndroid Build Coastguard Worker * After sending, the function will wait for the ACK or an eventual
289*4dc78e53SAndroid Build Coastguard Worker * error message to be received and will therefore block until the
290*4dc78e53SAndroid Build Coastguard Worker * operation has been completed.
291*4dc78e53SAndroid Build Coastguard Worker *
292*4dc78e53SAndroid Build Coastguard Worker * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
293*4dc78e53SAndroid Build Coastguard Worker * this function to return immediately after sending. In this case,
294*4dc78e53SAndroid Build Coastguard Worker * it is the responsibility of the caller to handle any error
295*4dc78e53SAndroid Build Coastguard Worker * messages returned.
296*4dc78e53SAndroid Build Coastguard Worker *
297*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
298*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_delete(struct nl_sock * sk,struct rtnl_cls * cls,int flags)299*4dc78e53SAndroid Build Coastguard Worker int rtnl_cls_delete(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
300*4dc78e53SAndroid Build Coastguard Worker {
301*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg;
302*4dc78e53SAndroid Build Coastguard Worker int err;
303*4dc78e53SAndroid Build Coastguard Worker
304*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_cls_build_delete_request(cls, flags, &msg)) < 0)
305*4dc78e53SAndroid Build Coastguard Worker return err;
306*4dc78e53SAndroid Build Coastguard Worker
307*4dc78e53SAndroid Build Coastguard Worker return nl_send_sync(sk, msg);
308*4dc78e53SAndroid Build Coastguard Worker }
309*4dc78e53SAndroid Build Coastguard Worker
310*4dc78e53SAndroid Build Coastguard Worker /** @} */
311*4dc78e53SAndroid Build Coastguard Worker
312*4dc78e53SAndroid Build Coastguard Worker /**
313*4dc78e53SAndroid Build Coastguard Worker * @name Cache Related Functions
314*4dc78e53SAndroid Build Coastguard Worker * @{
315*4dc78e53SAndroid Build Coastguard Worker */
316*4dc78e53SAndroid Build Coastguard Worker
317*4dc78e53SAndroid Build Coastguard Worker /**
318*4dc78e53SAndroid Build Coastguard Worker * Allocate a cache and fill it with all configured classifiers
319*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket
320*4dc78e53SAndroid Build Coastguard Worker * @arg ifindex Interface index of the network device
321*4dc78e53SAndroid Build Coastguard Worker * @arg parent Parent qdisc/traffic class class
322*4dc78e53SAndroid Build Coastguard Worker * @arg result Pointer to store the created cache
323*4dc78e53SAndroid Build Coastguard Worker *
324*4dc78e53SAndroid Build Coastguard Worker * Allocates a new classifier cache and fills it with a list of all
325*4dc78e53SAndroid Build Coastguard Worker * configured classifier attached to the specified parent qdisc/traffic
326*4dc78e53SAndroid Build Coastguard Worker * class on the specified network device. Release the cache with
327*4dc78e53SAndroid Build Coastguard Worker * nl_cache_free().
328*4dc78e53SAndroid Build Coastguard Worker *
329*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
330*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_alloc_cache(struct nl_sock * sk,int ifindex,uint32_t parent,struct nl_cache ** result)331*4dc78e53SAndroid Build Coastguard Worker int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent,
332*4dc78e53SAndroid Build Coastguard Worker struct nl_cache **result)
333*4dc78e53SAndroid Build Coastguard Worker {
334*4dc78e53SAndroid Build Coastguard Worker struct nl_cache * cache;
335*4dc78e53SAndroid Build Coastguard Worker int err;
336*4dc78e53SAndroid Build Coastguard Worker
337*4dc78e53SAndroid Build Coastguard Worker if (!(cache = nl_cache_alloc(&rtnl_cls_ops)))
338*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
339*4dc78e53SAndroid Build Coastguard Worker
340*4dc78e53SAndroid Build Coastguard Worker cache->c_iarg1 = ifindex;
341*4dc78e53SAndroid Build Coastguard Worker cache->c_iarg2 = parent;
342*4dc78e53SAndroid Build Coastguard Worker
343*4dc78e53SAndroid Build Coastguard Worker if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
344*4dc78e53SAndroid Build Coastguard Worker nl_cache_free(cache);
345*4dc78e53SAndroid Build Coastguard Worker return err;
346*4dc78e53SAndroid Build Coastguard Worker }
347*4dc78e53SAndroid Build Coastguard Worker
348*4dc78e53SAndroid Build Coastguard Worker *result = cache;
349*4dc78e53SAndroid Build Coastguard Worker return 0;
350*4dc78e53SAndroid Build Coastguard Worker }
351*4dc78e53SAndroid Build Coastguard Worker
352*4dc78e53SAndroid Build Coastguard Worker /**
353*4dc78e53SAndroid Build Coastguard Worker * Set interface index and parent handle for classifier cache.
354*4dc78e53SAndroid Build Coastguard Worker * @arg cache Pointer to cache
355*4dc78e53SAndroid Build Coastguard Worker * @arg parent Parent qdisc/traffic class class
356*4dc78e53SAndroid Build Coastguard Worker *
357*4dc78e53SAndroid Build Coastguard Worker * Set the interface index and parent handle of a classifier cache.
358*4dc78e53SAndroid Build Coastguard Worker * This is useful for reusing some existed classifier cache to reduce
359*4dc78e53SAndroid Build Coastguard Worker * the overhead introduced by memory allocation.
360*4dc78e53SAndroid Build Coastguard Worker *
361*4dc78e53SAndroid Build Coastguard Worker * @return void.
362*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_cache_set_tc_params(struct nl_cache * cache,int ifindex,uint32_t parent)363*4dc78e53SAndroid Build Coastguard Worker void rtnl_cls_cache_set_tc_params(struct nl_cache *cache,
364*4dc78e53SAndroid Build Coastguard Worker int ifindex, uint32_t parent)
365*4dc78e53SAndroid Build Coastguard Worker {
366*4dc78e53SAndroid Build Coastguard Worker cache->c_iarg1 = ifindex;
367*4dc78e53SAndroid Build Coastguard Worker cache->c_iarg2 = parent;
368*4dc78e53SAndroid Build Coastguard Worker }
369*4dc78e53SAndroid Build Coastguard Worker
370*4dc78e53SAndroid Build Coastguard Worker /**
371*4dc78e53SAndroid Build Coastguard Worker * Search classifier by interface index, parent and handle
372*4dc78e53SAndroid Build Coastguard Worker * @arg cache Classifier cache
373*4dc78e53SAndroid Build Coastguard Worker * @arg ifindex Interface index
374*4dc78e53SAndroid Build Coastguard Worker * @arg parent Parent
375*4dc78e53SAndroid Build Coastguard Worker * @arg handle Handle
376*4dc78e53SAndroid Build Coastguard Worker *
377*4dc78e53SAndroid Build Coastguard Worker * Searches a classifier cache previously allocated with rtnl_cls_alloc_cache()
378*4dc78e53SAndroid Build Coastguard Worker * and searches for a classifier matching the interface index, parent
379*4dc78e53SAndroid Build Coastguard Worker * and handle.
380*4dc78e53SAndroid Build Coastguard Worker *
381*4dc78e53SAndroid Build Coastguard Worker * The reference counter is incremented before returning the classifier,
382*4dc78e53SAndroid Build Coastguard Worker * therefore the reference must be given back with rtnl_cls_put() after usage.
383*4dc78e53SAndroid Build Coastguard Worker *
384*4dc78e53SAndroid Build Coastguard Worker * @return Classifier or NULL if no match was found.
385*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_find_by_handle(struct nl_cache * cache,int ifindex,uint32_t parent,uint32_t handle)386*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cls *rtnl_cls_find_by_handle(struct nl_cache *cache, int ifindex, uint32_t parent,
387*4dc78e53SAndroid Build Coastguard Worker uint32_t handle)
388*4dc78e53SAndroid Build Coastguard Worker {
389*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cls *cls;
390*4dc78e53SAndroid Build Coastguard Worker
391*4dc78e53SAndroid Build Coastguard Worker if (cache->c_ops != &rtnl_cls_ops)
392*4dc78e53SAndroid Build Coastguard Worker return NULL;
393*4dc78e53SAndroid Build Coastguard Worker
394*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry(cls, &cache->c_items, ce_list) {
395*4dc78e53SAndroid Build Coastguard Worker if ((cls->c_parent == parent) &&
396*4dc78e53SAndroid Build Coastguard Worker cls->c_ifindex == ((unsigned)ifindex) &&
397*4dc78e53SAndroid Build Coastguard Worker (cls->c_handle == handle)) {
398*4dc78e53SAndroid Build Coastguard Worker nl_object_get((struct nl_object *) cls);
399*4dc78e53SAndroid Build Coastguard Worker return cls;
400*4dc78e53SAndroid Build Coastguard Worker }
401*4dc78e53SAndroid Build Coastguard Worker }
402*4dc78e53SAndroid Build Coastguard Worker
403*4dc78e53SAndroid Build Coastguard Worker return NULL;
404*4dc78e53SAndroid Build Coastguard Worker }
405*4dc78e53SAndroid Build Coastguard Worker
406*4dc78e53SAndroid Build Coastguard Worker /**
407*4dc78e53SAndroid Build Coastguard Worker * Search classifier by interface index, parent and priority
408*4dc78e53SAndroid Build Coastguard Worker * @arg cache Classifier cache
409*4dc78e53SAndroid Build Coastguard Worker * @arg ifindex Interface index
410*4dc78e53SAndroid Build Coastguard Worker * @arg parent Parent
411*4dc78e53SAndroid Build Coastguard Worker * @arg prio Priority
412*4dc78e53SAndroid Build Coastguard Worker *
413*4dc78e53SAndroid Build Coastguard Worker * Searches a classifier cache previously allocated with rtnl_cls_alloc_cache()
414*4dc78e53SAndroid Build Coastguard Worker * and searches for a classifier matching the interface index, parent
415*4dc78e53SAndroid Build Coastguard Worker * and prio.
416*4dc78e53SAndroid Build Coastguard Worker *
417*4dc78e53SAndroid Build Coastguard Worker * The reference counter is incremented before returning the classifier,
418*4dc78e53SAndroid Build Coastguard Worker * therefore the reference must be given back with rtnl_cls_put() after usage.
419*4dc78e53SAndroid Build Coastguard Worker *
420*4dc78e53SAndroid Build Coastguard Worker * @return Classifier or NULL if no match was found.
421*4dc78e53SAndroid Build Coastguard Worker */
rtnl_cls_find_by_prio(struct nl_cache * cache,int ifindex,uint32_t parent,uint16_t prio)422*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cls *rtnl_cls_find_by_prio(struct nl_cache *cache, int ifindex,
423*4dc78e53SAndroid Build Coastguard Worker uint32_t parent, uint16_t prio)
424*4dc78e53SAndroid Build Coastguard Worker {
425*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cls *cls;
426*4dc78e53SAndroid Build Coastguard Worker
427*4dc78e53SAndroid Build Coastguard Worker if (cache->c_ops != &rtnl_cls_ops)
428*4dc78e53SAndroid Build Coastguard Worker return NULL;
429*4dc78e53SAndroid Build Coastguard Worker
430*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry(cls, &cache->c_items, ce_list) {
431*4dc78e53SAndroid Build Coastguard Worker if ((cls->c_parent == parent) &&
432*4dc78e53SAndroid Build Coastguard Worker cls->c_ifindex == ((unsigned)ifindex) &&
433*4dc78e53SAndroid Build Coastguard Worker (cls->c_prio == prio)) {
434*4dc78e53SAndroid Build Coastguard Worker nl_object_get((struct nl_object *)cls);
435*4dc78e53SAndroid Build Coastguard Worker return cls;
436*4dc78e53SAndroid Build Coastguard Worker }
437*4dc78e53SAndroid Build Coastguard Worker }
438*4dc78e53SAndroid Build Coastguard Worker
439*4dc78e53SAndroid Build Coastguard Worker return NULL;
440*4dc78e53SAndroid Build Coastguard Worker }
441*4dc78e53SAndroid Build Coastguard Worker
442*4dc78e53SAndroid Build Coastguard Worker /** @} */
443*4dc78e53SAndroid Build Coastguard Worker
cls_dump_line(struct rtnl_tc * tc,struct nl_dump_params * p)444*4dc78e53SAndroid Build Coastguard Worker static void cls_dump_line(struct rtnl_tc *tc, struct nl_dump_params *p)
445*4dc78e53SAndroid Build Coastguard Worker {
446*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cls *cls = (struct rtnl_cls *) tc;
447*4dc78e53SAndroid Build Coastguard Worker char buf[32];
448*4dc78e53SAndroid Build Coastguard Worker
449*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " prio %u protocol %s", cls->c_prio,
450*4dc78e53SAndroid Build Coastguard Worker nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
451*4dc78e53SAndroid Build Coastguard Worker }
452*4dc78e53SAndroid Build Coastguard Worker
cls_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)453*4dc78e53SAndroid Build Coastguard Worker static int cls_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
454*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *nlh, struct nl_parser_param *pp)
455*4dc78e53SAndroid Build Coastguard Worker {
456*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cls *cls;
457*4dc78e53SAndroid Build Coastguard Worker int err;
458*4dc78e53SAndroid Build Coastguard Worker
459*4dc78e53SAndroid Build Coastguard Worker if (!(cls = rtnl_cls_alloc()))
460*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
461*4dc78e53SAndroid Build Coastguard Worker
462*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_tc_msg_parse(nlh, TC_CAST(cls))) < 0)
463*4dc78e53SAndroid Build Coastguard Worker goto errout;
464*4dc78e53SAndroid Build Coastguard Worker
465*4dc78e53SAndroid Build Coastguard Worker cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
466*4dc78e53SAndroid Build Coastguard Worker if (cls->c_prio)
467*4dc78e53SAndroid Build Coastguard Worker cls->ce_mask |= CLS_ATTR_PRIO;
468*4dc78e53SAndroid Build Coastguard Worker cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
469*4dc78e53SAndroid Build Coastguard Worker if (cls->c_protocol)
470*4dc78e53SAndroid Build Coastguard Worker cls->ce_mask |= CLS_ATTR_PROTOCOL;
471*4dc78e53SAndroid Build Coastguard Worker
472*4dc78e53SAndroid Build Coastguard Worker err = pp->pp_cb(OBJ_CAST(cls), pp);
473*4dc78e53SAndroid Build Coastguard Worker errout:
474*4dc78e53SAndroid Build Coastguard Worker rtnl_cls_put(cls);
475*4dc78e53SAndroid Build Coastguard Worker
476*4dc78e53SAndroid Build Coastguard Worker return err;
477*4dc78e53SAndroid Build Coastguard Worker }
478*4dc78e53SAndroid Build Coastguard Worker
cls_request_update(struct nl_cache * cache,struct nl_sock * sk)479*4dc78e53SAndroid Build Coastguard Worker static int cls_request_update(struct nl_cache *cache, struct nl_sock *sk)
480*4dc78e53SAndroid Build Coastguard Worker {
481*4dc78e53SAndroid Build Coastguard Worker struct tcmsg tchdr = {
482*4dc78e53SAndroid Build Coastguard Worker .tcm_family = AF_UNSPEC,
483*4dc78e53SAndroid Build Coastguard Worker .tcm_ifindex = cache->c_iarg1,
484*4dc78e53SAndroid Build Coastguard Worker .tcm_parent = cache->c_iarg2,
485*4dc78e53SAndroid Build Coastguard Worker };
486*4dc78e53SAndroid Build Coastguard Worker
487*4dc78e53SAndroid Build Coastguard Worker return nl_send_simple(sk, RTM_GETTFILTER, NLM_F_DUMP, &tchdr,
488*4dc78e53SAndroid Build Coastguard Worker sizeof(tchdr));
489*4dc78e53SAndroid Build Coastguard Worker }
490*4dc78e53SAndroid Build Coastguard Worker
491*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_type_ops cls_ops = {
492*4dc78e53SAndroid Build Coastguard Worker .tt_type = RTNL_TC_TYPE_CLS,
493*4dc78e53SAndroid Build Coastguard Worker .tt_dump_prefix = "cls",
494*4dc78e53SAndroid Build Coastguard Worker .tt_dump = {
495*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_LINE] = cls_dump_line,
496*4dc78e53SAndroid Build Coastguard Worker },
497*4dc78e53SAndroid Build Coastguard Worker };
498*4dc78e53SAndroid Build Coastguard Worker
499*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_cls_ops = {
500*4dc78e53SAndroid Build Coastguard Worker .co_name = "route/cls",
501*4dc78e53SAndroid Build Coastguard Worker .co_hdrsize = sizeof(struct tcmsg),
502*4dc78e53SAndroid Build Coastguard Worker .co_msgtypes = {
503*4dc78e53SAndroid Build Coastguard Worker { RTM_NEWTFILTER, NL_ACT_NEW, "new" },
504*4dc78e53SAndroid Build Coastguard Worker { RTM_DELTFILTER, NL_ACT_DEL, "del" },
505*4dc78e53SAndroid Build Coastguard Worker { RTM_GETTFILTER, NL_ACT_GET, "get" },
506*4dc78e53SAndroid Build Coastguard Worker END_OF_MSGTYPES_LIST,
507*4dc78e53SAndroid Build Coastguard Worker },
508*4dc78e53SAndroid Build Coastguard Worker .co_protocol = NETLINK_ROUTE,
509*4dc78e53SAndroid Build Coastguard Worker .co_groups = tc_groups,
510*4dc78e53SAndroid Build Coastguard Worker .co_request_update = cls_request_update,
511*4dc78e53SAndroid Build Coastguard Worker .co_msg_parser = cls_msg_parser,
512*4dc78e53SAndroid Build Coastguard Worker .co_obj_ops = &cls_obj_ops,
513*4dc78e53SAndroid Build Coastguard Worker };
514*4dc78e53SAndroid Build Coastguard Worker
515*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops cls_obj_ops = {
516*4dc78e53SAndroid Build Coastguard Worker .oo_name = "route/cls",
517*4dc78e53SAndroid Build Coastguard Worker .oo_size = sizeof(struct rtnl_cls),
518*4dc78e53SAndroid Build Coastguard Worker .oo_free_data = rtnl_tc_free_data,
519*4dc78e53SAndroid Build Coastguard Worker .oo_clone = rtnl_tc_clone,
520*4dc78e53SAndroid Build Coastguard Worker .oo_dump = {
521*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_LINE] = rtnl_tc_dump_line,
522*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_DETAILS] = rtnl_tc_dump_details,
523*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_STATS] = rtnl_tc_dump_stats,
524*4dc78e53SAndroid Build Coastguard Worker },
525*4dc78e53SAndroid Build Coastguard Worker .oo_compare = rtnl_tc_compare,
526*4dc78e53SAndroid Build Coastguard Worker .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
527*4dc78e53SAndroid Build Coastguard Worker };
528*4dc78e53SAndroid Build Coastguard Worker
cls_init(void)529*4dc78e53SAndroid Build Coastguard Worker static void _nl_init cls_init(void)
530*4dc78e53SAndroid Build Coastguard Worker {
531*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_type_register(&cls_ops);
532*4dc78e53SAndroid Build Coastguard Worker nl_cache_mngt_register(&rtnl_cls_ops);
533*4dc78e53SAndroid Build Coastguard Worker }
534*4dc78e53SAndroid Build Coastguard Worker
cls_exit(void)535*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit cls_exit(void)
536*4dc78e53SAndroid Build Coastguard Worker {
537*4dc78e53SAndroid Build Coastguard Worker nl_cache_mngt_unregister(&rtnl_cls_ops);
538*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_type_unregister(&cls_ops);
539*4dc78e53SAndroid Build Coastguard Worker }
540*4dc78e53SAndroid Build Coastguard Worker
541*4dc78e53SAndroid Build Coastguard Worker /** @} */
542