libnl: /data/src/libnl3/lib/route/link/bonding.c Source File

libnl 3.10.0

bonding.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2011-2013 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup link
8 * @defgroup bonding Bonding
9 *
10 * @details
11 * \b Link Type Name: "bond"
12 *
13 * @route_doc{link_bonding, Bonding Documentation}
14 * @{
15 */
16
17#include "nl-default.h"
18
19#include <netlink/netlink.h>
20#include <netlink/route/link/bonding.h>
21
22#include "nl-route.h"
23#include "link-api.h"
24
25#define BOND_HAS_MODE (1 << 0)
26#define BOND_HAS_ACTIVE_SLAVE (1 << 1)
27#define BOND_HAS_HASHING_TYPE (1 << 2)
28#define BOND_HAS_MIIMON (1 << 3)
29#define BOND_HAS_MIN_LINKS (1 << 4)
30
31 struct bond_info {
32 uint8_t bn_mode;
33 uint8_t hashing_type;
34 uint32_t ifindex;
35 uint32_t bn_mask;
36 uint32_t miimon;
37 uint32_t min_links;
38};
39
40static int bond_info_alloc(struct rtnl_link *link)
41{
42 struct bond_info *bn;
43
44 if (link->l_info)
45 memset(link->l_info, 0, sizeof(*bn));
46 else {
47 bn = calloc(1, sizeof(*bn));
48 if (!bn)
49 return -NLE_NOMEM;
50
51 link->l_info = bn;
52 }
53
54 return 0;
55}
56
57static void bond_info_free(struct rtnl_link *link)
58{
59 _nl_clear_free(&link->l_info);
60}
61
62static int bond_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
63{
64 struct bond_info *bn = link->l_info;
65 struct nlattr *data;
66
67 data = nla_nest_start(msg, IFLA_INFO_DATA);
68 if (!data)
69 return -NLE_MSGSIZE;
70 if (bn->bn_mask & BOND_HAS_MODE)
71 NLA_PUT_U8(msg, IFLA_BOND_MODE, bn->bn_mode);
72
73 if (bn->bn_mask & BOND_HAS_ACTIVE_SLAVE)
74 NLA_PUT_U32(msg, IFLA_BOND_ACTIVE_SLAVE, bn->ifindex);
75
76 if (bn->bn_mask & BOND_HAS_HASHING_TYPE)
77 NLA_PUT_U8(msg, IFLA_BOND_XMIT_HASH_POLICY, bn->hashing_type);
78
79 if (bn->bn_mask & BOND_HAS_MIIMON)
80 NLA_PUT_U32(msg, IFLA_BOND_MIIMON, bn->miimon);
81
82 if (bn->bn_mask & BOND_HAS_MIN_LINKS)
83 NLA_PUT_U32(msg, IFLA_BOND_MIN_LINKS, bn->min_links);
84
85 nla_nest_end(msg, data);
86 return 0;
87
88nla_put_failure:
89 nla_nest_cancel(msg, data);
90 return -NLE_MSGSIZE;
91}
92
93static struct rtnl_link_info_ops bonding_info_ops = {
94 .io_name = "bond",
95 .io_alloc = bond_info_alloc,
96 .io_put_attrs = bond_put_attrs,
97 .io_free = bond_info_free,
98};
99
100#define IS_BOND_INFO_ASSERT(link) \
101 do { \
102 if (link->l_info_ops != &bonding_info_ops) { \
103 APPBUG("Link is not a bond link. Set type \"bond\" first."); \
104 } \
105 } while (0)
106
107/**
108 * Set active slave for bond
109 * @arg link Link object of type bond
110 * @arg active ifindex of active slave to set
111 *
112 * @return void
113 */
114 void rtnl_link_bond_set_activeslave(struct rtnl_link *link, int active_slave)
115{
116 struct bond_info *bn = link->l_info;
117
118 IS_BOND_INFO_ASSERT(link);
119
120 bn->ifindex = active_slave;
121
122 bn->bn_mask |= BOND_HAS_ACTIVE_SLAVE;
123}
124
125/**
126 * Set bond mode
127 * @arg link Link object of type bond
128 * @arg mode bond mode to set
129 *
130 * @return void
131 */
132 void rtnl_link_bond_set_mode(struct rtnl_link *link, uint8_t mode)
133{
134 struct bond_info *bn = link->l_info;
135
136 IS_BOND_INFO_ASSERT(link);
137
138 bn->bn_mode = mode;
139
140 bn->bn_mask |= BOND_HAS_MODE;
141}
142
143/**
144 * Set hashing type
145 * @arg link Link object of type bond
146 * @arg type bond hashing type to set
147 *
148 * @return void
149 */
150 void rtnl_link_bond_set_hashing_type (struct rtnl_link *link, uint8_t type)
151{
152 struct bond_info *bn = link->l_info;
153
154 IS_BOND_INFO_ASSERT(link);
155
156 bn->hashing_type = type;
157
158 bn->bn_mask |= BOND_HAS_HASHING_TYPE;
159}
160
161/**
162 * Set MII monitoring interval
163 * @arg link Link object of type bond
164 * @arg miimon interval in milliseconds
165 *
166 * @return void
167 */
168 void rtnl_link_bond_set_miimon (struct rtnl_link *link, uint32_t miimon)
169{
170 struct bond_info *bn = link->l_info;
171
172 IS_BOND_INFO_ASSERT(link);
173
174 bn->miimon = miimon;
175
176 bn->bn_mask |= BOND_HAS_MIIMON;
177}
178
179/**
180 * Set the minimum number of member ports that must be up before
181 * marking the bond device as up
182 * @arg link Link object of type bond
183 * @arg min_links Number of links
184 *
185 * @return void
186 */
187 void rtnl_link_bond_set_min_links (struct rtnl_link *link, uint32_t min_links)
188{
189 struct bond_info *bn = link->l_info;
190
191 IS_BOND_INFO_ASSERT(link);
192
193 bn->min_links = min_links;
194
195 bn->bn_mask |= BOND_HAS_MIN_LINKS;
196}
197
198/**
199 * Allocate link object of type bond
200 *
201 * @return Allocated link object or NULL.
202 */
203 struct rtnl_link *rtnl_link_bond_alloc(void)
204{
205 struct rtnl_link *link;
206
207 if (!(link = rtnl_link_alloc()))
208 return NULL;
209
210 if (rtnl_link_set_type(link, "bond") < 0) {
211 rtnl_link_put(link);
212 return NULL;
213 }
214
215 return link;
216}
217
218/**
219 * Create a new kernel bonding device
220 * @arg sock netlink socket
221 * @arg name name of bonding device or NULL
222 * @arg opts bonding options (currently unused)
223 *
224 * Creates a new bonding device in the kernel. If no name is
225 * provided, the kernel will automatically pick a name of the
226 * form "type%d" (e.g. bond0, vlan1, etc.)
227 *
228 * The \a opts argument is currently unused. In the future, it
229 * may be used to carry additional bonding options to be set
230 * when creating the bonding device.
231 *
232 * @note When letting the kernel assign a name, it will become
233 * difficult to retrieve the interface afterwards because
234 * you have to guess the name the kernel has chosen. It is
235 * therefore not recommended to not provide a device name.
236 *
237 * @see rtnl_link_bond_enslave()
238 * @see rtnl_link_bond_release()
239 *
240 * @return 0 on success or a negative error code
241 */
242 int rtnl_link_bond_add(struct nl_sock *sock, const char *name,
243 struct rtnl_link *opts)
244{
245 struct rtnl_link *link;
246 int err;
247
248 if (!(link = rtnl_link_bond_alloc()))
249 return -NLE_NOMEM;
250
251 if (!name && opts)
252 name = rtnl_link_get_name(opts);
253
254 if (name)
255 rtnl_link_set_name(link, name);
256
257 err = rtnl_link_add(sock, link, NLM_F_CREATE);
258
259 rtnl_link_put(link);
260
261 return err;
262}
263
264/**
265 * Add a link to a bond (enslave)
266 * @arg sock netlink socket
267 * @arg master ifindex of bonding master
268 * @arg slave ifindex of slave link to add to bond
269 *
270 * This function is identical to rtnl_link_bond_enslave() except that
271 * it takes interface indices instead of rtnl_link objcets.
272 *
273 * @see rtnl_link_bond_enslave()
274 *
275 * @return 0 on success or a negative error code.
276 */
277 int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master,
278 int slave)
279{
280 struct rtnl_link *link;
281 int err;
282
283 if (!(link = rtnl_link_bond_alloc()))
284 return -NLE_NOMEM;
285
286 rtnl_link_set_ifindex(link, slave);
287 rtnl_link_set_master(link, master);
288
289 if ((err = rtnl_link_change(sock, link, link, 0)) < 0)
290 goto errout;
291
292 rtnl_link_put(link);
293
294 /*
295 * Due to the kernel not signaling whether this opertion is
296 * supported or not, we will retrieve the attribute to see if the
297 * request was successful. If the master assigned remains unchanged
298 * we will return NLE_OPNOTSUPP to allow performing backwards
299 * compatibility of some sort.
300 */
301 if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0)
302 return err;
303
304 if (rtnl_link_get_master(link) != master)
305 err = -NLE_OPNOTSUPP;
306
307errout:
308 rtnl_link_put(link);
309
310 return err;
311}
312
313/**
314 * Add a link to a bond (enslave)
315 * @arg sock netlink socket
316 * @arg master bonding master
317 * @arg slave slave link to add to bond
318 *
319 * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to
320 * the master and sends the request via the specified netlink socket.
321 *
322 * @note The feature of enslaving/releasing via netlink has only been added
323 * recently to the kernel (Feb 2011). Also, the kernel does not signal
324 * if the operation is not supported. Therefore this function will
325 * verify if the master assignment has changed and will return
326 * -NLE_OPNOTSUPP if it did not.
327 *
328 * @see rtnl_link_bond_enslave_ifindex()
329 * @see rtnl_link_bond_release()
330 *
331 * @return 0 on success or a negative error code.
332 */
333 int rtnl_link_bond_enslave(struct nl_sock *sock, struct rtnl_link *master,
334 struct rtnl_link *slave)
335{
336 return rtnl_link_bond_enslave_ifindex(sock,
337 rtnl_link_get_ifindex(master),
338 rtnl_link_get_ifindex(slave));
339}
340
341/**
342 * Release a link from a bond
343 * @arg sock netlink socket
344 * @arg slave slave link to be released
345 *
346 * This function is identical to rtnl_link_bond_release() except that
347 * it takes an interface index instead of a rtnl_link object.
348 *
349 * @see rtnl_link_bond_release()
350 *
351 * @return 0 on success or a negative error code.
352 */
353 int rtnl_link_bond_release_ifindex(struct nl_sock *sock, int slave)
354{
355 return rtnl_link_bond_enslave_ifindex(sock, 0, slave);
356}
357
358/**
359 * Release a link from a bond
360 * @arg sock netlink socket
361 * @arg slave slave link to be released
362 *
363 * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from
364 * its master and sends the request via the specified netlink socket.
365 *
366 * @note The feature of enslaving/releasing via netlink has only been added
367 * recently to the kernel (Feb 2011). Also, the kernel does not signal
368 * if the operation is not supported. Therefore this function will
369 * verify if the master assignment has changed and will return
370 * -NLE_OPNOTSUPP if it did not.
371 *
372 * @see rtnl_link_bond_release_ifindex()
373 * @see rtnl_link_bond_enslave()
374 *
375 * @return 0 on success or a negative error code.
376 */
377 int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave)
378{
379 return rtnl_link_bond_release_ifindex(sock,
380 rtnl_link_get_ifindex(slave));
381}
382
383static void _nl_init bonding_init(void)
384{
385 rtnl_link_register_info(&bonding_info_ops);
386}
387
388static void _nl_exit bonding_exit(void)
389{
390 rtnl_link_unregister_info(&bonding_info_ops);
391}
392
393/** @} */
NLA_PUT_U8
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition attr.h:194
NLA_PUT_U32
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:230
nla_nest_start
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:908
nla_nest_cancel
void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr)
Cancel the addition of a nested attribute.
Definition attr.c:1000
nla_nest_end
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:971
rtnl_link_bond_set_mode
void rtnl_link_bond_set_mode(struct rtnl_link *link, uint8_t mode)
Set bond mode.
Definition bonding.c:132
rtnl_link_bond_set_min_links
void rtnl_link_bond_set_min_links(struct rtnl_link *link, uint32_t min_links)
Set the minimum number of member ports that must be up before marking the bond device as up.
Definition bonding.c:187
rtnl_link_bond_set_activeslave
void rtnl_link_bond_set_activeslave(struct rtnl_link *link, int active_slave)
Set active slave for bond.
Definition bonding.c:114
rtnl_link_bond_enslave_ifindex
int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master, int slave)
Add a link to a bond (enslave)
Definition bonding.c:277
rtnl_link_bond_add
int rtnl_link_bond_add(struct nl_sock *sock, const char *name, struct rtnl_link *opts)
Create a new kernel bonding device.
Definition bonding.c:242
rtnl_link_bond_alloc
struct rtnl_link * rtnl_link_bond_alloc(void)
Allocate link object of type bond.
Definition bonding.c:203
rtnl_link_bond_enslave
int rtnl_link_bond_enslave(struct nl_sock *sock, struct rtnl_link *master, struct rtnl_link *slave)
Add a link to a bond (enslave)
Definition bonding.c:333
rtnl_link_bond_release
int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave)
Release a link from a bond.
Definition bonding.c:377
rtnl_link_bond_set_hashing_type
void rtnl_link_bond_set_hashing_type(struct rtnl_link *link, uint8_t type)
Set hashing type.
Definition bonding.c:150
rtnl_link_bond_release_ifindex
int rtnl_link_bond_release_ifindex(struct nl_sock *sock, int slave)
Release a link from a bond.
Definition bonding.c:353
rtnl_link_bond_set_miimon
void rtnl_link_bond_set_miimon(struct rtnl_link *link, uint32_t miimon)
Set MII monitoring interval.
Definition bonding.c:168
rtnl_link_register_info
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
Register operations for a link info type.
Definition api.c:127
rtnl_link_unregister_info
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
Definition api.c:162
rtnl_link_add
int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
Add virtual link.
Definition link.c:1694
rtnl_link_get_master
int rtnl_link_get_master(struct rtnl_link *link)
Return master link of link object.
Definition link.c:2320
rtnl_link_alloc
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
Definition link.c:1920
rtnl_link_set_name
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set name of link object.
Definition link.c:1948
rtnl_link_get_kernel
int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, struct rtnl_link **result)
Get a link object directly from kernel.
Definition link.c:1431
rtnl_link_get_name
char * rtnl_link_get_name(struct rtnl_link *link)
Return name of link object.
Definition link.c:1962
rtnl_link_put
void rtnl_link_put(struct rtnl_link *link)
Release a link object reference.
Definition link.c:1929
rtnl_link_set_type
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
Definition link.c:2558
rtnl_link_set_master
void rtnl_link_set_master(struct rtnl_link *link, int ifindex)
Set master link of link object.
Definition link.c:2307
rtnl_link_set_ifindex
void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex)
Set interface index of link object.
Definition link.c:2177
rtnl_link_get_ifindex
int rtnl_link_get_ifindex(struct rtnl_link *link)
Return interface index of link object.
Definition link.c:2192
rtnl_link_change
int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *orig, struct rtnl_link *changes, int flags)
Change link.
Definition link.c:1797
bond_info
Definition bonding.c:31
rtnl_link_info_ops
Available operations to modules implementing a link info type.
Definition link-api.h:20
rtnl_link_info_ops::io_name
char * io_name
Name of link info type, must match name on kernel side.
Definition link-api.h:22
rtnl_link
Link object.
Definition nl-route.h:29