libnl  3.6.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 <netlink-private/netlink.h>
18 #include <netlink/netlink.h>
19 #include <netlink/route/link/bonding.h>
20 #include <netlink-private/route/link/api.h>
21 
22 /**
23  * Allocate link object of type bond
24  *
25  * @return Allocated link object or NULL.
26  */
28 {
29  struct rtnl_link *link;
30  int err;
31 
32  if (!(link = rtnl_link_alloc()))
33  return NULL;
34 
35  if ((err = rtnl_link_set_type(link, "bond")) < 0) {
36  rtnl_link_put(link);
37  return NULL;
38  }
39 
40  return link;
41 }
42 
43 /**
44  * Create a new kernel bonding device
45  * @arg sock netlink socket
46  * @arg name name of bonding device or NULL
47  * @arg opts bonding options (currently unused)
48  *
49  * Creates a new bonding device in the kernel. If no name is
50  * provided, the kernel will automatically pick a name of the
51  * form "type%d" (e.g. bond0, vlan1, etc.)
52  *
53  * The \a opts argument is currently unused. In the future, it
54  * may be used to carry additional bonding options to be set
55  * when creating the bonding device.
56  *
57  * @note When letting the kernel assign a name, it will become
58  * difficult to retrieve the interface afterwards because
59  * you have to guess the name the kernel has chosen. It is
60  * therefore not recommended to not provide a device name.
61  *
62  * @see rtnl_link_bond_enslave()
63  * @see rtnl_link_bond_release()
64  *
65  * @return 0 on success or a negative error code
66  */
67 int rtnl_link_bond_add(struct nl_sock *sock, const char *name,
68  struct rtnl_link *opts)
69 {
70  struct rtnl_link *link;
71  int err;
72 
73  if (!(link = rtnl_link_bond_alloc()))
74  return -NLE_NOMEM;
75 
76  if (!name && opts)
77  name = rtnl_link_get_name(opts);
78 
79  if (name)
80  rtnl_link_set_name(link, name);
81 
82  err = rtnl_link_add(sock, link, NLM_F_CREATE);
83 
84  rtnl_link_put(link);
85 
86  return err;
87 }
88 
89 /**
90  * Add a link to a bond (enslave)
91  * @arg sock netlink socket
92  * @arg master ifindex of bonding master
93  * @arg slave ifindex of slave link to add to bond
94  *
95  * This function is identical to rtnl_link_bond_enslave() except that
96  * it takes interface indices instead of rtnl_link objcets.
97  *
98  * @see rtnl_link_bond_enslave()
99  *
100  * @return 0 on success or a negative error code.
101  */
102 int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master,
103  int slave)
104 {
105  struct rtnl_link *link;
106  int err;
107 
108  if (!(link = rtnl_link_bond_alloc()))
109  return -NLE_NOMEM;
110 
111  rtnl_link_set_ifindex(link, slave);
112  rtnl_link_set_master(link, master);
113 
114  if ((err = rtnl_link_change(sock, link, link, 0)) < 0)
115  goto errout;
116 
117  rtnl_link_put(link);
118 
119  /*
120  * Due to the kernel not signaling whether this opertion is
121  * supported or not, we will retrieve the attribute to see if the
122  * request was successful. If the master assigned remains unchanged
123  * we will return NLE_OPNOTSUPP to allow performing backwards
124  * compatibility of some sort.
125  */
126  if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0)
127  return err;
128 
129  if (rtnl_link_get_master(link) != master)
130  err = -NLE_OPNOTSUPP;
131 
132 errout:
133  rtnl_link_put(link);
134 
135  return err;
136 }
137 
138 /**
139  * Add a link to a bond (enslave)
140  * @arg sock netlink socket
141  * @arg master bonding master
142  * @arg slave slave link to add to bond
143  *
144  * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to
145  * the master and sends the request via the specified netlink socket.
146  *
147  * @note The feature of enslaving/releasing via netlink has only been added
148  * recently to the kernel (Feb 2011). Also, the kernel does not signal
149  * if the operation is not supported. Therefore this function will
150  * verify if the master assignment has changed and will return
151  * -NLE_OPNOTSUPP if it did not.
152  *
153  * @see rtnl_link_bond_enslave_ifindex()
154  * @see rtnl_link_bond_release()
155  *
156  * @return 0 on success or a negative error code.
157  */
158 int rtnl_link_bond_enslave(struct nl_sock *sock, struct rtnl_link *master,
159  struct rtnl_link *slave)
160 {
161  return rtnl_link_bond_enslave_ifindex(sock,
162  rtnl_link_get_ifindex(master),
163  rtnl_link_get_ifindex(slave));
164 }
165 
166 /**
167  * Release a link from a bond
168  * @arg sock netlink socket
169  * @arg slave slave link to be released
170  *
171  * This function is identical to rtnl_link_bond_release() except that
172  * it takes an interface index instead of a rtnl_link object.
173  *
174  * @see rtnl_link_bond_release()
175  *
176  * @return 0 on success or a negative error code.
177  */
178 int rtnl_link_bond_release_ifindex(struct nl_sock *sock, int slave)
179 {
180  return rtnl_link_bond_enslave_ifindex(sock, 0, slave);
181 }
182 
183 /**
184  * Release a link from a bond
185  * @arg sock netlink socket
186  * @arg slave slave link to be released
187  *
188  * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from
189  * its master and sends the request via the specified netlink socket.
190  *
191  * @note The feature of enslaving/releasing via netlink has only been added
192  * recently to the kernel (Feb 2011). Also, the kernel does not signal
193  * if the operation is not supported. Therefore this function will
194  * verify if the master assignment has changed and will return
195  * -NLE_OPNOTSUPP if it did not.
196  *
197  * @see rtnl_link_bond_release_ifindex()
198  * @see rtnl_link_bond_enslave()
199  *
200  * @return 0 on success or a negative error code.
201  */
202 int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave)
203 {
204  return rtnl_link_bond_release_ifindex(sock,
205  rtnl_link_get_ifindex(slave));
206 }
207 
208 static struct rtnl_link_info_ops bonding_info_ops = {
209  .io_name = "bond",
210 };
211 
212 static void __init bonding_init(void)
213 {
214  rtnl_link_register_info(&bonding_info_ops);
215 }
216 
217 static void __exit bonding_exit(void)
218 {
219  rtnl_link_unregister_info(&bonding_info_ops);
220 }
221 
222 /** @} */
struct rtnl_link * rtnl_link_bond_alloc(void)
Allocate link object of type bond.
Definition: bonding.c:27
int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master, int slave)
Add a link to a bond (enslave)
Definition: bonding.c:102
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:67
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:158
int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave)
Release a link from a bond.
Definition: bonding.c:202
int rtnl_link_bond_release_ifindex(struct nl_sock *sock, int slave)
Release a link from a bond.
Definition: bonding.c:178