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