libnl 3.12.0
bridge_info.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2022 MaxLinear, Inc.
4 */
5
6/**
7 * @ingroup link
8 * @defgroup bridge Bridging
9 *
10 * @details
11 * @{
12 */
13
14#include "nl-default.h"
15
16#include <linux/if_bridge.h>
17
18#include <netlink/route/link/bridge_info.h>
19
20#include "nl-route.h"
21#include "link-api.h"
22
23#define BRIDGE_ATTR_VLAN_FILTERING (1 << 0)
24#define BRIDGE_ATTR_VLAN_PROTOCOL (1 << 1)
25#define BRIDGE_ATTR_VLAN_STATS_ENABLED (1 << 2)
26#define BRIDGE_ATTR_AGEING_TIME (1 << 3)
27#define BRIDGE_ATTR_VLAN_DEFAULT_PVID (1 << 4)
28#define BRIDGE_ATTR_NF_CALL_IPTABLES (1 << 5)
29#define BRIDGE_ATTR_NF_CALL_IP6TABLES (1 << 6)
30#define BRIDGE_ATTR_NF_CALL_ARPTABLES (1 << 7)
31#define BRIDGE_ATTR_STP_STATE (1 << 8)
32#define BRIDGE_ATTR_MCAST_ROUTER (1 << 9)
33#define BRIDGE_ATTR_MCAST_SNOOPING (1 << 10)
34#define BRIDGE_ATTR_BOOLOPT (1 << 11)
35
37 uint32_t ce_mask; /* to support attr macros */
38 uint32_t b_ageing_time;
39 uint16_t b_vlan_protocol;
40 uint16_t b_vlan_default_pvid;
41 uint8_t b_vlan_filtering;
42 uint8_t b_vlan_stats_enabled;
43 uint8_t b_nf_call_iptables;
44 uint8_t b_nf_call_ip6tables;
45 uint8_t b_nf_call_arptables;
46 uint32_t b_stp_state;
47 uint8_t b_mcast_router;
48 uint8_t b_mcast_snooping;
49 struct br_boolopt_multi b_boolopts;
50};
51
52static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = {
53 [IFLA_BR_AGEING_TIME] = { .type = NLA_U32 },
54 [IFLA_BR_VLAN_DEFAULT_PVID] = { .type = NLA_U16 },
55 [IFLA_BR_VLAN_FILTERING] = { .type = NLA_U8 },
56 [IFLA_BR_VLAN_PROTOCOL] = { .type = NLA_U16 },
57 [IFLA_BR_VLAN_STATS_ENABLED] = { .type = NLA_U8 },
58 [IFLA_BR_NF_CALL_IPTABLES] = { .type = NLA_U8 },
59 [IFLA_BR_NF_CALL_IP6TABLES] = { .type = NLA_U8 },
60 [IFLA_BR_NF_CALL_ARPTABLES] = { .type = NLA_U8 },
61 [IFLA_BR_STP_STATE] = { .type = NLA_U32 },
62 [IFLA_BR_MCAST_ROUTER] = { .type = NLA_U8 },
63 [IFLA_BR_MCAST_SNOOPING] = { .type = NLA_U8 },
64 [IFLA_BR_MULTI_BOOLOPT] = { .type = NLA_BINARY,
65 .minlen = sizeof(struct br_boolopt_multi),
66 .maxlen = sizeof(struct br_boolopt_multi) },
67};
68
69static inline struct bridge_info *bridge_info(struct rtnl_link *link)
70{
71 return link->l_info;
72}
73
74static int bridge_info_alloc(struct rtnl_link *link)
75{
76 struct bridge_info *bi;
77
78 if (link->l_info)
79 memset(link->l_info, 0, sizeof(*bi));
80 else {
81 bi = calloc(1, sizeof(*bi));
82 if (!bi)
83 return -NLE_NOMEM;
84
85 link->l_info = bi;
86 }
87
88 return 0;
89}
90
91static int bridge_info_clone(struct rtnl_link *dst, struct rtnl_link *src)
92{
93 struct bridge_info *bi_dst, *bi_src = src->l_info;
94 int err;
95
96 _nl_assert(bi_src);
97
98 err = bridge_info_alloc(dst);
99 if (err)
100 return err;
101
102 bi_dst = dst->l_info;
103
104 _nl_assert(bi_dst);
105
106 *bi_dst = *bi_src;
107
108 return 0;
109}
110
111static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data,
112 struct nlattr *xstats)
113{
114 struct nlattr *tb[IFLA_BR_MAX + 1];
115 struct bridge_info *bi;
116 int err;
117
118 NL_DBG(3, "Parsing Bridge link info\n");
119
120 if ((err = nla_parse_nested(tb, IFLA_BR_MAX, data, bi_attrs_policy)) <
121 0)
122 return err;
123
124 if ((err = bridge_info_alloc(link)) < 0)
125 return err;
126
127 bi = link->l_info;
128
129 if (tb[IFLA_BR_AGEING_TIME]) {
130 bi->b_ageing_time = nla_get_u32(tb[IFLA_BR_AGEING_TIME]);
131 bi->ce_mask |= BRIDGE_ATTR_AGEING_TIME;
132 }
133
134 if (tb[IFLA_BR_VLAN_DEFAULT_PVID]) {
135 bi->b_vlan_default_pvid =
136 nla_get_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]);
137 bi->ce_mask |= BRIDGE_ATTR_VLAN_DEFAULT_PVID;
138 }
139
140 if (tb[IFLA_BR_VLAN_FILTERING]) {
141 bi->b_vlan_filtering = nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]);
142 bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
143 }
144
145 if (tb[IFLA_BR_VLAN_PROTOCOL]) {
146 bi->b_vlan_protocol =
147 ntohs(nla_get_u16(tb[IFLA_BR_VLAN_PROTOCOL]));
148 bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
149 }
150
151 if (tb[IFLA_BR_VLAN_STATS_ENABLED]) {
152 bi->b_vlan_stats_enabled =
153 nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]);
154 bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
155 }
156
157 if (tb[IFLA_BR_NF_CALL_IPTABLES]) {
158 bi->b_nf_call_iptables =
159 nla_get_u8(tb[IFLA_BR_NF_CALL_IPTABLES]);
160 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IPTABLES;
161 }
162
163 if (tb[IFLA_BR_NF_CALL_IP6TABLES]) {
164 bi->b_nf_call_ip6tables =
165 nla_get_u8(tb[IFLA_BR_NF_CALL_IP6TABLES]);
166 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IP6TABLES;
167 }
168
169 if (tb[IFLA_BR_NF_CALL_ARPTABLES]) {
170 bi->b_nf_call_arptables =
171 nla_get_u8(tb[IFLA_BR_NF_CALL_ARPTABLES]);
172 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES;
173 }
174
175 if (tb[IFLA_BR_STP_STATE]) {
176 bi->b_stp_state = nla_get_u32(tb[IFLA_BR_STP_STATE]);
177 bi->ce_mask |= BRIDGE_ATTR_STP_STATE;
178 }
179
180 if (tb[IFLA_BR_MCAST_ROUTER]) {
181 bi->b_mcast_router = nla_get_u8(tb[IFLA_BR_MCAST_ROUTER]);
182 bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER;
183 }
184
185 if (tb[IFLA_BR_MCAST_SNOOPING]) {
186 bi->b_mcast_snooping = nla_get_u8(tb[IFLA_BR_MCAST_SNOOPING]);
187 bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING;
188 }
189
190 if (tb[IFLA_BR_MULTI_BOOLOPT]) {
191 nla_memcpy(&bi->b_boolopts, tb[IFLA_BR_MULTI_BOOLOPT],
192 sizeof(bi->b_boolopts));
193 bi->ce_mask |= BRIDGE_ATTR_BOOLOPT;
194 }
195
196 return 0;
197}
198
199static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
200{
201 struct bridge_info *bi = link->l_info;
202 struct nlattr *data;
203
204 data = nla_nest_start(msg, IFLA_INFO_DATA);
205 if (!data)
206 return -NLE_MSGSIZE;
207
208 if (bi->ce_mask & BRIDGE_ATTR_AGEING_TIME)
209 NLA_PUT_U32(msg, IFLA_BR_AGEING_TIME, bi->b_ageing_time);
210
211 if (bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING)
212 NLA_PUT_U8(msg, IFLA_BR_VLAN_FILTERING, bi->b_vlan_filtering);
213
214 if (bi->ce_mask & BRIDGE_ATTR_VLAN_DEFAULT_PVID)
215 NLA_PUT_U16(msg, IFLA_BR_VLAN_DEFAULT_PVID,
216 bi->b_vlan_default_pvid);
217
218 if (bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL)
219 NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL,
220 htons(bi->b_vlan_protocol));
221
222 if (bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED)
223 NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED,
224 bi->b_vlan_stats_enabled);
225
226 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_IPTABLES)
227 NLA_PUT_U8(msg, IFLA_BR_NF_CALL_IPTABLES,
228 bi->b_nf_call_iptables);
229
230 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_IP6TABLES)
231 NLA_PUT_U8(msg, IFLA_BR_NF_CALL_IP6TABLES,
232 bi->b_nf_call_ip6tables);
233
234 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_ARPTABLES)
235 NLA_PUT_U8(msg, IFLA_BR_NF_CALL_ARPTABLES,
236 bi->b_nf_call_arptables);
237
238 if (bi->ce_mask & BRIDGE_ATTR_STP_STATE)
239 NLA_PUT_U32(msg, IFLA_BR_STP_STATE, bi->b_stp_state);
240
241 if (bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER)
242 NLA_PUT_U8(msg, IFLA_BR_MCAST_ROUTER, bi->b_mcast_router);
243
244 if (bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING)
245 NLA_PUT_U8(msg, IFLA_BR_MCAST_SNOOPING, bi->b_mcast_snooping);
246
247 if (bi->ce_mask & BRIDGE_ATTR_BOOLOPT)
248 NLA_PUT(msg, IFLA_BR_MULTI_BOOLOPT, sizeof(bi->b_boolopts),
249 &bi->b_boolopts);
250
251 nla_nest_end(msg, data);
252 return 0;
253
254nla_put_failure:
255 nla_nest_cancel(msg, data);
256 return -NLE_MSGSIZE;
257}
258
259static void bridge_info_free(struct rtnl_link *link)
260{
261 _nl_clear_free(&link->l_info);
262}
263
264static int bridge_info_compare(struct rtnl_link *link_a,
265 struct rtnl_link *link_b, int flags)
266{
267 struct bridge_info *a = link_a->l_info;
268 struct bridge_info *b = link_b->l_info;
269 uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0u;
270 int diff = 0;
271
272#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
273 diff |= _DIFF(BRIDGE_ATTR_VLAN_FILTERING,
274 a->b_vlan_filtering != b->b_vlan_filtering);
275 diff |= _DIFF(BRIDGE_ATTR_VLAN_PROTOCOL,
276 a->b_vlan_protocol != b->b_vlan_protocol);
277 diff |= _DIFF(BRIDGE_ATTR_VLAN_STATS_ENABLED,
278 a->b_vlan_stats_enabled != b->b_vlan_stats_enabled);
279 diff |= _DIFF(BRIDGE_ATTR_AGEING_TIME,
280 a->b_ageing_time != b->b_ageing_time);
281 diff |= _DIFF(BRIDGE_ATTR_VLAN_DEFAULT_PVID,
282 a->b_vlan_default_pvid != b->b_vlan_default_pvid);
283 diff |= _DIFF(BRIDGE_ATTR_NF_CALL_IPTABLES,
284 a->b_nf_call_iptables != b->b_nf_call_iptables);
285 diff |= _DIFF(BRIDGE_ATTR_NF_CALL_IP6TABLES,
286 a->b_nf_call_ip6tables != b->b_nf_call_ip6tables);
287 diff |= _DIFF(BRIDGE_ATTR_NF_CALL_ARPTABLES,
288 a->b_nf_call_arptables != b->b_nf_call_arptables);
289 diff |= _DIFF(BRIDGE_ATTR_STP_STATE, a->b_stp_state != b->b_stp_state);
290 diff |= _DIFF(BRIDGE_ATTR_MCAST_ROUTER,
291 a->b_mcast_router != b->b_mcast_router);
292 diff |= _DIFF(BRIDGE_ATTR_MCAST_SNOOPING,
293 a->b_mcast_snooping != b->b_mcast_snooping);
294
295 if (flags & LOOSE_COMPARISON)
296 diff |= _DIFF(
297 BRIDGE_ATTR_BOOLOPT,
298 (b->b_boolopts.optmask & ~a->b_boolopts.optmask) ||
299 ((a->b_boolopts.optval ^ b->b_boolopts.optval) &
300 b->b_boolopts.optmask));
301 else
302 diff |= _DIFF(
303 BRIDGE_ATTR_BOOLOPT,
304 (a->b_boolopts.optmask != b->b_boolopts.optmask) ||
305 (a->b_boolopts.optval != b->b_boolopts.optval));
306#undef _DIFF
307
308 return diff;
309}
310
311static struct rtnl_link_info_ops bridge_info_ops = {
312 .io_name = "bridge",
313 .io_alloc = bridge_info_alloc,
314 .io_clone = bridge_info_clone,
315 .io_parse = bridge_info_parse,
316 .io_put_attrs = bridge_info_put_attrs,
317 .io_free = bridge_info_free,
318 .io_compare = bridge_info_compare,
319};
320
321#define IS_BRIDGE_INFO_ASSERT(link) \
322 do { \
323 if ((link)->l_info_ops != &bridge_info_ops) { \
324 APPBUG("Link is not a bridge link. Set type \"bridge\" first."); \
325 } \
326 } while (0)
327
328/**
329 * Set ageing time for dynamic forwarding entries
330 * @arg link Link object of type bridge
331 * @arg ageing_time Interval to set.
332 *
333 * @see rtnl_link_bridge_get_ageing_time()
334 *
335 * @return void
336 */
338 uint32_t ageing_time)
339{
340 struct bridge_info *bi = bridge_info(link);
341
342 IS_BRIDGE_INFO_ASSERT(link);
343
344 bi->b_ageing_time = ageing_time;
345
346 bi->ce_mask |= BRIDGE_ATTR_AGEING_TIME;
347}
348
349/**
350 * Get ageing time for dynamic forwarding entries
351 * @arg link Link object of type bridge
352 * @arg ageing_time Output argument.
353 *
354 * @see rtnl_link_bridge_set_ageing_time()
355 * @return Zero on success, otherwise a negative error code.
356 * @retval -NLE_NOATTR
357 * @retval -NLE_INVAL
358 */
360 uint32_t *ageing_time)
361{
362 struct bridge_info *bi = bridge_info(link);
363
364 IS_BRIDGE_INFO_ASSERT(link);
365
366 if (!(bi->ce_mask & BRIDGE_ATTR_AGEING_TIME))
367 return -NLE_NOATTR;
368
369 if (!ageing_time)
370 return -NLE_INVAL;
371
372 *ageing_time = bi->b_ageing_time;
373
374 return 0;
375}
376
377/**
378 * Set VLAN filtering flag
379 * @arg link Link object of type bridge
380 * @arg vlan_filtering VLAN_filtering boolean flag to set.
381 *
382 * @see rtnl_link_bridge_get_vlan_filtering()
383 *
384 * @return void
385 */
387 uint8_t vlan_filtering)
388{
389 struct bridge_info *bi = bridge_info(link);
390
391 IS_BRIDGE_INFO_ASSERT(link);
392
393 bi->b_vlan_filtering = vlan_filtering;
394
395 bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
396}
397
398/**
399 * Get VLAN filtering flag
400 * @arg link Link object of type bridge
401 * @arg vlan_filtering Output argument.
402 *
403 * @see rtnl_link_bridge_set_vlan_filtering()
404 *
405 * @return Zero on success, otherwise a negative error code.
406 * @retval -NLE_NOATTR
407 * @retval -NLE_INVAL
408 */
410 uint8_t *vlan_filtering)
411{
412 struct bridge_info *bi = bridge_info(link);
413
414 IS_BRIDGE_INFO_ASSERT(link);
415
416 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING))
417 return -NLE_NOATTR;
418
419 if (!vlan_filtering)
420 return -NLE_INVAL;
421
422 *vlan_filtering = bi->b_vlan_filtering;
423 return 0;
424}
425
426/**
427 * Set VLAN protocol
428 * @arg link Link object of type bridge
429 * @arg vlan_protocol VLAN protocol to set. The protocol
430 * numbers is in host byte order.
431 *
432 * @see rtnl_link_bridge_get_vlan_protocol()
433 *
434 * @return void
435 */
437 uint16_t vlan_protocol)
438{
439 struct bridge_info *bi = bridge_info(link);
440
441 IS_BRIDGE_INFO_ASSERT(link);
442
443 bi->b_vlan_protocol = vlan_protocol;
444
445 bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
446}
447
448/**
449 * Get VLAN protocol
450 * @arg link Link object of type bridge
451 * @arg vlan_protocol Output argument. The protocol number is in host byte order.
452 *
453 * @see rtnl_link_bridge_set_vlan_protocol()
454 *
455 * @return Zero on success, otherwise a negative error code.
456 * @retval -NLE_NOATTR
457 * @retval -NLE_INVAL
458 */
460 uint16_t *vlan_protocol)
461{
462 struct bridge_info *bi = bridge_info(link);
463
464 IS_BRIDGE_INFO_ASSERT(link);
465
466 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL))
467 return -NLE_NOATTR;
468
469 if (!vlan_protocol)
470 return -NLE_INVAL;
471
472 *vlan_protocol = bi->b_vlan_protocol;
473
474 return 0;
475}
476
477/**
478 * Set VLAN default pvid
479 * @arg link Link object of type bridge
480 * @arg default pvid VLAN default pvid to set.
481 *
482 * @see rtnl_link_bridge_get_vlan_default_pvid()
483 *
484 * @return void
485 */
487 uint16_t default_pvid)
488{
489 struct bridge_info *bi = bridge_info(link);
490
491 IS_BRIDGE_INFO_ASSERT(link);
492
493 bi->b_vlan_default_pvid = default_pvid;
494
495 bi->ce_mask |= BRIDGE_ATTR_VLAN_DEFAULT_PVID;
496}
497
498/**
499 * Get VLAN default pvid
500 * @arg link Link object of type bridge
501 * @arg default_pvid Output argument.
502 *
503 * @see rtnl_link_bridge_set_vlan_default_pvid()
504 *
505 * @return Zero on success, otherwise a negative error code.
506 * @retval -NLE_NOATTR
507 * @retval -NLE_INVAL
508 */
510 uint16_t *default_pvid)
511{
512 struct bridge_info *bi = bridge_info(link);
513
514 IS_BRIDGE_INFO_ASSERT(link);
515
516 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_DEFAULT_PVID))
517 return -NLE_NOATTR;
518
519 if (!default_pvid)
520 return -NLE_INVAL;
521
522 *default_pvid = bi->b_vlan_default_pvid;
523
524 return 0;
525}
526
527/**
528 * Set VLAN stats enabled flag
529 * @arg link Link object of type bridge
530 * @arg vlan_stats_enabled VLAN stats enabled flag to set
531 *
532 * @see rtnl_link_bridge_get_vlan_stats_enabled()
533 *
534 * @return void
535 */
537 uint8_t vlan_stats_enabled)
538{
539 struct bridge_info *bi = bridge_info(link);
540
541 IS_BRIDGE_INFO_ASSERT(link);
542
543 bi->b_vlan_stats_enabled = vlan_stats_enabled;
544
545 bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
546}
547
548/**
549 * Get VLAN stats enabled flag
550 * @arg link Link object of type bridge
551 * @arg vlan_stats_enabled Output argument.
552 *
553 * @see rtnl_link_bridge_set_vlan_stats_enabled()
554 *
555 * @return Zero on success, otherwise a negative error code.
556 * @retval -NLE_NOATTR
557 * @retval -NLE_INVAL
558 */
560 uint8_t *vlan_stats_enabled)
561{
562 struct bridge_info *bi = bridge_info(link);
563
564 IS_BRIDGE_INFO_ASSERT(link);
565
566 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED))
567 return -NLE_NOATTR;
568
569 if (!vlan_stats_enabled)
570 return -NLE_INVAL;
571
572 *vlan_stats_enabled = bi->b_vlan_stats_enabled;
573
574 return 0;
575}
576
577/**
578 * Set call enabled flag for passing IPv4 traffic to iptables
579 * @arg link Link object of type bridge
580 * @arg call_enabled call enabled boolean flag to set.
581 *
582 * @see rtnl_link_bridge_get_nf_call_iptables()
583 *
584 * @return void
585 */
587 uint8_t call_enabled)
588{
589 struct bridge_info *bi = bridge_info(link);
590
591 IS_BRIDGE_INFO_ASSERT(link);
592
593 bi->b_nf_call_iptables = call_enabled;
594
595 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IPTABLES;
596}
597
598/**
599 * Get call enabled flag for passing IPv4 traffic to iptables
600 * @arg link Link object of type bridge
601 * @arg call_enabled Output argument.
602 *
603 * @see rtnl_link_bridge_set_nf_call_iptables()
604 *
605 * @return Zero on success, otherwise a negative error code.
606 * @retval -NLE_NOATTR
607 * @retval -NLE_INVAL
608 */
610 uint8_t *call_enabled)
611{
612 struct bridge_info *bi = bridge_info(link);
613
614 IS_BRIDGE_INFO_ASSERT(link);
615
616 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_IPTABLES))
617 return -NLE_NOATTR;
618
619 if (!call_enabled)
620 return -NLE_INVAL;
621
622 *call_enabled = bi->b_nf_call_iptables;
623
624 return 0;
625}
626
627/**
628 * Set call enabled flag for passing IPv6 traffic to ip6tables
629 * @arg link Link object of type bridge
630 * @arg call_enabled call enabled boolean flag to set.
631 *
632 * @see rtnl_link_bridge_get_nf_call_ip6tables()
633 *
634 * @return void
635 */
637 uint8_t call_enabled)
638{
639 struct bridge_info *bi = bridge_info(link);
640
641 IS_BRIDGE_INFO_ASSERT(link);
642
643 bi->b_nf_call_ip6tables = call_enabled;
644
645 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IP6TABLES;
646}
647
648/**
649 * Get call enabled flag for passing IPv6 traffic to iptables
650 * @arg link Link object of type bridge
651 * @arg call_enabled Output argument.
652 *
653 * @see rtnl_link_bridge_set_nf_call_ip6tables()
654 *
655 * @return Zero on success, otherwise a negative error code.
656 * @retval -NLE_NOATTR
657 * @retval -NLE_INVAL
658 */
660 uint8_t *call_enabled)
661{
662 struct bridge_info *bi = bridge_info(link);
663
664 IS_BRIDGE_INFO_ASSERT(link);
665
666 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_IP6TABLES))
667 return -NLE_NOATTR;
668
669 if (!call_enabled)
670 return -NLE_INVAL;
671
672 *call_enabled = bi->b_nf_call_ip6tables;
673
674 return 0;
675}
676
677/**
678 * Set call enabled flag for passing ARP traffic to arptables
679 * @arg link Link object of type bridge
680 * @arg call_enabled call enabled boolean flag to set.
681 *
682 * @see rtnl_link_bridge_get_nf_call_arptables()
683 *
684 * @return void
685 */
687 uint8_t call_enabled)
688{
689 struct bridge_info *bi = bridge_info(link);
690
691 IS_BRIDGE_INFO_ASSERT(link);
692
693 bi->b_nf_call_arptables = call_enabled;
694
695 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES;
696}
697
698/**
699 * Get call enabled flag for passing ARP traffic to arptables
700 * @arg link Link object of type bridge
701 * @arg call_enabled Output argument.
702 *
703 * @see rtnl_link_bridge_set_nf_call_arptables()
704 *
705 * @return Zero on success, otherwise a negative error code.
706 * @retval -NLE_NOATTR
707 * @retval -NLE_INVAL
708 */
710 uint8_t *call_enabled)
711{
712 struct bridge_info *bi = bridge_info(link);
713
714 IS_BRIDGE_INFO_ASSERT(link);
715
716 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_ARPTABLES))
717 return -NLE_NOATTR;
718
719 if (!call_enabled)
720 return -NLE_INVAL;
721
722 *call_enabled = bi->b_nf_call_arptables;
723
724 return 0;
725}
726
727/**
728 * Set STP state
729 * @arg link Link object of type bridge
730 * @arg stp_state STP state to set. Typically 0 or 1.
731 *
732 * @see rtnl_link_bridge_get_stp_state()
733 *
734 * @return void
735 */
736void rtnl_link_bridge_set_stp_state(struct rtnl_link *link, uint32_t stp_state)
737{
738 struct bridge_info *bi = bridge_info(link);
739
740 IS_BRIDGE_INFO_ASSERT(link);
741
742 bi->b_stp_state = stp_state;
743
744 bi->ce_mask |= BRIDGE_ATTR_STP_STATE;
745}
746
747/**
748 * Get STP state
749 * @arg link Link object of type bridge
750 * @arg stp_state Output argument.
751 *
752 * @see rtnl_link_bridge_set_stp_state()
753 *
754 * @return Zero on success, otherwise a negative error code.
755 * @retval -NLE_NOATTR
756 * @retval -NLE_INVAL
757 */
758int rtnl_link_bridge_get_stp_state(struct rtnl_link *link, uint32_t *stp_state)
759{
760 struct bridge_info *bi = bridge_info(link);
761
762 IS_BRIDGE_INFO_ASSERT(link);
763
764 if (!(bi->ce_mask & BRIDGE_ATTR_STP_STATE))
765 return -NLE_NOATTR;
766
767 if (!stp_state)
768 return -NLE_INVAL;
769
770 *stp_state = bi->b_stp_state;
771 return 0;
772}
773
774/**
775 * Set multicast router type
776 * @arg link Link object of type bridge
777 * @arg type Multicast router type (MDB_RTR_TYPE_*)
778 *
779 * @see rtnl_link_bridge_get_mcast_router()
780 *
781 * @return void
782 */
783void rtnl_link_bridge_set_mcast_router(struct rtnl_link *link, uint8_t type)
784{
785 struct bridge_info *bi = bridge_info(link);
786
787 IS_BRIDGE_INFO_ASSERT(link);
788
789 bi->b_mcast_router = type;
790
791 bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER;
792}
793
794/**
795 * Get multicast router type
796 * @arg link Link object of type bridge
797 * @arg type Output argument.
798 *
799 * @see rtnl_link_bridge_set_mcast_router()
800 *
801 * @return Zero on success, otherwise a negative error code.
802 * @retval -NLE_NOATTR
803 * @retval -NLE_INVAL
804 */
805int rtnl_link_bridge_get_mcast_router(struct rtnl_link *link, uint8_t *type)
806{
807 struct bridge_info *bi = bridge_info(link);
808
809 IS_BRIDGE_INFO_ASSERT(link);
810
811 if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER))
812 return -NLE_NOATTR;
813
814 if (!type)
815 return -NLE_INVAL;
816
817 *type = bi->b_mcast_router;
818 return 0;
819}
820
821/**
822 * Set multicast snooping
823 * @arg link Link object of type bridge
824 * @arg value Value to set. Typically 0 or 1.
825 *
826 * @see rtnl_link_bridge_get_mcast_snooping()
827 *
828 * @return void
829 */
830void rtnl_link_bridge_set_mcast_snooping(struct rtnl_link *link, uint8_t value)
831{
832 struct bridge_info *bi = bridge_info(link);
833
834 IS_BRIDGE_INFO_ASSERT(link);
835
836 bi->b_mcast_snooping = value;
837
838 bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING;
839}
840
841/**
842 * Get multicast snooping value
843 * @arg link Link object of type bridge
844 * @arg value Output argument.
845 *
846 * @see rtnl_link_bridge_set_mcast_snooping()
847 *
848 * @return Zero on success, otherwise a negative error code.
849 * @retval -NLE_NOATTR
850 * @retval -NLE_INVAL
851 */
852int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, uint8_t *value)
853{
854 struct bridge_info *bi = bridge_info(link);
855
856 IS_BRIDGE_INFO_ASSERT(link);
857
858 if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING))
859 return -NLE_NOATTR;
860
861 if (!value)
862 return -NLE_INVAL;
863
864 *value = bi->b_mcast_snooping;
865 return 0;
866}
867
868/**
869 * Set a the value of a boolopt
870 * @arg link Link object of type bridge
871 * @arg opt Option to modify (BR_BOOLOPT_*)
872 * @arg value Value to set the option to. 0 or 1.
873 *
874 * @see rtnl_link_bridge_get_boolopt()
875 *
876 * @return Zero on success, otherwise a negative error code.
877 * @retval -NLE_INVAL
878 */
879int rtnl_link_bridge_set_boolopt(struct rtnl_link *link, int opt, int value)
880{
881 struct bridge_info *bi = bridge_info(link);
882 uint32_t mask;
883
884 IS_BRIDGE_INFO_ASSERT(link);
885
886 if (opt < 0 || opt >= 32 || !(value == 0 || value == 1))
887 return -NLE_INVAL;
888
889 mask = 1ul << opt;
890
891 if (value)
892 bi->b_boolopts.optval |= mask;
893 else
894 bi->b_boolopts.optval &= ~mask;
895
896 bi->b_boolopts.optmask |= mask;
897 bi->ce_mask |= BRIDGE_ATTR_BOOLOPT;
898
899 return 0;
900}
901
902/**
903 * Get the value of a boolopt
904 * @arg link Link object of type bridge
905 * @arg opt Option to get (BR_BOOLOPT_*).
906 *
907 * @see rtnl_link_bridge_set_boolopt()
908 *
909 * @return The value of the boolopt (0 or 1), otherwise a negative error code.
910 * @retval -NLE_NOATTR
911 * @retval -NLE_INVAL
912 */
913int rtnl_link_bridge_get_boolopt(struct rtnl_link *link, int opt)
914{
915 struct bridge_info *bi = bridge_info(link);
916 uint32_t mask;
917
918 IS_BRIDGE_INFO_ASSERT(link);
919
920 if (opt < 0 || opt >= 32)
921 return -NLE_INVAL;
922
923 mask = 1ul << opt;
924
925 if (!(bi->ce_mask & BRIDGE_ATTR_BOOLOPT) ||
926 !(bi->b_boolopts.optmask & mask))
927 return -NLE_NOATTR;
928
929 return !!(bi->b_boolopts.optval & mask);
930}
931
932static void _nl_init bridge_info_init(void)
933{
934 rtnl_link_register_info(&bridge_info_ops);
935}
936
937static void _nl_exit bridge_info_exit(void)
938{
939 rtnl_link_unregister_info(&bridge_info_ops);
940}
941
942/** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:714
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition attr.c:664
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition attr.h:219
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition attr.h:201
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:166
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:237
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:614
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:355
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:974
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition attr.c:1101
void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr)
Cancel the addition of a nested attribute.
Definition attr.c:1066
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:1037
@ NLA_U8
8 bit integer
Definition attr.h:35
@ NLA_U16
16 bit integer
Definition attr.h:36
@ NLA_U32
32 bit integer
Definition attr.h:37
int rtnl_link_bridge_get_nf_call_arptables(struct rtnl_link *link, uint8_t *call_enabled)
Get call enabled flag for passing ARP traffic to arptables.
void rtnl_link_bridge_set_stp_state(struct rtnl_link *link, uint32_t stp_state)
Set STP state.
int rtnl_link_bridge_get_vlan_default_pvid(struct rtnl_link *link, uint16_t *default_pvid)
Get VLAN default pvid.
int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link, uint16_t *vlan_protocol)
Get VLAN protocol.
void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link, uint8_t vlan_stats_enabled)
Set VLAN stats enabled flag.
void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link, uint8_t vlan_filtering)
Set VLAN filtering flag.
void rtnl_link_bridge_set_mcast_snooping(struct rtnl_link *link, uint8_t value)
Set multicast snooping.
int rtnl_link_bridge_get_stp_state(struct rtnl_link *link, uint32_t *stp_state)
Get STP state.
int rtnl_link_bridge_get_ageing_time(struct rtnl_link *link, uint32_t *ageing_time)
Get ageing time for dynamic forwarding entries.
int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link, uint8_t *vlan_filtering)
Get VLAN filtering flag.
void rtnl_link_bridge_set_mcast_router(struct rtnl_link *link, uint8_t type)
Set multicast router type.
void rtnl_link_bridge_set_nf_call_iptables(struct rtnl_link *link, uint8_t call_enabled)
Set call enabled flag for passing IPv4 traffic to iptables.
int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, uint8_t *value)
Get multicast snooping value.
void rtnl_link_bridge_set_ageing_time(struct rtnl_link *link, uint32_t ageing_time)
Set ageing time for dynamic forwarding entries.
int rtnl_link_bridge_get_boolopt(struct rtnl_link *link, int opt)
Get the value of a boolopt.
void rtnl_link_bridge_set_nf_call_arptables(struct rtnl_link *link, uint8_t call_enabled)
Set call enabled flag for passing ARP traffic to arptables.
int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, uint8_t *vlan_stats_enabled)
Get VLAN stats enabled flag.
int rtnl_link_bridge_set_boolopt(struct rtnl_link *link, int opt, int value)
Set a the value of a boolopt.
void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link, uint16_t vlan_protocol)
Set VLAN protocol.
int rtnl_link_bridge_get_mcast_router(struct rtnl_link *link, uint8_t *type)
Get multicast router type.
int rtnl_link_bridge_get_nf_call_iptables(struct rtnl_link *link, uint8_t *call_enabled)
Get call enabled flag for passing IPv4 traffic to iptables.
void rtnl_link_bridge_set_nf_call_ip6tables(struct rtnl_link *link, uint8_t call_enabled)
Set call enabled flag for passing IPv6 traffic to ip6tables.
int rtnl_link_bridge_get_nf_call_ip6tables(struct rtnl_link *link, uint8_t *call_enabled)
Get call enabled flag for passing IPv6 traffic to iptables.
void rtnl_link_bridge_set_vlan_default_pvid(struct rtnl_link *link, uint16_t default_pvid)
Set VLAN default pvid.
Attribute validation policy.
Definition attr.h:66