xref: /aosp_15_r20/external/libnl/lib/route/cls.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-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