libnl 3.9.0
skbedit.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2015 Cong Wang <xiyou.wangcong@gmail.com>
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
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
31static 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
38static 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
70static void skbedit_free_data(struct rtnl_tc *tc, void *data)
71{
72}
73
74static 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
113static void skbedit_dump_details(struct rtnl_tc *tc, void *data,
114 struct nl_dump_params *p)
115{
116}
117
118static 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
129static 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
149nla_put_failure:
150 return -NLE_NOMEM;
151}
152
153/**
154 * @name Attribute Modifications
155 * @{
156 */
157
158int 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
170int 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
179int 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
191int 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
205int 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
217int 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
231int 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
243int 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
259static 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
274static void _nl_init skbedit_init(void)
275{
276 rtnl_tc_register(&skbedit_ops);
277}
278
279static void _nl_exit skbedit_exit(void)
280{
281 rtnl_tc_unregister(&skbedit_ops);
282}
283
284/** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:710
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition attr.c:660
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:159
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:230
@ NLA_U16
16 bit integer
Definition attr.h:36
@ NLA_U32
32 bit integer
Definition attr.h:37
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition tc.h:50
void * rtnl_tc_data(struct rtnl_tc *)
Return pointer to private data of traffic control object.
Definition tc.c:1079
int rtnl_tc_register(struct rtnl_tc_ops *)
Register a traffic control module.
Definition tc.c:1018
void rtnl_tc_unregister(struct rtnl_tc_ops *)
Unregister a traffic control module.
Definition tc.c:1052
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1017
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition types.h:22
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition types.h:20
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
Dumping parameters.
Definition types.h:32
Attribute validation policy.
Definition attr.h:63
uint16_t minlen
Minimal length of payload required.
Definition attr.h:68