1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2008-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 cls
8*4dc78e53SAndroid Build Coastguard Worker * @defgroup cls_basic Basic Classifier
9*4dc78e53SAndroid Build Coastguard Worker *
10*4dc78e53SAndroid Build Coastguard Worker * @par Introduction
11*4dc78e53SAndroid Build Coastguard Worker * The basic classifier is the simplest form of a classifier. It does
12*4dc78e53SAndroid Build Coastguard Worker * not have any special classification capabilities, instead it can be
13*4dc78e53SAndroid Build Coastguard Worker * used to classify exclusively based on extended matches or to
14*4dc78e53SAndroid Build Coastguard Worker * create a "catch-all" filter.
15*4dc78e53SAndroid Build Coastguard Worker *
16*4dc78e53SAndroid Build Coastguard Worker * @{
17*4dc78e53SAndroid Build Coastguard Worker */
18*4dc78e53SAndroid Build Coastguard Worker
19*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
20*4dc78e53SAndroid Build Coastguard Worker
21*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
22*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/classifier.h>
23*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/action.h>
24*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/cls/basic.h>
25*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/cls/ematch.h>
26*4dc78e53SAndroid Build Coastguard Worker
27*4dc78e53SAndroid Build Coastguard Worker #include "tc-api.h"
28*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-route/nl-route.h"
29*4dc78e53SAndroid Build Coastguard Worker
30*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic
31*4dc78e53SAndroid Build Coastguard Worker {
32*4dc78e53SAndroid Build Coastguard Worker uint32_t b_target;
33*4dc78e53SAndroid Build Coastguard Worker struct rtnl_ematch_tree * b_ematch;
34*4dc78e53SAndroid Build Coastguard Worker int b_mask;
35*4dc78e53SAndroid Build Coastguard Worker struct rtnl_act * b_act;
36*4dc78e53SAndroid Build Coastguard Worker };
37*4dc78e53SAndroid Build Coastguard Worker
38*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
39*4dc78e53SAndroid Build Coastguard Worker #define BASIC_ATTR_TARGET 0x001
40*4dc78e53SAndroid Build Coastguard Worker #define BASIC_ATTR_EMATCH 0x002
41*4dc78e53SAndroid Build Coastguard Worker #define BASIC_ATTR_ACTION 0x004
42*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
43*4dc78e53SAndroid Build Coastguard Worker
44*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy basic_policy[TCA_BASIC_MAX+1] = {
45*4dc78e53SAndroid Build Coastguard Worker [TCA_BASIC_CLASSID] = { .type = NLA_U32 },
46*4dc78e53SAndroid Build Coastguard Worker [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED },
47*4dc78e53SAndroid Build Coastguard Worker };
48*4dc78e53SAndroid Build Coastguard Worker
basic_clone(void * _dst,void * _src)49*4dc78e53SAndroid Build Coastguard Worker static int basic_clone(void *_dst, void *_src)
50*4dc78e53SAndroid Build Coastguard Worker {
51*4dc78e53SAndroid Build Coastguard Worker return -NLE_OPNOTSUPP;
52*4dc78e53SAndroid Build Coastguard Worker }
53*4dc78e53SAndroid Build Coastguard Worker
basic_free_data(struct rtnl_tc * tc,void * data)54*4dc78e53SAndroid Build Coastguard Worker static void basic_free_data(struct rtnl_tc *tc, void *data)
55*4dc78e53SAndroid Build Coastguard Worker {
56*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b = data;
57*4dc78e53SAndroid Build Coastguard Worker
58*4dc78e53SAndroid Build Coastguard Worker if (!b)
59*4dc78e53SAndroid Build Coastguard Worker return;
60*4dc78e53SAndroid Build Coastguard Worker
61*4dc78e53SAndroid Build Coastguard Worker if (b->b_act)
62*4dc78e53SAndroid Build Coastguard Worker rtnl_act_put_all(&b->b_act);
63*4dc78e53SAndroid Build Coastguard Worker rtnl_ematch_tree_free(b->b_ematch);
64*4dc78e53SAndroid Build Coastguard Worker }
65*4dc78e53SAndroid Build Coastguard Worker
basic_msg_parser(struct rtnl_tc * tc,void * data)66*4dc78e53SAndroid Build Coastguard Worker static int basic_msg_parser(struct rtnl_tc *tc, void *data)
67*4dc78e53SAndroid Build Coastguard Worker {
68*4dc78e53SAndroid Build Coastguard Worker struct nlattr *tb[TCA_BASIC_MAX + 1];
69*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b = data;
70*4dc78e53SAndroid Build Coastguard Worker int err;
71*4dc78e53SAndroid Build Coastguard Worker
72*4dc78e53SAndroid Build Coastguard Worker err = tca_parse(tb, TCA_BASIC_MAX, tc, basic_policy);
73*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
74*4dc78e53SAndroid Build Coastguard Worker return err;
75*4dc78e53SAndroid Build Coastguard Worker
76*4dc78e53SAndroid Build Coastguard Worker if (tb[TCA_BASIC_CLASSID]) {
77*4dc78e53SAndroid Build Coastguard Worker b->b_target = nla_get_u32(tb[TCA_BASIC_CLASSID]);
78*4dc78e53SAndroid Build Coastguard Worker b->b_mask |= BASIC_ATTR_TARGET;
79*4dc78e53SAndroid Build Coastguard Worker }
80*4dc78e53SAndroid Build Coastguard Worker
81*4dc78e53SAndroid Build Coastguard Worker if (tb[TCA_BASIC_EMATCHES]) {
82*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_ematch_parse_attr(tb[TCA_BASIC_EMATCHES],
83*4dc78e53SAndroid Build Coastguard Worker &b->b_ematch)) < 0)
84*4dc78e53SAndroid Build Coastguard Worker return err;
85*4dc78e53SAndroid Build Coastguard Worker
86*4dc78e53SAndroid Build Coastguard Worker if (b->b_ematch)
87*4dc78e53SAndroid Build Coastguard Worker b->b_mask |= BASIC_ATTR_EMATCH;
88*4dc78e53SAndroid Build Coastguard Worker }
89*4dc78e53SAndroid Build Coastguard Worker if (tb[TCA_BASIC_ACT]) {
90*4dc78e53SAndroid Build Coastguard Worker b->b_mask |= BASIC_ATTR_ACTION;
91*4dc78e53SAndroid Build Coastguard Worker err = rtnl_act_parse(&b->b_act, tb[TCA_BASIC_ACT]);
92*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
93*4dc78e53SAndroid Build Coastguard Worker return err;
94*4dc78e53SAndroid Build Coastguard Worker }
95*4dc78e53SAndroid Build Coastguard Worker
96*4dc78e53SAndroid Build Coastguard Worker return 0;
97*4dc78e53SAndroid Build Coastguard Worker }
98*4dc78e53SAndroid Build Coastguard Worker
basic_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)99*4dc78e53SAndroid Build Coastguard Worker static void basic_dump_line(struct rtnl_tc *tc, void *data,
100*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params *p)
101*4dc78e53SAndroid Build Coastguard Worker {
102*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b = data;
103*4dc78e53SAndroid Build Coastguard Worker char buf[32];
104*4dc78e53SAndroid Build Coastguard Worker
105*4dc78e53SAndroid Build Coastguard Worker if (!b)
106*4dc78e53SAndroid Build Coastguard Worker return;
107*4dc78e53SAndroid Build Coastguard Worker
108*4dc78e53SAndroid Build Coastguard Worker if (b->b_mask & BASIC_ATTR_EMATCH)
109*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " ematch");
110*4dc78e53SAndroid Build Coastguard Worker else
111*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " match-all");
112*4dc78e53SAndroid Build Coastguard Worker
113*4dc78e53SAndroid Build Coastguard Worker if (b->b_mask & BASIC_ATTR_TARGET)
114*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " target %s",
115*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_handle2str(b->b_target, buf, sizeof(buf)));
116*4dc78e53SAndroid Build Coastguard Worker }
117*4dc78e53SAndroid Build Coastguard Worker
basic_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)118*4dc78e53SAndroid Build Coastguard Worker static void basic_dump_details(struct rtnl_tc *tc, void *data,
119*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params *p)
120*4dc78e53SAndroid Build Coastguard Worker {
121*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b = data;
122*4dc78e53SAndroid Build Coastguard Worker
123*4dc78e53SAndroid Build Coastguard Worker if (!b)
124*4dc78e53SAndroid Build Coastguard Worker return;
125*4dc78e53SAndroid Build Coastguard Worker
126*4dc78e53SAndroid Build Coastguard Worker if (b->b_mask & BASIC_ATTR_EMATCH) {
127*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, " ematch ");
128*4dc78e53SAndroid Build Coastguard Worker rtnl_ematch_tree_dump(b->b_ematch, p);
129*4dc78e53SAndroid Build Coastguard Worker } else
130*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "no options.\n");
131*4dc78e53SAndroid Build Coastguard Worker }
132*4dc78e53SAndroid Build Coastguard Worker
basic_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)133*4dc78e53SAndroid Build Coastguard Worker static int basic_msg_fill(struct rtnl_tc *tc, void *data,
134*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg)
135*4dc78e53SAndroid Build Coastguard Worker {
136*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b = data;
137*4dc78e53SAndroid Build Coastguard Worker
138*4dc78e53SAndroid Build Coastguard Worker if (!b)
139*4dc78e53SAndroid Build Coastguard Worker return 0;
140*4dc78e53SAndroid Build Coastguard Worker
141*4dc78e53SAndroid Build Coastguard Worker if (b->b_mask & BASIC_ATTR_TARGET)
142*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_target);
143*4dc78e53SAndroid Build Coastguard Worker
144*4dc78e53SAndroid Build Coastguard Worker if (b->b_mask & BASIC_ATTR_EMATCH &&
145*4dc78e53SAndroid Build Coastguard Worker rtnl_ematch_fill_attr(msg, TCA_BASIC_EMATCHES, b->b_ematch) < 0)
146*4dc78e53SAndroid Build Coastguard Worker goto nla_put_failure;
147*4dc78e53SAndroid Build Coastguard Worker
148*4dc78e53SAndroid Build Coastguard Worker if (b->b_mask & BASIC_ATTR_ACTION) {
149*4dc78e53SAndroid Build Coastguard Worker int err;
150*4dc78e53SAndroid Build Coastguard Worker
151*4dc78e53SAndroid Build Coastguard Worker err = rtnl_act_fill(msg, TCA_BASIC_ACT, b->b_act);
152*4dc78e53SAndroid Build Coastguard Worker if (err)
153*4dc78e53SAndroid Build Coastguard Worker return err;
154*4dc78e53SAndroid Build Coastguard Worker }
155*4dc78e53SAndroid Build Coastguard Worker
156*4dc78e53SAndroid Build Coastguard Worker return 0;
157*4dc78e53SAndroid Build Coastguard Worker
158*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
159*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
160*4dc78e53SAndroid Build Coastguard Worker }
161*4dc78e53SAndroid Build Coastguard Worker
162*4dc78e53SAndroid Build Coastguard Worker /**
163*4dc78e53SAndroid Build Coastguard Worker * @name Attribute Modifications
164*4dc78e53SAndroid Build Coastguard Worker * @{
165*4dc78e53SAndroid Build Coastguard Worker */
166*4dc78e53SAndroid Build Coastguard Worker
rtnl_basic_set_target(struct rtnl_cls * cls,uint32_t target)167*4dc78e53SAndroid Build Coastguard Worker void rtnl_basic_set_target(struct rtnl_cls *cls, uint32_t target)
168*4dc78e53SAndroid Build Coastguard Worker {
169*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b;
170*4dc78e53SAndroid Build Coastguard Worker
171*4dc78e53SAndroid Build Coastguard Worker if (!(b = rtnl_tc_data(TC_CAST(cls))))
172*4dc78e53SAndroid Build Coastguard Worker return;
173*4dc78e53SAndroid Build Coastguard Worker
174*4dc78e53SAndroid Build Coastguard Worker b->b_target = target;
175*4dc78e53SAndroid Build Coastguard Worker b->b_mask |= BASIC_ATTR_TARGET;
176*4dc78e53SAndroid Build Coastguard Worker }
177*4dc78e53SAndroid Build Coastguard Worker
rtnl_basic_get_target(struct rtnl_cls * cls)178*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_basic_get_target(struct rtnl_cls *cls)
179*4dc78e53SAndroid Build Coastguard Worker {
180*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b;
181*4dc78e53SAndroid Build Coastguard Worker
182*4dc78e53SAndroid Build Coastguard Worker if (!(b = rtnl_tc_data(TC_CAST(cls))))
183*4dc78e53SAndroid Build Coastguard Worker return 0;
184*4dc78e53SAndroid Build Coastguard Worker
185*4dc78e53SAndroid Build Coastguard Worker return b->b_target;
186*4dc78e53SAndroid Build Coastguard Worker }
187*4dc78e53SAndroid Build Coastguard Worker
rtnl_basic_set_ematch(struct rtnl_cls * cls,struct rtnl_ematch_tree * tree)188*4dc78e53SAndroid Build Coastguard Worker void rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
189*4dc78e53SAndroid Build Coastguard Worker {
190*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b;
191*4dc78e53SAndroid Build Coastguard Worker
192*4dc78e53SAndroid Build Coastguard Worker if (!(b = rtnl_tc_data(TC_CAST(cls))))
193*4dc78e53SAndroid Build Coastguard Worker return;
194*4dc78e53SAndroid Build Coastguard Worker
195*4dc78e53SAndroid Build Coastguard Worker if (b->b_ematch) {
196*4dc78e53SAndroid Build Coastguard Worker rtnl_ematch_tree_free(b->b_ematch);
197*4dc78e53SAndroid Build Coastguard Worker b->b_mask &= ~BASIC_ATTR_EMATCH;
198*4dc78e53SAndroid Build Coastguard Worker }
199*4dc78e53SAndroid Build Coastguard Worker
200*4dc78e53SAndroid Build Coastguard Worker b->b_ematch = tree;
201*4dc78e53SAndroid Build Coastguard Worker
202*4dc78e53SAndroid Build Coastguard Worker if (tree)
203*4dc78e53SAndroid Build Coastguard Worker b->b_mask |= BASIC_ATTR_EMATCH;
204*4dc78e53SAndroid Build Coastguard Worker }
205*4dc78e53SAndroid Build Coastguard Worker
rtnl_basic_get_ematch(struct rtnl_cls * cls)206*4dc78e53SAndroid Build Coastguard Worker struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls)
207*4dc78e53SAndroid Build Coastguard Worker {
208*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b;
209*4dc78e53SAndroid Build Coastguard Worker
210*4dc78e53SAndroid Build Coastguard Worker if (!(b = rtnl_tc_data(TC_CAST(cls))))
211*4dc78e53SAndroid Build Coastguard Worker return NULL;
212*4dc78e53SAndroid Build Coastguard Worker
213*4dc78e53SAndroid Build Coastguard Worker return b->b_ematch;
214*4dc78e53SAndroid Build Coastguard Worker }
215*4dc78e53SAndroid Build Coastguard Worker
rtnl_basic_add_action(struct rtnl_cls * cls,struct rtnl_act * act)216*4dc78e53SAndroid Build Coastguard Worker int rtnl_basic_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
217*4dc78e53SAndroid Build Coastguard Worker {
218*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b;
219*4dc78e53SAndroid Build Coastguard Worker int err;
220*4dc78e53SAndroid Build Coastguard Worker
221*4dc78e53SAndroid Build Coastguard Worker if (!act)
222*4dc78e53SAndroid Build Coastguard Worker return 0;
223*4dc78e53SAndroid Build Coastguard Worker
224*4dc78e53SAndroid Build Coastguard Worker if (!(b = rtnl_tc_data(TC_CAST(cls))))
225*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
226*4dc78e53SAndroid Build Coastguard Worker
227*4dc78e53SAndroid Build Coastguard Worker if ((err = _rtnl_act_append_get(&b->b_act, act)) < 0)
228*4dc78e53SAndroid Build Coastguard Worker return err;
229*4dc78e53SAndroid Build Coastguard Worker
230*4dc78e53SAndroid Build Coastguard Worker b->b_mask |= BASIC_ATTR_ACTION;
231*4dc78e53SAndroid Build Coastguard Worker return 0;
232*4dc78e53SAndroid Build Coastguard Worker }
233*4dc78e53SAndroid Build Coastguard Worker
rtnl_basic_get_action(struct rtnl_cls * cls)234*4dc78e53SAndroid Build Coastguard Worker struct rtnl_act* rtnl_basic_get_action(struct rtnl_cls *cls)
235*4dc78e53SAndroid Build Coastguard Worker {
236*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b;
237*4dc78e53SAndroid Build Coastguard Worker
238*4dc78e53SAndroid Build Coastguard Worker if (!(b = rtnl_tc_data_peek(TC_CAST(cls))))
239*4dc78e53SAndroid Build Coastguard Worker return NULL;
240*4dc78e53SAndroid Build Coastguard Worker
241*4dc78e53SAndroid Build Coastguard Worker if (!(b->b_mask & BASIC_ATTR_ACTION))
242*4dc78e53SAndroid Build Coastguard Worker return NULL;
243*4dc78e53SAndroid Build Coastguard Worker
244*4dc78e53SAndroid Build Coastguard Worker return b->b_act;
245*4dc78e53SAndroid Build Coastguard Worker }
246*4dc78e53SAndroid Build Coastguard Worker
rtnl_basic_del_action(struct rtnl_cls * cls,struct rtnl_act * act)247*4dc78e53SAndroid Build Coastguard Worker int rtnl_basic_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
248*4dc78e53SAndroid Build Coastguard Worker {
249*4dc78e53SAndroid Build Coastguard Worker struct rtnl_basic *b;
250*4dc78e53SAndroid Build Coastguard Worker int ret;
251*4dc78e53SAndroid Build Coastguard Worker
252*4dc78e53SAndroid Build Coastguard Worker if (!act)
253*4dc78e53SAndroid Build Coastguard Worker return 0;
254*4dc78e53SAndroid Build Coastguard Worker
255*4dc78e53SAndroid Build Coastguard Worker if (!(b = rtnl_tc_data(TC_CAST(cls))))
256*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
257*4dc78e53SAndroid Build Coastguard Worker
258*4dc78e53SAndroid Build Coastguard Worker if (!(b->b_mask & BASIC_ATTR_ACTION))
259*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
260*4dc78e53SAndroid Build Coastguard Worker ret = rtnl_act_remove(&b->b_act, act);
261*4dc78e53SAndroid Build Coastguard Worker if (ret)
262*4dc78e53SAndroid Build Coastguard Worker return ret;
263*4dc78e53SAndroid Build Coastguard Worker
264*4dc78e53SAndroid Build Coastguard Worker if (!b->b_act)
265*4dc78e53SAndroid Build Coastguard Worker b->b_mask &= ~BASIC_ATTR_ACTION;
266*4dc78e53SAndroid Build Coastguard Worker rtnl_act_put(act);
267*4dc78e53SAndroid Build Coastguard Worker return 0;
268*4dc78e53SAndroid Build Coastguard Worker }
269*4dc78e53SAndroid Build Coastguard Worker /** @} */
270*4dc78e53SAndroid Build Coastguard Worker
271*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops basic_ops = {
272*4dc78e53SAndroid Build Coastguard Worker .to_kind = "basic",
273*4dc78e53SAndroid Build Coastguard Worker .to_type = RTNL_TC_TYPE_CLS,
274*4dc78e53SAndroid Build Coastguard Worker .to_size = sizeof(struct rtnl_basic),
275*4dc78e53SAndroid Build Coastguard Worker .to_msg_parser = basic_msg_parser,
276*4dc78e53SAndroid Build Coastguard Worker .to_clone = basic_clone,
277*4dc78e53SAndroid Build Coastguard Worker .to_free_data = basic_free_data,
278*4dc78e53SAndroid Build Coastguard Worker .to_msg_fill = basic_msg_fill,
279*4dc78e53SAndroid Build Coastguard Worker .to_dump = {
280*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_LINE] = basic_dump_line,
281*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_DETAILS] = basic_dump_details,
282*4dc78e53SAndroid Build Coastguard Worker },
283*4dc78e53SAndroid Build Coastguard Worker };
284*4dc78e53SAndroid Build Coastguard Worker
basic_init(void)285*4dc78e53SAndroid Build Coastguard Worker static void _nl_init basic_init(void)
286*4dc78e53SAndroid Build Coastguard Worker {
287*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_register(&basic_ops);
288*4dc78e53SAndroid Build Coastguard Worker }
289*4dc78e53SAndroid Build Coastguard Worker
basic_exit(void)290*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit basic_exit(void)
291*4dc78e53SAndroid Build Coastguard Worker {
292*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_unregister(&basic_ops);
293*4dc78e53SAndroid Build Coastguard Worker }
294*4dc78e53SAndroid Build Coastguard Worker
295*4dc78e53SAndroid Build Coastguard Worker /** @} */
296