xref: /aosp_15_r20/external/libnl/lib/route/act/skbedit.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2015 Cong Wang <[email protected]>
4  */
5 
6 /**
7  * @ingroup act
8  * @defgroup act_skbedit SKB Editing
9  *
10  * @{
11  */
12 
13 #include "nl-default.h"
14 
15 #include <netlink/netlink.h>
16 #include <netlink/attr.h>
17 #include <netlink/utils.h>
18 #include <netlink/route/act/skbedit.h>
19 
20 #include "nl-route.h"
21 #include "tc-api.h"
22 
23 struct rtnl_skbedit {
24 	struct tc_skbedit s_parm;
25 	uint32_t s_flags;
26 	uint32_t s_mark;
27 	uint32_t s_prio;
28 	uint16_t s_queue_mapping;
29 };
30 
31 static struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
32 	[TCA_SKBEDIT_PARMS]             = { .minlen = sizeof(struct tc_skbedit) },
33 	[TCA_SKBEDIT_PRIORITY]          = { .type = NLA_U32 },
34 	[TCA_SKBEDIT_QUEUE_MAPPING]     = { .type = NLA_U16 },
35 	[TCA_SKBEDIT_MARK]              = { .type = NLA_U32 },
36 };
37 
skbedit_msg_parser(struct rtnl_tc * tc,void * data)38 static int skbedit_msg_parser(struct rtnl_tc *tc, void *data)
39 {
40 	struct rtnl_skbedit *u = data;
41 	struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
42 	int err;
43 
44 	err = tca_parse(tb, TCA_SKBEDIT_MAX, tc, skbedit_policy);
45 	if (err < 0)
46 		return err;
47 
48 	if (!tb[TCA_SKBEDIT_PARMS])
49 		return -NLE_MISSING_ATTR;
50 
51 	u->s_flags = 0;
52 	if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
53 		u->s_flags |= SKBEDIT_F_PRIORITY;
54 		u->s_prio = nla_get_u32(tb[TCA_SKBEDIT_PRIORITY]);
55 	}
56 
57 	if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
58 		u->s_flags |= SKBEDIT_F_QUEUE_MAPPING;
59 		u->s_queue_mapping = nla_get_u16(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
60 	}
61 
62 	if (tb[TCA_SKBEDIT_MARK] != NULL) {
63 		u->s_flags |= SKBEDIT_F_MARK;
64 		u->s_mark = nla_get_u32(tb[TCA_SKBEDIT_MARK]);
65 	}
66 
67 	return 0;
68 }
69 
skbedit_free_data(struct rtnl_tc * tc,void * data)70 static void skbedit_free_data(struct rtnl_tc *tc, void *data)
71 {
72 }
73 
skbedit_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)74 static void skbedit_dump_line(struct rtnl_tc *tc, void *data,
75 			  struct nl_dump_params *p)
76 {
77 	struct rtnl_skbedit *u = data;
78 
79 	if (!u)
80 		return;
81 
82 	if (u->s_flags & SKBEDIT_F_PRIORITY)
83 		nl_dump(p, " priority %u", u->s_prio);
84 
85 	if (u->s_flags & SKBEDIT_F_MARK)
86 		nl_dump(p, " mark %u", u->s_mark);
87 
88 	if (u->s_flags & SKBEDIT_F_QUEUE_MAPPING)
89 		nl_dump(p, " queue_mapping %u", u->s_queue_mapping);
90 
91 	switch(u->s_parm.action){
92 	case TC_ACT_UNSPEC:
93 		nl_dump(p, " unspecified");
94 		break;
95 	case TC_ACT_PIPE:
96 		nl_dump(p, " pipe");
97 		break;
98 	case TC_ACT_STOLEN:
99 		nl_dump(p, " stolen");
100 		break;
101 	case TC_ACT_SHOT:
102 		nl_dump(p, " shot");
103 		break;
104 	case TC_ACT_QUEUED:
105 		nl_dump(p, " queued");
106 		break;
107 	case TC_ACT_REPEAT:
108 		nl_dump(p, " repeat");
109 		break;
110 	}
111 }
112 
skbedit_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)113 static void skbedit_dump_details(struct rtnl_tc *tc, void *data,
114 			     struct nl_dump_params *p)
115 {
116 }
117 
skbedit_dump_stats(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)118 static void skbedit_dump_stats(struct rtnl_tc *tc, void *data,
119 			   struct nl_dump_params *p)
120 {
121 	struct rtnl_skbedit *u = data;
122 
123 	if (!u)
124 		return;
125 	/* TODO */
126 }
127 
128 
skbedit_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)129 static int skbedit_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
130 {
131 	struct rtnl_skbedit *u = data;
132 
133 	if (!u)
134 		return 0;
135 
136 	NLA_PUT(msg, TCA_SKBEDIT_PARMS, sizeof(u->s_parm), &u->s_parm);
137 
138 	if (u->s_flags & SKBEDIT_F_MARK)
139 		NLA_PUT_U32(msg, TCA_SKBEDIT_MARK, u->s_mark);
140 
141 	if (u->s_flags & SKBEDIT_F_PRIORITY)
142 		NLA_PUT_U32(msg, TCA_SKBEDIT_PRIORITY, u->s_prio);
143 
144 	if (u->s_flags & SKBEDIT_F_QUEUE_MAPPING)
145 		NLA_PUT_U32(msg, TCA_SKBEDIT_QUEUE_MAPPING, u->s_queue_mapping);
146 
147 	return 0;
148 
149 nla_put_failure:
150 	return -NLE_NOMEM;
151 }
152 
153 /**
154  * @name Attribute Modifications
155  * @{
156  */
157 
rtnl_skbedit_set_action(struct rtnl_act * act,int action)158 int rtnl_skbedit_set_action(struct rtnl_act *act, int action)
159 {
160 	struct rtnl_skbedit *u;
161 
162 	if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
163 		return -NLE_NOMEM;
164 
165 	u->s_parm.action = action;
166 
167 	return 0;
168 }
169 
rtnl_skbedit_get_action(struct rtnl_act * act)170 int rtnl_skbedit_get_action(struct rtnl_act *act)
171 {
172 	struct rtnl_skbedit *u;
173 
174 	if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
175 		return -NLE_NOMEM;
176 	return u->s_parm.action;
177 }
178 
rtnl_skbedit_set_queue_mapping(struct rtnl_act * act,uint16_t index)179 int rtnl_skbedit_set_queue_mapping(struct rtnl_act *act, uint16_t index)
180 {
181 	struct rtnl_skbedit *u;
182 
183 	if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
184 		return -NLE_NOMEM;
185 
186 	u->s_queue_mapping = index;
187 	u->s_flags |= SKBEDIT_F_QUEUE_MAPPING;
188 	return 0;
189 }
190 
rtnl_skbedit_get_queue_mapping(struct rtnl_act * act,uint16_t * index)191 int rtnl_skbedit_get_queue_mapping(struct rtnl_act *act, uint16_t *index)
192 {
193 	struct rtnl_skbedit *u;
194 
195 	u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
196 	if (!u)
197 		return -NLE_NOMEM;
198 	if (!(u->s_flags & SKBEDIT_F_QUEUE_MAPPING))
199 		return -NLE_NOATTR;
200 
201 	*index = u->s_queue_mapping;
202 	return 0;
203 }
204 
rtnl_skbedit_set_mark(struct rtnl_act * act,uint32_t mark)205 int rtnl_skbedit_set_mark(struct rtnl_act *act, uint32_t mark)
206 {
207 	struct rtnl_skbedit *u;
208 
209 	if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
210 		return -NLE_NOMEM;
211 
212 	u->s_mark = mark;
213 	u->s_flags |= SKBEDIT_F_MARK;
214 	return 0;
215 }
216 
rtnl_skbedit_get_mark(struct rtnl_act * act,uint32_t * mark)217 int rtnl_skbedit_get_mark(struct rtnl_act *act, uint32_t *mark)
218 {
219 	struct rtnl_skbedit *u;
220 
221 	u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
222 	if (!u)
223 		return -NLE_NOMEM;
224 	if (!(u->s_flags & SKBEDIT_F_MARK))
225 		return -NLE_NOATTR;
226 
227 	*mark = u->s_mark;
228 	return 0;
229 }
230 
rtnl_skbedit_set_priority(struct rtnl_act * act,uint32_t prio)231 int rtnl_skbedit_set_priority(struct rtnl_act *act, uint32_t prio)
232 {
233 	struct rtnl_skbedit *u;
234 
235 	if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
236 		return -NLE_NOMEM;
237 
238 	u->s_prio = prio;
239 	u->s_flags |= SKBEDIT_F_PRIORITY;
240 	return 0;
241 }
242 
rtnl_skbedit_get_priority(struct rtnl_act * act,uint32_t * prio)243 int rtnl_skbedit_get_priority(struct rtnl_act *act, uint32_t *prio)
244 {
245 	struct rtnl_skbedit *u;
246 
247 	u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
248 	if (!u)
249 		return -NLE_NOMEM;
250 	if (!(u->s_flags & SKBEDIT_F_PRIORITY))
251 		return -NLE_NOATTR;
252 
253 	*prio = u->s_prio;
254 	return 0;
255 }
256 
257 /** @} */
258 
259 static struct rtnl_tc_ops skbedit_ops = {
260 	.to_kind		= "skbedit",
261 	.to_type		= RTNL_TC_TYPE_ACT,
262 	.to_size		= sizeof(struct rtnl_skbedit),
263 	.to_msg_parser		= skbedit_msg_parser,
264 	.to_free_data		= skbedit_free_data,
265 	.to_clone		= NULL,
266 	.to_msg_fill		= skbedit_msg_fill,
267 	.to_dump = {
268 	    [NL_DUMP_LINE]	= skbedit_dump_line,
269 	    [NL_DUMP_DETAILS]	= skbedit_dump_details,
270 	    [NL_DUMP_STATS]	= skbedit_dump_stats,
271 	},
272 };
273 
skbedit_init(void)274 static void _nl_init skbedit_init(void)
275 {
276 	rtnl_tc_register(&skbedit_ops);
277 }
278 
skbedit_exit(void)279 static void _nl_exit skbedit_exit(void)
280 {
281 	rtnl_tc_unregister(&skbedit_ops);
282 }
283 
284 /** @} */
285