libnl: /data/src/libnl/lib/route/cls/flower.c Source File

libnl 3.12.0

flower.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2018 Volodymyr Bendiuga <volodymyr.bendiuga@gmail.com>
4 */
5
6#include "nl-default.h"
7
8#include <linux/ethtool.h>
9
10#include <netlink/netlink.h>
11#include <netlink/attr.h>
12#include <netlink/utils.h>
13#include <netlink/route/classifier.h>
14#include <netlink/route/action.h>
15#include <netlink/route/cls/flower.h>
16
17#include "tc-api.h"
18#include "nl-aux-route/nl-route.h"
19
20/** @cond SKIP */
21struct rtnl_flower {
22 struct rtnl_act *cf_act;
23 int cf_mask;
24 uint32_t cf_flags;
25 uint16_t cf_proto;
26 uint16_t cf_vlan_id;
27 uint16_t cf_vlan_ethtype;
28 uint8_t cf_vlan_prio;
29 uint8_t cf_src_mac[ETH_ALEN];
30 uint8_t cf_src_mac_mask[ETH_ALEN];
31 uint8_t cf_dst_mac[ETH_ALEN];
32 uint8_t cf_dst_mac_mask[ETH_ALEN];
33 in_addr_t cf_ipv4_src;
34 in_addr_t cf_ipv4_src_mask;
35 in_addr_t cf_ipv4_dst;
36 in_addr_t cf_ipv4_dst_mask;
37 uint8_t cf_ip_dscp;
38 uint8_t cf_ip_dscp_mask;
39};
40
41#define FLOWER_ATTR_FLAGS (1 << 0)
42#define FLOWER_ATTR_ACTION (1 << 1)
43#define FLOWER_ATTR_VLAN_ID (1 << 2)
44#define FLOWER_ATTR_VLAN_PRIO (1 << 3)
45#define FLOWER_ATTR_VLAN_ETH_TYPE (1 << 4)
46#define FLOWER_ATTR_DST_MAC (1 << 5)
47#define FLOWER_ATTR_DST_MAC_MASK (1 << 6)
48#define FLOWER_ATTR_SRC_MAC (1 << 7)
49#define FLOWER_ATTR_SRC_MAC_MASK (1 << 8)
50#define FLOWER_ATTR_IP_DSCP (1 << 9)
51#define FLOWER_ATTR_IP_DSCP_MASK (1 << 10)
52#define FLOWER_ATTR_PROTO (1 << 11)
53#define FLOWER_ATTR_IPV4_SRC (1 << 12)
54#define FLOWER_ATTR_IPV4_SRC_MASK (1 << 13)
55#define FLOWER_ATTR_IPV4_DST (1 << 14)
56#define FLOWER_ATTR_IPV4_DST_MASK (1 << 15)
57/** @endcond */
58
59#define FLOWER_DSCP_MAX 0xe0
60#define FLOWER_DSCP_MASK_MAX 0xe0
61#define FLOWER_VID_MAX 4095
62#define FLOWER_VLAN_PRIO_MAX 7
63
64static struct nla_policy flower_policy[TCA_FLOWER_MAX + 1] = {
65 [TCA_FLOWER_FLAGS] = { .type = NLA_U32 },
66 [TCA_FLOWER_KEY_ETH_TYPE] = { .type = NLA_U16 },
67 [TCA_FLOWER_KEY_ETH_DST] = { .maxlen = ETH_ALEN },
68 [TCA_FLOWER_KEY_ETH_DST_MASK] = { .maxlen = ETH_ALEN },
69 [TCA_FLOWER_KEY_ETH_SRC] = { .maxlen = ETH_ALEN },
70 [TCA_FLOWER_KEY_ETH_SRC_MASK] = { .maxlen = ETH_ALEN },
71 [TCA_FLOWER_KEY_VLAN_ID] = { .type = NLA_U16 },
72 [TCA_FLOWER_KEY_VLAN_PRIO] = { .type = NLA_U8 },
73 [TCA_FLOWER_KEY_IP_TOS] = { .type = NLA_U8 },
74 [TCA_FLOWER_KEY_IP_TOS_MASK] = { .type = NLA_U8 },
75 [TCA_FLOWER_KEY_VLAN_ETH_TYPE] = { .type = NLA_U16 },
76 [TCA_FLOWER_KEY_IPV4_SRC] = { .type = NLA_U32 },
77 [TCA_FLOWER_KEY_IPV4_SRC_MASK] = { .type = NLA_U32 },
78 [TCA_FLOWER_KEY_IPV4_DST] = { .type = NLA_U32 },
79 [TCA_FLOWER_KEY_IPV4_DST_MASK] = { .type = NLA_U32 },
80};
81
82static int flower_msg_parser(struct rtnl_tc *tc, void *data)
83{
84 struct rtnl_flower *f = data;
85 struct nlattr *tb[TCA_FLOWER_MAX + 1];
86 int err;
87
88 err = tca_parse(tb, TCA_FLOWER_MAX, tc, flower_policy);
89 if (err < 0)
90 return err;
91
92 if (tb[TCA_FLOWER_FLAGS]) {
93 f->cf_flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
94 f->cf_mask |= FLOWER_ATTR_FLAGS;
95 }
96
97 if (tb[TCA_FLOWER_ACT]) {
98 err = rtnl_act_parse(&f->cf_act, tb[TCA_FLOWER_ACT]);
99 if (err)
100 return err;
101
102 f->cf_mask |= FLOWER_ATTR_ACTION;
103 }
104
105 if (tb[TCA_FLOWER_KEY_ETH_TYPE]) {
106 f->cf_proto = nla_get_u16(tb[TCA_FLOWER_KEY_ETH_TYPE]);
107 f->cf_mask |= FLOWER_ATTR_PROTO;
108 }
109
110 if (tb[TCA_FLOWER_KEY_VLAN_ID]) {
111 f->cf_vlan_id = nla_get_u16(tb[TCA_FLOWER_KEY_VLAN_ID]);
112 f->cf_mask |= FLOWER_ATTR_VLAN_ID;
113 }
114
115 if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) {
116 f->cf_vlan_prio = nla_get_u8(tb[TCA_FLOWER_KEY_VLAN_PRIO]);
117 f->cf_mask |= FLOWER_ATTR_VLAN_PRIO;
118 }
119
120 if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
121 f->cf_vlan_ethtype = nla_get_u16(tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]);
122 f->cf_mask |= FLOWER_ATTR_VLAN_ETH_TYPE;
123 }
124
125 if (tb[TCA_FLOWER_KEY_ETH_DST]) {
126 nla_memcpy(f->cf_dst_mac, tb[TCA_FLOWER_KEY_ETH_DST], ETH_ALEN);
127 f->cf_mask |= FLOWER_ATTR_DST_MAC;
128 }
129
130 if (tb[TCA_FLOWER_KEY_ETH_DST_MASK]) {
131 nla_memcpy(f->cf_dst_mac_mask, tb[TCA_FLOWER_KEY_ETH_DST_MASK], ETH_ALEN);
132 f->cf_mask |= FLOWER_ATTR_DST_MAC_MASK;
133 }
134
135 if (tb[TCA_FLOWER_KEY_ETH_SRC]) {
136 nla_memcpy(f->cf_src_mac, tb[TCA_FLOWER_KEY_ETH_SRC], ETH_ALEN);
137 f->cf_mask |= FLOWER_ATTR_SRC_MAC;
138 }
139
140 if (tb[TCA_FLOWER_KEY_ETH_SRC_MASK]) {
141 nla_memcpy(f->cf_src_mac_mask, tb[TCA_FLOWER_KEY_ETH_SRC_MASK], ETH_ALEN);
142 f->cf_mask |= FLOWER_ATTR_SRC_MAC_MASK;
143 }
144
145 if (tb[TCA_FLOWER_KEY_IP_TOS]) {
146 f->cf_ip_dscp = nla_get_u8(tb[TCA_FLOWER_KEY_IP_TOS]);
147 f->cf_mask |= FLOWER_ATTR_IP_DSCP;
148 }
149
150 if (tb[TCA_FLOWER_KEY_IP_TOS_MASK]) {
151 f->cf_ip_dscp_mask = nla_get_u8(tb[TCA_FLOWER_KEY_IP_TOS_MASK]);
152 f->cf_mask |= FLOWER_ATTR_IP_DSCP_MASK;
153 }
154
155 if (tb[TCA_FLOWER_KEY_IPV4_SRC]) {
156 f->cf_ipv4_src = nla_get_u32(tb[TCA_FLOWER_KEY_IPV4_SRC]);
157 f->cf_mask |= FLOWER_ATTR_IPV4_SRC;
158 }
159
160 if (tb[TCA_FLOWER_KEY_IPV4_SRC_MASK]) {
161 f->cf_ipv4_src_mask =
162 nla_get_u32(tb[TCA_FLOWER_KEY_IPV4_SRC_MASK]);
163 f->cf_mask |= FLOWER_ATTR_IPV4_SRC_MASK;
164 }
165
166 if (tb[TCA_FLOWER_KEY_IPV4_DST]) {
167 f->cf_ipv4_dst = nla_get_u32(tb[TCA_FLOWER_KEY_IPV4_DST]);
168 f->cf_mask |= FLOWER_ATTR_IPV4_DST;
169 }
170
171 if (tb[TCA_FLOWER_KEY_IPV4_DST_MASK]) {
172 f->cf_ipv4_dst_mask =
173 nla_get_u32(tb[TCA_FLOWER_KEY_IPV4_DST_MASK]);
174 f->cf_mask |= FLOWER_ATTR_IPV4_DST_MASK;
175 }
176
177 return 0;
178}
179
180static int flower_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
181{
182 struct rtnl_flower *f = data;
183 int err;
184
185 if (!f)
186 return 0;
187
188 if (f->cf_mask & FLOWER_ATTR_FLAGS)
189 NLA_PUT_U32(msg, TCA_FLOWER_FLAGS, f->cf_flags);
190
191 if (f->cf_mask & FLOWER_ATTR_ACTION) {
192 err = rtnl_act_fill(msg, TCA_FLOWER_ACT, f->cf_act);
193 if (err)
194 return err;
195 }
196
197 if (f->cf_mask & FLOWER_ATTR_PROTO)
198 NLA_PUT_U16(msg, TCA_FLOWER_KEY_ETH_TYPE, f->cf_proto);
199
200 if (f->cf_mask & FLOWER_ATTR_VLAN_ID)
201 NLA_PUT_U16(msg, TCA_FLOWER_KEY_VLAN_ID, f->cf_vlan_id);
202
203 if (f->cf_mask & FLOWER_ATTR_VLAN_PRIO)
204 NLA_PUT_U8(msg, TCA_FLOWER_KEY_VLAN_PRIO, f->cf_vlan_prio);
205
206 if (f->cf_mask & FLOWER_ATTR_VLAN_ETH_TYPE)
207 NLA_PUT_U16(msg, TCA_FLOWER_KEY_VLAN_ETH_TYPE, f->cf_vlan_ethtype);
208
209 if (f->cf_mask & FLOWER_ATTR_DST_MAC)
210 NLA_PUT(msg, TCA_FLOWER_KEY_ETH_DST, ETH_ALEN, f->cf_dst_mac);
211
212 if (f->cf_mask & FLOWER_ATTR_DST_MAC_MASK)
213 NLA_PUT(msg, TCA_FLOWER_KEY_ETH_DST_MASK, ETH_ALEN, f->cf_dst_mac_mask);
214
215 if (f->cf_mask & FLOWER_ATTR_SRC_MAC)
216 NLA_PUT(msg, TCA_FLOWER_KEY_ETH_SRC, ETH_ALEN, f->cf_src_mac);
217
218 if (f->cf_mask & FLOWER_ATTR_SRC_MAC_MASK)
219 NLA_PUT(msg, TCA_FLOWER_KEY_ETH_SRC_MASK, ETH_ALEN, f->cf_src_mac_mask);
220
221 if (f->cf_mask & FLOWER_ATTR_IP_DSCP)
222 NLA_PUT_U8(msg, TCA_FLOWER_KEY_IP_TOS, f->cf_ip_dscp);
223
224 if (f->cf_mask & FLOWER_ATTR_IP_DSCP_MASK)
225 NLA_PUT_U8(msg, TCA_FLOWER_KEY_IP_TOS_MASK, f->cf_ip_dscp_mask);
226
227 if (f->cf_mask & FLOWER_ATTR_IPV4_SRC)
228 NLA_PUT_U32(msg, TCA_FLOWER_KEY_IPV4_SRC, f->cf_ipv4_src);
229
230 if (f->cf_mask & FLOWER_ATTR_IPV4_SRC_MASK)
231 NLA_PUT_U32(msg, TCA_FLOWER_KEY_IPV4_SRC_MASK,
232 f->cf_ipv4_src_mask);
233
234 if (f->cf_mask & FLOWER_ATTR_IPV4_DST)
235 NLA_PUT_U32(msg, TCA_FLOWER_KEY_IPV4_DST, f->cf_ipv4_dst);
236
237 if (f->cf_mask & FLOWER_ATTR_IPV4_DST_MASK)
238 NLA_PUT_U32(msg, TCA_FLOWER_KEY_IPV4_DST_MASK,
239 f->cf_ipv4_dst_mask);
240
241 return 0;
242
243nla_put_failure:
244 return -NLE_NOMEM;
245}
246
247static void flower_free_data(struct rtnl_tc *tc, void *data)
248{
249 struct rtnl_flower *f = data;
250
251 if (f->cf_act)
252 rtnl_act_put_all(&f->cf_act);
253}
254
255static int flower_clone(void *_dst, void *_src)
256{
257 struct rtnl_flower *dst = _dst, *src = _src;
258
259 if (src->cf_act) {
260 if (!(dst->cf_act = rtnl_act_alloc()))
261 return -NLE_NOMEM;
262
263 memcpy(dst->cf_act, src->cf_act, sizeof(struct rtnl_act));
264
265 /* action nl list next and prev pointers must be updated */
266 nl_init_list_head(&dst->cf_act->ce_list);
267
268 if ( src->cf_act->c_opts
269 && !(dst->cf_act->c_opts = nl_data_clone(src->cf_act->c_opts)))
270 return -NLE_NOMEM;
271
272 if ( src->cf_act->c_xstats
273 && !(dst->cf_act->c_xstats = nl_data_clone(src->cf_act->c_xstats)))
274 return -NLE_NOMEM;
275
276 if ( src->cf_act->c_subdata
277 && !(dst->cf_act->c_subdata = nl_data_clone(src->cf_act->c_subdata)))
278 return -NLE_NOMEM;
279
280 if (dst->cf_act->c_link) {
281 nl_object_get(OBJ_CAST(dst->cf_act->c_link));
282 }
283
284 dst->cf_act->a_next = NULL; /* Only clone first in chain */
285 }
286
287 return 0;
288}
289
290static void flower_dump_details(struct rtnl_tc *tc, void *data,
291 struct nl_dump_params *p)
292{
293 struct rtnl_flower *f = data;
294 char addr_str[INET_ADDRSTRLEN];
295 char mask_str[INET_ADDRSTRLEN];
296
297 if (!f)
298 return;
299
300 if (f->cf_mask & FLOWER_ATTR_FLAGS)
301 nl_dump(p, " flags %u", f->cf_flags);
302
303 if (f->cf_mask & FLOWER_ATTR_PROTO)
304 nl_dump(p, " protocol %u", f->cf_proto);
305
306 if (f->cf_mask & FLOWER_ATTR_VLAN_ID)
307 nl_dump(p, " vlan_id %u", f->cf_vlan_id);
308
309 if (f->cf_mask & FLOWER_ATTR_VLAN_PRIO)
310 nl_dump(p, " vlan_prio %u", f->cf_vlan_prio);
311
312 if (f->cf_mask & FLOWER_ATTR_VLAN_ETH_TYPE)
313 nl_dump(p, " vlan_ethtype %u", f->cf_vlan_ethtype);
314
315 if (f->cf_mask & FLOWER_ATTR_DST_MAC)
316 nl_dump(p, " dst_mac %02x:%02x:%02x:%02x:%02x:%02x",
317 f->cf_dst_mac[0], f->cf_dst_mac[1],
318 f->cf_dst_mac[2], f->cf_dst_mac[3],
319 f->cf_dst_mac[4], f->cf_dst_mac[5]);
320
321 if (f->cf_mask & FLOWER_ATTR_DST_MAC_MASK)
322 nl_dump(p, " dst_mac_mask %02x:%02x:%02x:%02x:%02x:%02x",
323 f->cf_dst_mac_mask[0], f->cf_dst_mac_mask[1],
324 f->cf_dst_mac_mask[2], f->cf_dst_mac_mask[3],
325 f->cf_dst_mac_mask[4], f->cf_dst_mac_mask[5]);
326
327 if (f->cf_mask & FLOWER_ATTR_SRC_MAC)
328 nl_dump(p, " src_mac %02x:%02x:%02x:%02x:%02x:%02x",
329 f->cf_src_mac[0], f->cf_src_mac[1],
330 f->cf_src_mac[2], f->cf_src_mac[3],
331 f->cf_src_mac[4], f->cf_src_mac[5]);
332
333 if (f->cf_mask & FLOWER_ATTR_SRC_MAC_MASK)
334 nl_dump(p, " src_mac_mask %02x:%02x:%02x:%02x:%02x:%02x",
335 f->cf_src_mac_mask[0], f->cf_src_mac_mask[1],
336 f->cf_src_mac_mask[2], f->cf_src_mac_mask[3],
337 f->cf_src_mac_mask[4], f->cf_src_mac_mask[5]);
338
339 if (f->cf_mask & FLOWER_ATTR_IP_DSCP)
340 nl_dump(p, " dscp %u", f->cf_ip_dscp);
341
342 if (f->cf_mask & FLOWER_ATTR_IP_DSCP_MASK)
343 nl_dump(p, " dscp_mask %u", f->cf_ip_dscp_mask);
344
345 if (f->cf_mask & FLOWER_ATTR_IPV4_SRC) {
346 _nl_inet_ntop4(f->cf_ipv4_src, addr_str);
347 _nl_inet_ntop4(f->cf_ipv4_src_mask, mask_str);
348 nl_dump(p, "IPv4 src %s mask %s\n", addr_str, mask_str);
349 }
350
351 if (f->cf_mask & FLOWER_ATTR_IPV4_DST) {
352 _nl_inet_ntop4(f->cf_ipv4_dst, addr_str);
353 _nl_inet_ntop4(f->cf_ipv4_dst_mask, mask_str);
354 nl_dump(p, "IPv4 dst %s mask %s\n", addr_str, mask_str);
355 }
356}
357
358/**
359 * @name Attribute Modification
360 * @{
361 */
362
363/**
364 * Set protocol for flower classifier
365 * @arg cls Flower classifier.
366 * @arg proto protocol (ETH_P_*)
367 * @return 0 on success or a negative error code.
368 */
369int rtnl_flower_set_proto(struct rtnl_cls *cls, uint16_t proto)
370{
371 struct rtnl_flower *f;
372
373 if (!(f = rtnl_tc_data(TC_CAST(cls))))
374 return -NLE_NOMEM;
375
376 f->cf_proto = htons(proto);
377 f->cf_mask |= FLOWER_ATTR_PROTO;
378
379 return 0;
380}
381
382/**
383 * Get protocol for flower classifier
384 * @arg cls Flower classifier.
385 * @arg proto protocol
386 * @return 0 on success or a negative error code.
387*/
388int rtnl_flower_get_proto(struct rtnl_cls *cls, uint16_t *proto)
389{
390 struct rtnl_flower *f;
391
392 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
393 return -NLE_INVAL;
394
395 if (!(f->cf_mask & FLOWER_ATTR_PROTO))
396 return -NLE_MISSING_ATTR;
397
398 *proto = ntohs(f->cf_proto);
399
400 return 0;
401}
402
403/**
404 * Set vlan id for flower classifier
405 * @arg cls Flower classifier.
406 * @arg vid vlan id
407 * @return 0 on success or a negative error code.
408 */
409int rtnl_flower_set_vlan_id(struct rtnl_cls *cls, uint16_t vid)
410{
411 struct rtnl_flower *f;
412
413 if (!(f = rtnl_tc_data(TC_CAST(cls))))
414 return -NLE_NOMEM;
415
416 if (vid > FLOWER_VID_MAX)
417 return -NLE_RANGE;
418
419 f->cf_vlan_id = vid;
420 f->cf_mask |= FLOWER_ATTR_VLAN_ID;
421
422 return 0;
423}
424
425/**
426 * Get vlan id for flower classifier
427 * @arg cls Flower classifier.
428 * @arg vid vlan id
429 * @return 0 on success or a negative error code.
430*/
431int rtnl_flower_get_vlan_id(struct rtnl_cls *cls, uint16_t *vid)
432{
433 struct rtnl_flower *f;
434
435 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
436 return -NLE_INVAL;
437
438 if (!(f->cf_mask & FLOWER_ATTR_VLAN_ID))
439 return -NLE_MISSING_ATTR;
440
441 *vid = f->cf_vlan_id;
442
443 return 0;
444}
445
446/**
447 * Set vlan priority for flower classifier
448 * @arg cls Flower classifier.
449 * @arg prio vlan priority
450 * @return 0 on success or a negative error code.
451 */
452int rtnl_flower_set_vlan_prio(struct rtnl_cls *cls, uint8_t prio)
453{
454 struct rtnl_flower *f;
455
456 if (!(f = rtnl_tc_data(TC_CAST(cls))))
457 return -NLE_NOMEM;
458
459 if (prio > FLOWER_VLAN_PRIO_MAX)
460 return -NLE_RANGE;
461
462 f->cf_vlan_prio = prio;
463 f->cf_mask |= FLOWER_ATTR_VLAN_PRIO;
464
465 return 0;
466}
467
468/**
469 * Get vlan prio for flower classifier
470 * @arg cls Flower classifier.
471 * @arg prio vlan priority
472 * @return 0 on success or a negative error code.
473*/
474int rtnl_flower_get_vlan_prio(struct rtnl_cls *cls, uint8_t *prio)
475{
476 struct rtnl_flower *f;
477
478 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
479 return -NLE_INVAL;
480
481 if (!(f->cf_mask & FLOWER_ATTR_VLAN_PRIO))
482 return -NLE_MISSING_ATTR;
483
484 *prio = f->cf_vlan_prio;
485
486 return 0;
487}
488
489/**
490 * Set vlan ethertype for flower classifier
491 * @arg cls Flower classifier.
492 * @arg ethtype vlan ethertype
493 * @return 0 on success or a negative error code.
494 */
495int rtnl_flower_set_vlan_ethtype(struct rtnl_cls *cls, uint16_t ethtype)
496{
497 struct rtnl_flower *f;
498
499 if (!(f = rtnl_tc_data(TC_CAST(cls))))
500 return -NLE_NOMEM;
501
502 if (!(f->cf_mask & FLOWER_ATTR_PROTO))
503 return -NLE_MISSING_ATTR;
504
505 if (f->cf_proto != htons(ETH_P_8021Q))
506 return -NLE_INVAL;
507
508 f->cf_vlan_ethtype = htons(ethtype);
509 f->cf_mask |= FLOWER_ATTR_VLAN_ETH_TYPE;
510
511 return 0;
512}
513
514/**
515 * Set destination mac address for flower classifier
516 * @arg cls Flower classifier.
517 * @arg mac destination mac address
518 * @arg mask mask for mac address
519 * @return 0 on success or a negative error code.
520 */
521int rtnl_flower_set_dst_mac(struct rtnl_cls *cls, unsigned char *mac,
522 unsigned char *mask)
523{
524 struct rtnl_flower *f;
525
526 if (!(f = rtnl_tc_data(TC_CAST(cls))))
527 return -NLE_NOMEM;
528
529 if (mac) {
530 memcpy(f->cf_dst_mac, mac, ETH_ALEN);
531 f->cf_mask |= FLOWER_ATTR_DST_MAC;
532
533 if (mask) {
534 memcpy(f->cf_dst_mac_mask, mask, ETH_ALEN);
535 f->cf_mask |= FLOWER_ATTR_DST_MAC_MASK;
536 }
537
538 return 0;
539 }
540
541 return -NLE_FAILURE;
542}
543
544/**
545 * Get destination mac address for flower classifier
546 * @arg cls Flower classifier.
547 * @arg mac destination mac address
548 * @arg mask mask for mac address
549 * @return 0 on success or a negative error code.
550*/
551int rtnl_flower_get_dst_mac(struct rtnl_cls *cls, unsigned char *mac,
552 unsigned char *mask)
553{
554 struct rtnl_flower *f;
555
556 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
557 return -NLE_INVAL;
558
559 if (!(f->cf_mask & FLOWER_ATTR_DST_MAC))
560 return -NLE_MISSING_ATTR;
561
562 if (mac)
563 memcpy(mac, f->cf_dst_mac, ETH_ALEN);
564
565 if (mask)
566 memcpy(mask, f->cf_dst_mac_mask, ETH_ALEN);
567
568 return 0;
569}
570
571/**
572 * Set source mac address for flower classifier
573 * @arg cls Flower classifier.
574 * @arg mac source mac address
575 * @arg mask mask for mac address
576 * @return 0 on success or a negative error code.
577 */
578int rtnl_flower_set_src_mac(struct rtnl_cls *cls, unsigned char *mac,
579 unsigned char *mask)
580{
581 struct rtnl_flower *f;
582
583 if (!(f = rtnl_tc_data(TC_CAST(cls))))
584 return -NLE_NOMEM;
585
586 if (mac) {
587 memcpy(f->cf_src_mac, mac, ETH_ALEN);
588 f->cf_mask |= FLOWER_ATTR_SRC_MAC;
589
590 if (mask) {
591 memcpy(f->cf_src_mac_mask, mask, ETH_ALEN);
592 f->cf_mask |= FLOWER_ATTR_SRC_MAC_MASK;
593 }
594
595 return 0;
596 }
597
598 return -NLE_FAILURE;
599}
600
601/**
602 * Get source mac address for flower classifier
603 * @arg cls Flower classifier.
604 * @arg mac source mac address
605 * @arg mask mask for mac address
606 * @return 0 on success or a negative error code.
607*/
608int rtnl_flower_get_src_mac(struct rtnl_cls *cls, unsigned char *mac,
609 unsigned char *mask)
610{
611 struct rtnl_flower *f;
612
613 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
614 return -NLE_INVAL;
615
616 if (!(f->cf_mask & FLOWER_ATTR_SRC_MAC))
617 return -NLE_MISSING_ATTR;
618
619 if (mac)
620 memcpy(mac, f->cf_src_mac, ETH_ALEN);
621
622 if (mask)
623 memcpy(mask, f->cf_src_mac_mask, ETH_ALEN);
624
625 return 0;
626}
627
628/**
629 * Set dscp value for flower classifier
630 * @arg cls Flower classifier.
631 * @arg dscp dscp value
632 * @arg mask mask for dscp value
633 * @return 0 on success or a negative error code.
634 */
635int rtnl_flower_set_ip_dscp(struct rtnl_cls *cls, uint8_t dscp, uint8_t mask)
636{
637 struct rtnl_flower *f;
638
639 if (!(f = rtnl_tc_data(TC_CAST(cls))))
640 return -NLE_NOMEM;
641
642 if (dscp > FLOWER_DSCP_MAX)
643 return -NLE_RANGE;
644
645 if (mask > FLOWER_DSCP_MASK_MAX)
646 return -NLE_RANGE;
647
648 f->cf_ip_dscp = dscp;
649 f->cf_mask |= FLOWER_ATTR_IP_DSCP;
650
651 if (mask) {
652 f->cf_ip_dscp_mask = mask;
653 f->cf_mask |= FLOWER_ATTR_IP_DSCP_MASK;
654 }
655
656 return 0;
657}
658
659/**
660 * Get dscp value for flower classifier
661 * @arg cls Flower classifier.
662 * @arg dscp dscp value
663 * @arg mask mask for dscp value
664 * @return 0 on success or a negative error code.
665*/
666int rtnl_flower_get_ip_dscp(struct rtnl_cls *cls, uint8_t *dscp, uint8_t *mask)
667{
668 struct rtnl_flower *f;
669
670 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
671 return -NLE_INVAL;
672
673 if (!(f->cf_mask & FLOWER_ATTR_IP_DSCP))
674 return -NLE_MISSING_ATTR;
675
676 *dscp = f->cf_ip_dscp;
677 *mask = f->cf_ip_dscp_mask;
678
679 return 0;
680}
681
682/**
683 * Set IPv4 source address for flower classifier
684 * @arg cls Flower classifier.
685 * @arg addr IPv4 source address
686 * @arg mask mask for IPv4 source address
687 * @return 0 on success or a negative error code.
688 */
689int rtnl_flower_set_ipv4_src(struct rtnl_cls *cls, in_addr_t addr,
690 in_addr_t mask)
691{
692 struct rtnl_flower *f;
693
694 if (!(f = rtnl_tc_data(TC_CAST(cls))))
695 return -NLE_NOMEM;
696
697 if (addr) {
698 f->cf_ipv4_src = addr;
699 f->cf_mask |= FLOWER_ATTR_IPV4_SRC;
700
701 if (mask) {
702 f->cf_ipv4_src_mask = mask;
703 f->cf_mask |= FLOWER_ATTR_IPV4_SRC_MASK;
704 }
705
706 return 0;
707 }
708
709 return -NLE_FAILURE;
710}
711
712/**
713 * Get IPv4 source address for flower classifier
714 * @arg cls Flower classifier.
715 * @arg addr IPv4 source address
716 * @arg mask mask for IPv4 source address
717 * @return 0 on success or a negative error code.
718 */
719int rtnl_flower_get_ipv4_src(struct rtnl_cls *cls, in_addr_t *out_addr,
720 in_addr_t *out_mask)
721{
722 struct rtnl_flower *f;
723
724 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
725 return -NLE_INVAL;
726
727 if (!(f->cf_mask & FLOWER_ATTR_IPV4_SRC))
728 return -NLE_MISSING_ATTR;
729
730 if (out_addr)
731 *out_addr = f->cf_ipv4_src;
732
733 if (out_mask) {
734 if (f->cf_mask & FLOWER_ATTR_IPV4_SRC_MASK)
735 *out_mask = f->cf_ipv4_src_mask;
736 else
737 *out_mask = 0xffffffff;
738 }
739
740 return 0;
741}
742
743/**
744 * Set IPv4 destination address for flower classifier
745 * @arg cls Flower classifier.
746 * @arg addr IPv4 destination address
747 * @arg mask mask for IPv4 destination address
748 * @return 0 on success or a negative error code.
749 */
750int rtnl_flower_set_ipv4_dst(struct rtnl_cls *cls, in_addr_t addr,
751 in_addr_t mask)
752{
753 struct rtnl_flower *f;
754
755 if (!(f = rtnl_tc_data(TC_CAST(cls))))
756 return -NLE_NOMEM;
757
758 if (addr) {
759 f->cf_ipv4_dst = addr;
760 f->cf_mask |= FLOWER_ATTR_IPV4_DST;
761
762 if (mask) {
763 f->cf_ipv4_dst_mask = mask;
764 f->cf_mask |= FLOWER_ATTR_IPV4_DST_MASK;
765 }
766
767 return 0;
768 }
769
770 return -NLE_FAILURE;
771}
772
773/**
774 * Get IPv4 destination address for flower classifier
775 * @arg cls Flower classifier.
776 * @arg addr IPv4 destination address
777 * @arg mask mask for IPv4 destination address
778 * @return 0 on success or a negative error code.
779 */
780int rtnl_flower_get_ipv4_dst(struct rtnl_cls *cls, in_addr_t *out_addr,
781 in_addr_t *out_mask)
782{
783 struct rtnl_flower *f;
784
785 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
786 return -NLE_INVAL;
787
788 if (!(f->cf_mask & FLOWER_ATTR_IPV4_DST))
789 return -NLE_MISSING_ATTR;
790
791 if (out_addr)
792 *out_addr = f->cf_ipv4_dst;
793
794 if (out_mask) {
795 if (f->cf_mask & FLOWER_ATTR_IPV4_DST_MASK)
796 *out_mask = f->cf_ipv4_dst_mask;
797 else
798 *out_mask = 0xffffffff;
799 }
800
801 return 0;
802}
803
804/**
805 * Append action for flower classifier
806 * @arg cls Flower classifier.
807 * @arg act action to append
808 * @return 0 on success or a negative error code.
809 */
810int rtnl_flower_append_action(struct rtnl_cls *cls, struct rtnl_act *act)
811{
812 struct rtnl_flower *f;
813 int err;
814
815 if (!act)
816 return 0;
817
818 if (!(f = rtnl_tc_data(TC_CAST(cls))))
819 return -NLE_NOMEM;
820
821 if ((err = _rtnl_act_append_get(&f->cf_act, act)) < 0)
822 return err;
823
824 f->cf_mask |= FLOWER_ATTR_ACTION;
825 return 0;
826}
827
828/**
829 * Delete action from flower classifier
830 * @arg cls Flower classifier.
831 * @arg act action to delete
832 * @return 0 on success or a negative error code.
833 */
834int rtnl_flower_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
835{
836 struct rtnl_flower *f;
837 int ret;
838
839 if (!act)
840 return 0;
841
842 if (!(f = rtnl_tc_data(TC_CAST(cls))))
843 return -NLE_NOMEM;
844
845 if (!(f->cf_mask & FLOWER_ATTR_ACTION))
846 return -NLE_INVAL;
847
848 ret = rtnl_act_remove(&f->cf_act, act);
849 if (ret)
850 return ret;
851
852 if (!f->cf_act)
853 f->cf_mask &= ~FLOWER_ATTR_ACTION;
854 rtnl_act_put(act);
855
856 return 0;
857}
858
859/**
860 * Get action from flower classifier
861 * @arg cls Flower classifier.
862 * @return action on success or NULL on error.
863 */
864struct rtnl_act* rtnl_flower_get_action(struct rtnl_cls *cls)
865{
866 struct rtnl_flower *f;
867
868 if (!(f = rtnl_tc_data_peek(TC_CAST(cls))))
869 return NULL;
870
871 if (!(f->cf_mask & FLOWER_ATTR_ACTION))
872 return NULL;
873
874 rtnl_act_get(f->cf_act);
875
876 return f->cf_act;
877}
878
879/**
880 * Set flags for flower classifier
881 * @arg cls Flower classifier.
882 * @arg flags (TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW)
883 * @return 0 on success or a negative error code.
884 */
885int rtnl_flower_set_flags(struct rtnl_cls *cls, int flags)
886{
887 struct rtnl_flower *f;
888
889 if (!(f = rtnl_tc_data(TC_CAST(cls))))
890 return -NLE_NOMEM;
891
892 f->cf_flags = flags;
893 f->cf_mask |= FLOWER_ATTR_FLAGS;
894
895 return 0;
896}
897
898/** @} */
899
900static struct rtnl_tc_ops flower_ops = {
901 .to_kind = "flower",
902 .to_type = RTNL_TC_TYPE_CLS,
903 .to_size = sizeof(struct rtnl_flower),
904 .to_msg_parser = flower_msg_parser,
905 .to_free_data = flower_free_data,
906 .to_clone = flower_clone,
907 .to_msg_fill = flower_msg_fill,
908 .to_dump = {
909 [NL_DUMP_DETAILS] = flower_dump_details,
910 },
911};
912
913static void _nl_init flower_init(void)
914{
915 rtnl_tc_register(&flower_ops);
916}
917
918static void _nl_exit flower_exit(void)
919{
920 rtnl_tc_unregister(&flower_ops);
921}
nla_get_u32
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:714
nla_get_u16
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition attr.c:664
NLA_PUT_U16
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition attr.h:219
NLA_PUT_U8
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition attr.h:201
NLA_PUT
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:166
NLA_PUT_U32
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:237
nla_get_u8
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:614
nla_memcpy
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:355
NLA_U8
@ NLA_U8
8 bit integer
Definition attr.h:35
NLA_U16
@ NLA_U16
16 bit integer
Definition attr.h:36
NLA_U32
@ NLA_U32
32 bit integer
Definition attr.h:37
nl_data_clone
struct nl_data * nl_data_clone(const struct nl_data *src)
Clone an abstract data object.
Definition data.c:95
nl_object_get
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition object.c:210
rtnl_tc_data_peek
void * rtnl_tc_data_peek(struct rtnl_tc *tc)
Returns the private data of the traffic control object.
Definition tc.c:1065
TC_CAST
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition tc.h:50
rtnl_tc_data
void * rtnl_tc_data(struct rtnl_tc *)
Return pointer to private data of traffic control object.
Definition tc.c:1079
rtnl_tc_register
int rtnl_tc_register(struct rtnl_tc_ops *)
Register a traffic control module.
Definition tc.c:1018
rtnl_tc_unregister
void rtnl_tc_unregister(struct rtnl_tc_ops *)
Unregister a traffic control module.
Definition tc.c:1052
nl_dump
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
NL_DUMP_DETAILS
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
nl_dump_params
Dumping parameters.
Definition types.h:32
nla_policy
Attribute validation policy.
Definition attr.h:66
rtnl_act
Definition nl-route.h:123
rtnl_tc
Definition nl-route.h:115