libnl 3.7.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 <netlink-private/netlink.h>
14#include <netlink-private/tc.h>
15#include <netlink/netlink.h>
16#include <netlink/attr.h>
17#include <netlink/utils.h>
18#include <netlink-private/route/tc-api.h>
19#include <netlink/route/act/skbedit.h>
20
21static struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
22 [TCA_SKBEDIT_PARMS] = { .minlen = sizeof(struct tc_skbedit) },
23 [TCA_SKBEDIT_PRIORITY] = { .type = NLA_U32 },
24 [TCA_SKBEDIT_QUEUE_MAPPING] = { .type = NLA_U16 },
25 [TCA_SKBEDIT_MARK] = { .type = NLA_U32 },
26};
27
28static int skbedit_msg_parser(struct rtnl_tc *tc, void *data)
29{
30 struct rtnl_skbedit *u = data;
31 struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
32 int err;
33
34 err = tca_parse(tb, TCA_SKBEDIT_MAX, tc, skbedit_policy);
35 if (err < 0)
36 return err;
37
38 if (!tb[TCA_SKBEDIT_PARMS])
39 return -NLE_MISSING_ATTR;
40
41 u->s_flags = 0;
42 if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
43 u->s_flags |= SKBEDIT_F_PRIORITY;
44 u->s_prio = nla_get_u32(tb[TCA_SKBEDIT_PRIORITY]);
45 }
46
47 if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
48 u->s_flags |= SKBEDIT_F_QUEUE_MAPPING;
49 u->s_queue_mapping = nla_get_u16(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
50 }
51
52 if (tb[TCA_SKBEDIT_MARK] != NULL) {
53 u->s_flags |= SKBEDIT_F_MARK;
54 u->s_mark = nla_get_u32(tb[TCA_SKBEDIT_MARK]);
55 }
56
57 return 0;
58}
59
60static void skbedit_free_data(struct rtnl_tc *tc, void *data)
61{
62}
63
64static void skbedit_dump_line(struct rtnl_tc *tc, void *data,
65 struct nl_dump_params *p)
66{
67 struct rtnl_skbedit *u = data;
68
69 if (!u)
70 return;
71
72 if (u->s_flags & SKBEDIT_F_PRIORITY)
73 nl_dump(p, " priority %u", u->s_prio);
74
75 if (u->s_flags & SKBEDIT_F_MARK)
76 nl_dump(p, " mark %u", u->s_mark);
77
78 if (u->s_flags & SKBEDIT_F_QUEUE_MAPPING)
79 nl_dump(p, " queue_mapping %u", u->s_queue_mapping);
80
81 switch(u->s_parm.action){
82 case TC_ACT_UNSPEC:
83 nl_dump(p, " unspecified");
84 break;
85 case TC_ACT_PIPE:
86 nl_dump(p, " pipe");
87 break;
88 case TC_ACT_STOLEN:
89 nl_dump(p, " stolen");
90 break;
91 case TC_ACT_SHOT:
92 nl_dump(p, " shot");
93 break;
94 case TC_ACT_QUEUED:
95 nl_dump(p, " queued");
96 break;
97 case TC_ACT_REPEAT:
98 nl_dump(p, " repeat");
99 break;
100 }
101}
102
103static void skbedit_dump_details(struct rtnl_tc *tc, void *data,
104 struct nl_dump_params *p)
105{
106}
107
108static void skbedit_dump_stats(struct rtnl_tc *tc, void *data,
109 struct nl_dump_params *p)
110{
111 struct rtnl_skbedit *u = data;
112
113 if (!u)
114 return;
115 /* TODO */
116}
117
118
119static int skbedit_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
120{
121 struct rtnl_skbedit *u = data;
122
123 if (!u)
124 return 0;
125
126 NLA_PUT(msg, TCA_SKBEDIT_PARMS, sizeof(u->s_parm), &u->s_parm);
127
128 if (u->s_flags & SKBEDIT_F_MARK)
129 NLA_PUT_U32(msg, TCA_SKBEDIT_MARK, u->s_mark);
130
131 if (u->s_flags & SKBEDIT_F_PRIORITY)
132 NLA_PUT_U32(msg, TCA_SKBEDIT_PRIORITY, u->s_prio);
133
134 if (u->s_flags & SKBEDIT_F_QUEUE_MAPPING)
135 NLA_PUT_U32(msg, TCA_SKBEDIT_QUEUE_MAPPING, u->s_queue_mapping);
136
137 return 0;
138
139nla_put_failure:
140 return -NLE_NOMEM;
141}
142
143/**
144 * @name Attribute Modifications
145 * @{
146 */
147
148int rtnl_skbedit_set_action(struct rtnl_act *act, int action)
149{
150 struct rtnl_skbedit *u;
151
152 if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
153 return -NLE_NOMEM;
154
155 u->s_parm.action = action;
156
157 return 0;
158}
159
160int rtnl_skbedit_get_action(struct rtnl_act *act)
161{
162 struct rtnl_skbedit *u;
163
164 if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
165 return -NLE_NOMEM;
166 return u->s_parm.action;
167}
168
169int rtnl_skbedit_set_queue_mapping(struct rtnl_act *act, uint16_t index)
170{
171 struct rtnl_skbedit *u;
172
173 if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
174 return -NLE_NOMEM;
175
176 u->s_queue_mapping = index;
177 u->s_flags |= SKBEDIT_F_QUEUE_MAPPING;
178 return 0;
179}
180
181int rtnl_skbedit_get_queue_mapping(struct rtnl_act *act, uint16_t *index)
182{
183 struct rtnl_skbedit *u;
184
185 u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
186 if (!u)
187 return -NLE_NOMEM;
188 if (!(u->s_flags & SKBEDIT_F_QUEUE_MAPPING))
189 return -NLE_NOATTR;
190
191 *index = u->s_queue_mapping;
192 return 0;
193}
194
195int rtnl_skbedit_set_mark(struct rtnl_act *act, uint32_t mark)
196{
197 struct rtnl_skbedit *u;
198
199 if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
200 return -NLE_NOMEM;
201
202 u->s_mark = mark;
203 u->s_flags |= SKBEDIT_F_MARK;
204 return 0;
205}
206
207int rtnl_skbedit_get_mark(struct rtnl_act *act, uint32_t *mark)
208{
209 struct rtnl_skbedit *u;
210
211 u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
212 if (!u)
213 return -NLE_NOMEM;
214 if (!(u->s_flags & SKBEDIT_F_MARK))
215 return -NLE_NOATTR;
216
217 *mark = u->s_mark;
218 return 0;
219}
220
221int rtnl_skbedit_set_priority(struct rtnl_act *act, uint32_t prio)
222{
223 struct rtnl_skbedit *u;
224
225 if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
226 return -NLE_NOMEM;
227
228 u->s_prio = prio;
229 u->s_flags |= SKBEDIT_F_PRIORITY;
230 return 0;
231}
232
233int rtnl_skbedit_get_priority(struct rtnl_act *act, uint32_t *prio)
234{
235 struct rtnl_skbedit *u;
236
237 u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
238 if (!u)
239 return -NLE_NOMEM;
240 if (!(u->s_flags & SKBEDIT_F_PRIORITY))
241 return -NLE_NOATTR;
242
243 *prio = u->s_prio;
244 return 0;
245}
246
247/** @} */
248
249static struct rtnl_tc_ops skbedit_ops = {
250 .to_kind = "skbedit",
251 .to_type = RTNL_TC_TYPE_ACT,
252 .to_size = sizeof(struct rtnl_skbedit),
253 .to_msg_parser = skbedit_msg_parser,
254 .to_free_data = skbedit_free_data,
255 .to_clone = NULL,
256 .to_msg_fill = skbedit_msg_fill,
257 .to_dump = {
258 [NL_DUMP_LINE] = skbedit_dump_line,
259 [NL_DUMP_DETAILS] = skbedit_dump_details,
260 [NL_DUMP_STATS] = skbedit_dump_stats,
261 },
262};
263
264static void __init skbedit_init(void)
265{
266 rtnl_tc_register(&skbedit_ops);
267}
268
269static void __exit skbedit_exit(void)
270{
271 rtnl_tc_unregister(&skbedit_ops);
272}
273
274/** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:702
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:652
#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 *tc)
Return pointer to private data of traffic control object.
Definition: tc.c:1076
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Definition: tc.c:1015
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
Definition: tc.c:1049
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition: types.h:18
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
Dumping parameters.
Definition: types.h:28
Attribute validation policy.
Definition: attr.h:63
uint16_t minlen
Minimal length of payload required.
Definition: attr.h:68