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