libnl 3.11.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] = {
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_parse(struct rtnl_link *link, struct nlattr *data,
92 struct nlattr *xstats)
93{
94 struct nlattr *tb[IFLA_BR_MAX + 1];
95 struct bridge_info *bi;
96 int err;
97
98 NL_DBG(3, "Parsing Bridge link info\n");
99
100 if ((err = nla_parse_nested(tb, IFLA_BR_MAX, data, bi_attrs_policy)) <
101 0)
102 return err;
103
104 if ((err = bridge_info_alloc(link)) < 0)
105 return err;
106
107 bi = link->l_info;
108
109 if (tb[IFLA_BR_AGEING_TIME]) {
110 bi->b_ageing_time = nla_get_u32(tb[IFLA_BR_AGEING_TIME]);
111 bi->ce_mask |= BRIDGE_ATTR_AGEING_TIME;
112 }
113
114 if (tb[IFLA_BR_VLAN_DEFAULT_PVID]) {
115 bi->b_vlan_default_pvid =
116 nla_get_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]);
117 bi->ce_mask |= BRIDGE_ATTR_VLAN_DEFAULT_PVID;
118 }
119
120 if (tb[IFLA_BR_VLAN_FILTERING]) {
121 bi->b_vlan_filtering = nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]);
122 bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
123 }
124
125 if (tb[IFLA_BR_VLAN_PROTOCOL]) {
126 bi->b_vlan_protocol =
127 ntohs(nla_get_u16(tb[IFLA_BR_VLAN_PROTOCOL]));
128 bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
129 }
130
131 if (tb[IFLA_BR_VLAN_STATS_ENABLED]) {
132 bi->b_vlan_stats_enabled =
133 nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]);
134 bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
135 }
136
137 if (tb[IFLA_BR_NF_CALL_IPTABLES]) {
138 bi->b_nf_call_iptables =
139 nla_get_u8(tb[IFLA_BR_NF_CALL_IPTABLES]);
140 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IPTABLES;
141 }
142
143 if (tb[IFLA_BR_NF_CALL_IP6TABLES]) {
144 bi->b_nf_call_ip6tables =
145 nla_get_u8(tb[IFLA_BR_NF_CALL_IP6TABLES]);
146 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IP6TABLES;
147 }
148
149 if (tb[IFLA_BR_NF_CALL_ARPTABLES]) {
150 bi->b_nf_call_arptables =
151 nla_get_u8(tb[IFLA_BR_NF_CALL_ARPTABLES]);
152 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES;
153 }
154
155 if (tb[IFLA_BR_STP_STATE]) {
156 bi->b_stp_state = nla_get_u32(tb[IFLA_BR_STP_STATE]);
157 bi->ce_mask |= BRIDGE_ATTR_STP_STATE;
158 }
159
160 if (tb[IFLA_BR_MCAST_ROUTER]) {
161 bi->b_mcast_router = nla_get_u8(tb[IFLA_BR_MCAST_ROUTER]);
162 bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER;
163 }
164
165 if (tb[IFLA_BR_MCAST_SNOOPING]) {
166 bi->b_mcast_snooping = nla_get_u8(tb[IFLA_BR_MCAST_SNOOPING]);
167 bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING;
168 }
169
170 if (tb[IFLA_BR_MULTI_BOOLOPT]) {
171 nla_memcpy(&bi->b_boolopts, tb[IFLA_BR_MULTI_BOOLOPT],
172 sizeof(bi->b_boolopts));
173 bi->ce_mask |= BRIDGE_ATTR_BOOLOPT;
174 }
175
176 return 0;
177}
178
179static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
180{
181 struct bridge_info *bi = link->l_info;
182 struct nlattr *data;
183
184 data = nla_nest_start(msg, IFLA_INFO_DATA);
185 if (!data)
186 return -NLE_MSGSIZE;
187
188 if (bi->ce_mask & BRIDGE_ATTR_AGEING_TIME)
189 NLA_PUT_U32(msg, IFLA_BR_AGEING_TIME, bi->b_ageing_time);
190
191 if (bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING)
192 NLA_PUT_U8(msg, IFLA_BR_VLAN_FILTERING, bi->b_vlan_filtering);
193
194 if (bi->ce_mask & BRIDGE_ATTR_VLAN_DEFAULT_PVID)
195 NLA_PUT_U16(msg, IFLA_BR_VLAN_DEFAULT_PVID,
196 bi->b_vlan_default_pvid);
197
198 if (bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL)
199 NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL,
200 htons(bi->b_vlan_protocol));
201
202 if (bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED)
203 NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED,
204 bi->b_vlan_stats_enabled);
205
206 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_IPTABLES)
207 NLA_PUT_U8(msg, IFLA_BR_NF_CALL_IPTABLES,
208 bi->b_nf_call_iptables);
209
210 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_IP6TABLES)
211 NLA_PUT_U8(msg, IFLA_BR_NF_CALL_IP6TABLES,
212 bi->b_nf_call_ip6tables);
213
214 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_ARPTABLES)
215 NLA_PUT_U8(msg, IFLA_BR_NF_CALL_ARPTABLES,
216 bi->b_nf_call_arptables);
217
218 if (bi->ce_mask & BRIDGE_ATTR_STP_STATE)
219 NLA_PUT_U32(msg, IFLA_BR_STP_STATE, bi->b_stp_state);
220
221 if (bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER)
222 NLA_PUT_U8(msg, IFLA_BR_MCAST_ROUTER, bi->b_mcast_router);
223
224 if (bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING)
225 NLA_PUT_U8(msg, IFLA_BR_MCAST_SNOOPING, bi->b_mcast_snooping);
226
227 if (bi->ce_mask & BRIDGE_ATTR_BOOLOPT)
228 NLA_PUT(msg, IFLA_BR_MULTI_BOOLOPT, sizeof(bi->b_boolopts),
229 &bi->b_boolopts);
230
231 nla_nest_end(msg, data);
232 return 0;
233
234nla_put_failure:
235 nla_nest_cancel(msg, data);
236 return -NLE_MSGSIZE;
237}
238
239static void bridge_info_free(struct rtnl_link *link)
240{
241 _nl_clear_free(&link->l_info);
242}
243
244static struct rtnl_link_info_ops bridge_info_ops = {
245 .io_name = "bridge",
246 .io_alloc = bridge_info_alloc,
247 .io_parse = bridge_info_parse,
248 .io_put_attrs = bridge_info_put_attrs,
249 .io_free = bridge_info_free,
250};
251
252#define IS_BRIDGE_INFO_ASSERT(link) \
253 do { \
254 if ((link)->l_info_ops != &bridge_info_ops) { \
255 APPBUG("Link is not a bridge link. Set type \"bridge\" first."); \
256 } \
257 } while (0)
258
259/**
260 * Set ageing time for dynamic forwarding entries
261 * @arg link Link object of type bridge
262 * @arg ageing_time Interval to set.
263 *
264 * @see rtnl_link_bridge_get_ageing_time()
265 *
266 * @return void
267 */
269 uint32_t ageing_time)
270{
271 struct bridge_info *bi = bridge_info(link);
272
273 IS_BRIDGE_INFO_ASSERT(link);
274
275 bi->b_ageing_time = ageing_time;
276
277 bi->ce_mask |= BRIDGE_ATTR_AGEING_TIME;
278}
279
280/**
281 * Get ageing time for dynamic forwarding entries
282 * @arg link Link object of type bridge
283 * @arg ageing_time Output argument.
284 *
285 * @see rtnl_link_bridge_set_ageing_time()
286 * @return Zero on success, otherwise a negative error code.
287 * @retval -NLE_NOATTR
288 * @retval -NLE_INVAL
289 */
291 uint32_t *ageing_time)
292{
293 struct bridge_info *bi = bridge_info(link);
294
295 IS_BRIDGE_INFO_ASSERT(link);
296
297 if (!(bi->ce_mask & BRIDGE_ATTR_AGEING_TIME))
298 return -NLE_NOATTR;
299
300 if (!ageing_time)
301 return -NLE_INVAL;
302
303 *ageing_time = bi->b_ageing_time;
304
305 return 0;
306}
307
308/**
309 * Set VLAN filtering flag
310 * @arg link Link object of type bridge
311 * @arg vlan_filtering VLAN_filtering boolean flag to set.
312 *
313 * @see rtnl_link_bridge_get_vlan_filtering()
314 *
315 * @return void
316 */
318 uint8_t vlan_filtering)
319{
320 struct bridge_info *bi = bridge_info(link);
321
322 IS_BRIDGE_INFO_ASSERT(link);
323
324 bi->b_vlan_filtering = vlan_filtering;
325
326 bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
327}
328
329/**
330 * Get VLAN filtering flag
331 * @arg link Link object of type bridge
332 * @arg vlan_filtering Output argument.
333 *
334 * @see rtnl_link_bridge_set_vlan_filtering()
335 *
336 * @return Zero on success, otherwise a negative error code.
337 * @retval -NLE_NOATTR
338 * @retval -NLE_INVAL
339 */
341 uint8_t *vlan_filtering)
342{
343 struct bridge_info *bi = bridge_info(link);
344
345 IS_BRIDGE_INFO_ASSERT(link);
346
347 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING))
348 return -NLE_NOATTR;
349
350 if (!vlan_filtering)
351 return -NLE_INVAL;
352
353 *vlan_filtering = bi->b_vlan_filtering;
354 return 0;
355}
356
357/**
358 * Set VLAN protocol
359 * @arg link Link object of type bridge
360 * @arg vlan_protocol VLAN protocol to set. The protocol
361 * numbers is in host byte order.
362 *
363 * @see rtnl_link_bridge_get_vlan_protocol()
364 *
365 * @return void
366 */
368 uint16_t vlan_protocol)
369{
370 struct bridge_info *bi = bridge_info(link);
371
372 IS_BRIDGE_INFO_ASSERT(link);
373
374 bi->b_vlan_protocol = vlan_protocol;
375
376 bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
377}
378
379/**
380 * Get VLAN protocol
381 * @arg link Link object of type bridge
382 * @arg vlan_protocol Output argument. The protocol number is in host byte order.
383 *
384 * @see rtnl_link_bridge_set_vlan_protocol()
385 *
386 * @return Zero on success, otherwise a negative error code.
387 * @retval -NLE_NOATTR
388 * @retval -NLE_INVAL
389 */
391 uint16_t *vlan_protocol)
392{
393 struct bridge_info *bi = bridge_info(link);
394
395 IS_BRIDGE_INFO_ASSERT(link);
396
397 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL))
398 return -NLE_NOATTR;
399
400 if (!vlan_protocol)
401 return -NLE_INVAL;
402
403 *vlan_protocol = bi->b_vlan_protocol;
404
405 return 0;
406}
407
408/**
409 * Set VLAN default pvid
410 * @arg link Link object of type bridge
411 * @arg default pvid VLAN default pvid to set.
412 *
413 * @see rtnl_link_bridge_get_vlan_default_pvid()
414 *
415 * @return void
416 */
418 uint16_t default_pvid)
419{
420 struct bridge_info *bi = bridge_info(link);
421
422 IS_BRIDGE_INFO_ASSERT(link);
423
424 bi->b_vlan_default_pvid = default_pvid;
425
426 bi->ce_mask |= BRIDGE_ATTR_VLAN_DEFAULT_PVID;
427}
428
429/**
430 * Get VLAN default pvid
431 * @arg link Link object of type bridge
432 * @arg default_pvid Output argument.
433 *
434 * @see rtnl_link_bridge_set_vlan_default_pvid()
435 *
436 * @return Zero on success, otherwise a negative error code.
437 * @retval -NLE_NOATTR
438 * @retval -NLE_INVAL
439 */
441 uint16_t *default_pvid)
442{
443 struct bridge_info *bi = bridge_info(link);
444
445 IS_BRIDGE_INFO_ASSERT(link);
446
447 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_DEFAULT_PVID))
448 return -NLE_NOATTR;
449
450 if (!default_pvid)
451 return -NLE_INVAL;
452
453 *default_pvid = bi->b_vlan_default_pvid;
454
455 return 0;
456}
457
458/**
459 * Set VLAN stats enabled flag
460 * @arg link Link object of type bridge
461 * @arg vlan_stats_enabled VLAN stats enabled flag to set
462 *
463 * @see rtnl_link_bridge_get_vlan_stats_enabled()
464 *
465 * @return void
466 */
468 uint8_t vlan_stats_enabled)
469{
470 struct bridge_info *bi = bridge_info(link);
471
472 IS_BRIDGE_INFO_ASSERT(link);
473
474 bi->b_vlan_stats_enabled = vlan_stats_enabled;
475
476 bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
477}
478
479/**
480 * Get VLAN stats enabled flag
481 * @arg link Link object of type bridge
482 * @arg vlan_stats_enabled Output argument.
483 *
484 * @see rtnl_link_bridge_set_vlan_stats_enabled()
485 *
486 * @return Zero on success, otherwise a negative error code.
487 * @retval -NLE_NOATTR
488 * @retval -NLE_INVAL
489 */
491 uint8_t *vlan_stats_enabled)
492{
493 struct bridge_info *bi = bridge_info(link);
494
495 IS_BRIDGE_INFO_ASSERT(link);
496
497 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED))
498 return -NLE_NOATTR;
499
500 if (!vlan_stats_enabled)
501 return -NLE_INVAL;
502
503 *vlan_stats_enabled = bi->b_vlan_stats_enabled;
504
505 return 0;
506}
507
508/**
509 * Set call enabled flag for passing IPv4 traffic to iptables
510 * @arg link Link object of type bridge
511 * @arg call_enabled call enabled boolean flag to set.
512 *
513 * @see rtnl_link_bridge_get_nf_call_iptables()
514 *
515 * @return void
516 */
518 uint8_t call_enabled)
519{
520 struct bridge_info *bi = bridge_info(link);
521
522 IS_BRIDGE_INFO_ASSERT(link);
523
524 bi->b_nf_call_iptables = call_enabled;
525
526 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IPTABLES;
527}
528
529/**
530 * Get call enabled flag for passing IPv4 traffic to iptables
531 * @arg link Link object of type bridge
532 * @arg call_enabled Output argument.
533 *
534 * @see rtnl_link_bridge_set_nf_call_iptables()
535 *
536 * @return Zero on success, otherwise a negative error code.
537 * @retval -NLE_NOATTR
538 * @retval -NLE_INVAL
539 */
541 uint8_t *call_enabled)
542{
543 struct bridge_info *bi = bridge_info(link);
544
545 IS_BRIDGE_INFO_ASSERT(link);
546
547 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_IPTABLES))
548 return -NLE_NOATTR;
549
550 if (!call_enabled)
551 return -NLE_INVAL;
552
553 *call_enabled = bi->b_nf_call_iptables;
554
555 return 0;
556}
557
558/**
559 * Set call enabled flag for passing IPv6 traffic to ip6tables
560 * @arg link Link object of type bridge
561 * @arg call_enabled call enabled boolean flag to set.
562 *
563 * @see rtnl_link_bridge_get_nf_call_ip6tables()
564 *
565 * @return void
566 */
568 uint8_t call_enabled)
569{
570 struct bridge_info *bi = bridge_info(link);
571
572 IS_BRIDGE_INFO_ASSERT(link);
573
574 bi->b_nf_call_ip6tables = call_enabled;
575
576 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IP6TABLES;
577}
578
579/**
580 * Get call enabled flag for passing IPv6 traffic to iptables
581 * @arg link Link object of type bridge
582 * @arg call_enabled Output argument.
583 *
584 * @see rtnl_link_bridge_set_nf_call_ip6tables()
585 *
586 * @return Zero on success, otherwise a negative error code.
587 * @retval -NLE_NOATTR
588 * @retval -NLE_INVAL
589 */
591 uint8_t *call_enabled)
592{
593 struct bridge_info *bi = bridge_info(link);
594
595 IS_BRIDGE_INFO_ASSERT(link);
596
597 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_IP6TABLES))
598 return -NLE_NOATTR;
599
600 if (!call_enabled)
601 return -NLE_INVAL;
602
603 *call_enabled = bi->b_nf_call_ip6tables;
604
605 return 0;
606}
607
608/**
609 * Set call enabled flag for passing ARP traffic to arptables
610 * @arg link Link object of type bridge
611 * @arg call_enabled call enabled boolean flag to set.
612 *
613 * @see rtnl_link_bridge_get_nf_call_arptables()
614 *
615 * @return void
616 */
618 uint8_t call_enabled)
619{
620 struct bridge_info *bi = bridge_info(link);
621
622 IS_BRIDGE_INFO_ASSERT(link);
623
624 bi->b_nf_call_arptables = call_enabled;
625
626 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES;
627}
628
629/**
630 * Get call enabled flag for passing ARP traffic to arptables
631 * @arg link Link object of type bridge
632 * @arg call_enabled Output argument.
633 *
634 * @see rtnl_link_bridge_set_nf_call_arptables()
635 *
636 * @return Zero on success, otherwise a negative error code.
637 * @retval -NLE_NOATTR
638 * @retval -NLE_INVAL
639 */
641 uint8_t *call_enabled)
642{
643 struct bridge_info *bi = bridge_info(link);
644
645 IS_BRIDGE_INFO_ASSERT(link);
646
647 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_ARPTABLES))
648 return -NLE_NOATTR;
649
650 if (!call_enabled)
651 return -NLE_INVAL;
652
653 *call_enabled = bi->b_nf_call_arptables;
654
655 return 0;
656}
657
658/**
659 * Set STP state
660 * @arg link Link object of type bridge
661 * @arg stp_state STP state to set. Typically 0 or 1.
662 *
663 * @see rtnl_link_bridge_get_stp_state()
664 *
665 * @return void
666 */
667void rtnl_link_bridge_set_stp_state(struct rtnl_link *link, uint32_t stp_state)
668{
669 struct bridge_info *bi = bridge_info(link);
670
671 IS_BRIDGE_INFO_ASSERT(link);
672
673 bi->b_stp_state = stp_state;
674
675 bi->ce_mask |= BRIDGE_ATTR_STP_STATE;
676}
677
678/**
679 * Get STP state
680 * @arg link Link object of type bridge
681 * @arg stp_state Output argument.
682 *
683 * @see rtnl_link_bridge_set_stp_state()
684 *
685 * @return Zero on success, otherwise a negative error code.
686 * @retval -NLE_NOATTR
687 * @retval -NLE_INVAL
688 */
689int rtnl_link_bridge_get_stp_state(struct rtnl_link *link, uint32_t *stp_state)
690{
691 struct bridge_info *bi = bridge_info(link);
692
693 IS_BRIDGE_INFO_ASSERT(link);
694
695 if (!(bi->ce_mask & BRIDGE_ATTR_STP_STATE))
696 return -NLE_NOATTR;
697
698 if (!stp_state)
699 return -NLE_INVAL;
700
701 *stp_state = bi->b_stp_state;
702 return 0;
703}
704
705/**
706 * Set multicast router type
707 * @arg link Link object of type bridge
708 * @arg type Multicast router type (MDB_RTR_TYPE_*)
709 *
710 * @see rtnl_link_bridge_get_mcast_router()
711 *
712 * @return void
713 */
714void rtnl_link_bridge_set_mcast_router(struct rtnl_link *link, uint8_t type)
715{
716 struct bridge_info *bi = bridge_info(link);
717
718 IS_BRIDGE_INFO_ASSERT(link);
719
720 bi->b_mcast_router = type;
721
722 bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER;
723}
724
725/**
726 * Get multicast router type
727 * @arg link Link object of type bridge
728 * @arg type Output argument.
729 *
730 * @see rtnl_link_bridge_set_mcast_router()
731 *
732 * @return Zero on success, otherwise a negative error code.
733 * @retval -NLE_NOATTR
734 * @retval -NLE_INVAL
735 */
736int rtnl_link_bridge_get_mcast_router(struct rtnl_link *link, uint8_t *type)
737{
738 struct bridge_info *bi = bridge_info(link);
739
740 IS_BRIDGE_INFO_ASSERT(link);
741
742 if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER))
743 return -NLE_NOATTR;
744
745 if (!type)
746 return -NLE_INVAL;
747
748 *type = bi->b_mcast_router;
749 return 0;
750}
751
752/**
753 * Set multicast snooping
754 * @arg link Link object of type bridge
755 * @arg value Value to set. Typically 0 or 1.
756 *
757 * @see rtnl_link_bridge_get_mcast_snooping()
758 *
759 * @return void
760 */
761void rtnl_link_bridge_set_mcast_snooping(struct rtnl_link *link, uint8_t value)
762{
763 struct bridge_info *bi = bridge_info(link);
764
765 IS_BRIDGE_INFO_ASSERT(link);
766
767 bi->b_mcast_snooping = value;
768
769 bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING;
770}
771
772/**
773 * Get multicast snooping value
774 * @arg link Link object of type bridge
775 * @arg value Output argument.
776 *
777 * @see rtnl_link_bridge_set_mcast_snooping()
778 *
779 * @return Zero on success, otherwise a negative error code.
780 * @retval -NLE_NOATTR
781 * @retval -NLE_INVAL
782 */
783int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, uint8_t *value)
784{
785 struct bridge_info *bi = bridge_info(link);
786
787 IS_BRIDGE_INFO_ASSERT(link);
788
789 if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING))
790 return -NLE_NOATTR;
791
792 if (!value)
793 return -NLE_INVAL;
794
795 *value = bi->b_mcast_snooping;
796 return 0;
797}
798
799/**
800 * Set a the value of a boolopt
801 * @arg link Link object of type bridge
802 * @arg opt Option to modify (BR_BOOLOPT_*)
803 * @arg value Value to set the option to. 0 or 1.
804 *
805 * @see rtnl_link_bridge_get_boolopt()
806 *
807 * @return Zero on success, otherwise a negative error code.
808 * @retval -NLE_INVAL
809 */
810int rtnl_link_bridge_set_boolopt(struct rtnl_link *link, int opt, int value)
811{
812 struct bridge_info *bi = bridge_info(link);
813 uint32_t mask;
814
815 IS_BRIDGE_INFO_ASSERT(link);
816
817 if (opt < 0 || opt >= 32 || !(value == 0 || value == 1))
818 return -NLE_INVAL;
819
820 mask = 1ul << opt;
821
822 if (value)
823 bi->b_boolopts.optval |= mask;
824 else
825 bi->b_boolopts.optval &= ~mask;
826
827 bi->b_boolopts.optmask |= mask;
828 bi->ce_mask |= BRIDGE_ATTR_BOOLOPT;
829
830 return 0;
831}
832
833/**
834 * Get the value of a boolopt
835 * @arg link Link object of type bridge
836 * @arg opt Option to get (BR_BOOLOPT_*).
837 *
838 * @see rtnl_link_bridge_set_boolopt()
839 *
840 * @return The value of the boolopt (0 or 1), otherwise a negative error code.
841 * @retval -NLE_NOATTR
842 * @retval -NLE_INVAL
843 */
844int rtnl_link_bridge_get_boolopt(struct rtnl_link *link, int opt)
845{
846 struct bridge_info *bi = bridge_info(link);
847 uint32_t mask;
848
849 IS_BRIDGE_INFO_ASSERT(link);
850
851 if (opt < 0 || opt >= 32)
852 return -NLE_INVAL;
853
854 mask = 1ul << opt;
855
856 if (!(bi->ce_mask & BRIDGE_ATTR_BOOLOPT) ||
857 !(bi->b_boolopts.optmask & mask))
858 return -NLE_NOATTR;
859
860 return !!(bi->b_boolopts.optval & mask);
861}
862
863static void _nl_init bridge_info_init(void)
864{
865 rtnl_link_register_info(&bridge_info_ops);
866}
867
868static void _nl_exit bridge_info_exit(void)
869{
870 rtnl_link_unregister_info(&bridge_info_ops);
871}
872
873/** @} */
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
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:68