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