libnl 3.9.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 <netlink/route/link/bridge_info.h>
17
18#include "nl-route.h"
19#include "link-api.h"
20
21#define BRIDGE_ATTR_VLAN_FILTERING (1 << 0)
22#define BRIDGE_ATTR_VLAN_PROTOCOL (1 << 1)
23#define BRIDGE_ATTR_VLAN_STATS_ENABLED (1 << 2)
24
26 uint32_t ce_mask; /* to support attr macros */
27 uint16_t b_vlan_protocol;
28 uint8_t b_vlan_filtering;
29 uint8_t b_vlan_stats_enabled;
30};
31
32static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = {
33 [IFLA_BR_VLAN_FILTERING] = { .type = NLA_U8 },
34 [IFLA_BR_VLAN_PROTOCOL] = { .type = NLA_U16 },
35 [IFLA_BR_VLAN_STATS_ENABLED] = { .type = NLA_U8 },
36};
37
38static inline struct bridge_info *bridge_info(struct rtnl_link *link)
39{
40 return link->l_info;
41}
42
43static int bridge_info_alloc(struct rtnl_link *link)
44{
45 struct bridge_info *bi;
46
47 if (link->l_info)
48 memset(link->l_info, 0, sizeof(*bi));
49 else {
50 bi = calloc(1, sizeof(*bi));
51 if (!bi)
52 return -NLE_NOMEM;
53
54 link->l_info = bi;
55 }
56
57 return 0;
58}
59
60static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data,
61 struct nlattr *xstats)
62{
63 struct nlattr *tb[IFLA_BR_MAX + 1];
64 struct bridge_info *bi;
65 int err;
66
67 NL_DBG(3, "Parsing Bridge link info\n");
68
69 if ((err = nla_parse_nested(tb, IFLA_BR_MAX, data, bi_attrs_policy)) <
70 0)
71 return err;
72
73 if ((err = bridge_info_alloc(link)) < 0)
74 return err;
75
76 bi = link->l_info;
77
78 if (tb[IFLA_BR_VLAN_FILTERING]) {
79 bi->b_vlan_filtering = nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]);
80 bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
81 }
82
83 if (tb[IFLA_BR_VLAN_PROTOCOL]) {
84 bi->b_vlan_protocol =
85 ntohs(nla_get_u16(tb[IFLA_BR_VLAN_PROTOCOL]));
86 bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
87 }
88
89 if (tb[IFLA_BR_VLAN_STATS_ENABLED]) {
90 bi->b_vlan_stats_enabled =
91 nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]);
92 bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
93 }
94
95 return 0;
96}
97
98static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
99{
100 struct bridge_info *bi = link->l_info;
101 struct nlattr *data;
102
103 data = nla_nest_start(msg, IFLA_INFO_DATA);
104 if (!data)
105 return -NLE_MSGSIZE;
106
107 if (bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING)
108 NLA_PUT_U8(msg, IFLA_BR_VLAN_FILTERING, bi->b_vlan_filtering);
109
110 if (bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL)
111 NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL,
112 htons(bi->b_vlan_protocol));
113
114 if (bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED)
115 NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED,
116 bi->b_vlan_stats_enabled);
117
118 nla_nest_end(msg, data);
119 return 0;
120
121nla_put_failure:
122 nla_nest_cancel(msg, data);
123 return -NLE_MSGSIZE;
124}
125
126static void bridge_info_free(struct rtnl_link *link)
127{
128 _nl_clear_free(&link->l_info);
129}
130
131static struct rtnl_link_info_ops bridge_info_ops = {
132 .io_name = "bridge",
133 .io_alloc = bridge_info_alloc,
134 .io_parse = bridge_info_parse,
135 .io_put_attrs = bridge_info_put_attrs,
136 .io_free = bridge_info_free,
137};
138
139#define IS_BRIDGE_INFO_ASSERT(link) \
140 do { \
141 if ((link)->l_info_ops != &bridge_info_ops) { \
142 APPBUG("Link is not a bridge link. Set type \"bridge\" first."); \
143 } \
144 } while (0)
145
146/**
147 * Set VLAN filtering flag
148 * @arg link Link object of type bridge
149 * @arg vlan_filtering VLAN_filtering boolean flag to set.
150 *
151 * @see rtnl_link_bridge_get_vlan_filtering()
152 *
153 * @return void
154 */
156 uint8_t vlan_filtering)
157{
158 struct bridge_info *bi = bridge_info(link);
159
160 IS_BRIDGE_INFO_ASSERT(link);
161
162 bi->b_vlan_filtering = vlan_filtering;
163
164 bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
165}
166
167/**
168 * Get VLAN filtering flag
169 * @arg link Link object of type bridge
170 * @arg vlan_filtering Output argument.
171 *
172 * @see rtnl_link_bridge_set_vlan_filtering()
173 *
174 * @return Zero on success, otherwise a negative error code.
175 * @retval -NLE_NOATTR
176 * @retval -NLE_INVAL
177 */
179 uint8_t *vlan_filtering)
180{
181 struct bridge_info *bi = bridge_info(link);
182
183 IS_BRIDGE_INFO_ASSERT(link);
184
185 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING))
186 return -NLE_NOATTR;
187
188 if (!vlan_filtering)
189 return -NLE_INVAL;
190
191 *vlan_filtering = bi->b_vlan_filtering;
192 return 0;
193}
194
195/**
196 * Set VLAN protocol
197 * @arg link Link object of type bridge
198 * @arg vlan_protocol VLAN protocol to set. The protocol
199 * numbers is in host byte order.
200 *
201 * @see rtnl_link_bridge_get_vlan_protocol()
202 *
203 * @return void
204 */
206 uint16_t vlan_protocol)
207{
208 struct bridge_info *bi = bridge_info(link);
209
210 IS_BRIDGE_INFO_ASSERT(link);
211
212 bi->b_vlan_protocol = vlan_protocol;
213
214 bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
215}
216
217/**
218 * Get VLAN protocol
219 * @arg link Link object of type bridge
220 * @arg vlan_protocol Output argument. The protocol number is in host byte order.
221 *
222 * @see rtnl_link_bridge_set_vlan_protocol()
223 *
224 * @return Zero on success, otherwise a negative error code.
225 * @retval -NLE_NOATTR
226 * @retval -NLE_INVAL
227 */
229 uint16_t *vlan_protocol)
230{
231 struct bridge_info *bi = bridge_info(link);
232
233 IS_BRIDGE_INFO_ASSERT(link);
234
235 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL))
236 return -NLE_NOATTR;
237
238 if (!vlan_protocol)
239 return -NLE_INVAL;
240
241 *vlan_protocol = bi->b_vlan_protocol;
242
243 return 0;
244}
245
246/**
247 * Set VLAN stats enabled flag
248 * @arg link Link object of type bridge
249 * @arg vlan_stats_enabled VLAN stats enabled flag to set
250 *
251 * @see rtnl_link_bridge_get_vlan_stats_enabled()
252 *
253 * @return void
254 */
256 uint8_t vlan_stats_enabled)
257{
258 struct bridge_info *bi = bridge_info(link);
259
260 IS_BRIDGE_INFO_ASSERT(link);
261
262 bi->b_vlan_stats_enabled = vlan_stats_enabled;
263
264 bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
265}
266
267/**
268 * Get VLAN stats enabled flag
269 * @arg link Link object of type bridge
270 * @arg vlan_stats_enabled Output argument.
271 *
272 * @see rtnl_link_bridge_set_vlan_stats_enabled()
273 *
274 * @return Zero on success, otherwise a negative error code.
275 * @retval -NLE_NOATTR
276 * @retval -NLE_INVAL
277 */
279 uint8_t *vlan_stats_enabled)
280{
281 struct bridge_info *bi = bridge_info(link);
282
283 IS_BRIDGE_INFO_ASSERT(link);
284
285 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED))
286 return -NLE_NOATTR;
287
288 if (!vlan_stats_enabled)
289 return -NLE_INVAL;
290
291 *vlan_stats_enabled = bi->b_vlan_stats_enabled;
292
293 return 0;
294}
295
296static void _nl_init bridge_info_init(void)
297{
298 rtnl_link_register_info(&bridge_info_ops);
299}
300
301static void _nl_exit bridge_info_exit(void)
302{
303 rtnl_link_unregister_info(&bridge_info_ops);
304}
305
306/** @} */
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition attr.c:660
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition attr.h:212
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition attr.h:194
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:610
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:906
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:1033
void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr)
Cancel the addition of a nested attribute.
Definition attr.c:998
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:969
@ NLA_U8
8 bit integer
Definition attr.h:35
@ NLA_U16
16 bit integer
Definition attr.h:36
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.
int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link, uint8_t *vlan_filtering)
Get VLAN filtering flag.
int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, uint8_t *vlan_stats_enabled)
Get VLAN stats enabled flag.
void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link, uint16_t vlan_protocol)
Set VLAN protocol.
Attribute validation policy.
Definition attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:65