libnl  3.6.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 
21 static 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 
28 static 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 
60 static void skbedit_free_data(struct rtnl_tc *tc, void *data)
61 {
62 }
63 
64 static 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 
103 static void skbedit_dump_details(struct rtnl_tc *tc, void *data,
104  struct nl_dump_params *p)
105 {
106 }
107 
108 static 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 
119 static 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 
139 nla_put_failure:
140  return -NLE_NOMEM;
141 }
142 
143 /**
144  * @name Attribute Modifications
145  * @{
146  */
147 
148 int 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  if (action > TC_ACT_REPEAT || action < TC_ACT_UNSPEC)
156  return -NLE_INVAL;
157 
158  u->s_parm.action = action;
159  return 0;
160 }
161 
162 int rtnl_skbedit_get_action(struct rtnl_act *act)
163 {
164  struct rtnl_skbedit *u;
165 
166  if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
167  return -NLE_NOMEM;
168  return u->s_parm.action;
169 }
170 
171 int rtnl_skbedit_set_queue_mapping(struct rtnl_act *act, uint16_t index)
172 {
173  struct rtnl_skbedit *u;
174 
175  if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
176  return -NLE_NOMEM;
177 
178  u->s_queue_mapping = index;
179  u->s_flags |= SKBEDIT_F_QUEUE_MAPPING;
180  return 0;
181 }
182 
183 int rtnl_skbedit_get_queue_mapping(struct rtnl_act *act, uint16_t *index)
184 {
185  struct rtnl_skbedit *u;
186 
187  u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
188  if (!u)
189  return -NLE_NOMEM;
190  if (!(u->s_flags & SKBEDIT_F_QUEUE_MAPPING))
191  return -NLE_NOATTR;
192 
193  *index = u->s_queue_mapping;
194  return 0;
195 }
196 
197 int rtnl_skbedit_set_mark(struct rtnl_act *act, uint32_t mark)
198 {
199  struct rtnl_skbedit *u;
200 
201  if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
202  return -NLE_NOMEM;
203 
204  u->s_mark = mark;
205  u->s_flags |= SKBEDIT_F_MARK;
206  return 0;
207 }
208 
209 int rtnl_skbedit_get_mark(struct rtnl_act *act, uint32_t *mark)
210 {
211  struct rtnl_skbedit *u;
212 
213  u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
214  if (!u)
215  return -NLE_NOMEM;
216  if (!(u->s_flags & SKBEDIT_F_MARK))
217  return -NLE_NOATTR;
218 
219  *mark = u->s_mark;
220  return 0;
221 }
222 
223 int rtnl_skbedit_set_priority(struct rtnl_act *act, uint32_t prio)
224 {
225  struct rtnl_skbedit *u;
226 
227  if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act))))
228  return -NLE_NOMEM;
229 
230  u->s_prio = prio;
231  u->s_flags |= SKBEDIT_F_PRIORITY;
232  return 0;
233 }
234 
235 int rtnl_skbedit_get_priority(struct rtnl_act *act, uint32_t *prio)
236 {
237  struct rtnl_skbedit *u;
238 
239  u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act));
240  if (!u)
241  return -NLE_NOMEM;
242  if (!(u->s_flags & SKBEDIT_F_PRIORITY))
243  return -NLE_NOATTR;
244 
245  *prio = u->s_prio;
246  return 0;
247 }
248 
249 /** @} */
250 
251 static struct rtnl_tc_ops skbedit_ops = {
252  .to_kind = "skbedit",
253  .to_type = RTNL_TC_TYPE_ACT,
254  .to_size = sizeof(struct rtnl_skbedit),
255  .to_msg_parser = skbedit_msg_parser,
256  .to_free_data = skbedit_free_data,
257  .to_clone = NULL,
258  .to_msg_fill = skbedit_msg_fill,
259  .to_dump = {
260  [NL_DUMP_LINE] = skbedit_dump_line,
261  [NL_DUMP_DETAILS] = skbedit_dump_details,
262  [NL_DUMP_STATS] = skbedit_dump_stats,
263  },
264 };
265 
266 static void __init skbedit_init(void)
267 {
268  rtnl_tc_register(&skbedit_ops);
269 }
270 
271 static void __exit skbedit_exit(void)
272 {
273  rtnl_tc_unregister(&skbedit_ops);
274 }
275 
276 /** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:649
#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
void * rtnl_tc_data(struct rtnl_tc *tc)
Return pointer to private data of traffic control object.
Definition: tc.c:1079
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition: tc.h:50
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Definition: tc.c:1018
void rtnl_tc_unregister(struct rtnl_tc_ops *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: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