• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
skbedit_msg_parser(struct rtnl_tc * tc,void * data)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 
skbedit_free_data(struct rtnl_tc * tc,void * data)60 static void skbedit_free_data(struct rtnl_tc *tc, void *data)
61 {
62 }
63 
skbedit_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)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 
skbedit_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)103 static void skbedit_dump_details(struct rtnl_tc *tc, void *data,
104 			     struct nl_dump_params *p)
105 {
106 }
107 
skbedit_dump_stats(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)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 
skbedit_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)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 
rtnl_skbedit_set_action(struct rtnl_act * act,int action)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 
rtnl_skbedit_get_action(struct rtnl_act * act)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 
rtnl_skbedit_set_queue_mapping(struct rtnl_act * act,uint16_t index)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 
rtnl_skbedit_get_queue_mapping(struct rtnl_act * act,uint16_t * index)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 
rtnl_skbedit_set_mark(struct rtnl_act * act,uint32_t mark)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 
rtnl_skbedit_get_mark(struct rtnl_act * act,uint32_t * mark)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 
rtnl_skbedit_set_priority(struct rtnl_act * act,uint32_t prio)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 
rtnl_skbedit_get_priority(struct rtnl_act * act,uint32_t * prio)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 
skbedit_init(void)264 static void __init skbedit_init(void)
265 {
266 	rtnl_tc_register(&skbedit_ops);
267 }
268 
skbedit_exit(void)269 static void __exit skbedit_exit(void)
270 {
271 	rtnl_tc_unregister(&skbedit_ops);
272 }
273 
274 /** @} */
275