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 
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  u->s_parm.action = action;
156 
157  return 0;
158 }
159 
160 int 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 
169 int 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 
181 int 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 
195 int 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 
207 int 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 
221 int 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 
233 int 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 
249 static 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 
264 static void __init skbedit_init(void)
265 {
266  rtnl_tc_register(&skbedit_ops);
267 }
268 
269 static 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: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:1076
#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: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