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