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