libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/link/bonding.c
00001 /*
00002  * lib/route/link/bonding.c     Bonding Link Module
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2011 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup link
00014  * @defgroup bonding Bonding
00015  *
00016  * @details
00017  * \b Link Type Name: "bond"
00018  *
00019  * @route_doc{link_bonding, Bonding Documentation}
00020  * @{
00021  */
00022 
00023 #include <netlink-local.h>
00024 #include <netlink/netlink.h>
00025 #include <netlink/route/link/api.h>
00026 
00027 /**
00028  * Create a new kernel bonding device
00029  * @arg sock            netlink socket
00030  * @arg name            name of bonding device or NULL
00031  * @arg opts            bonding options (currently unused)
00032  *
00033  * Creates a new bonding device in the kernel. If no name is
00034  * provided, the kernel will automatically pick a name of the
00035  * form "type%d" (e.g. bond0, vlan1, etc.)
00036  *
00037  * The \a opts argument is currently unused. In the future, it
00038  * may be used to carry additional bonding options to be set
00039  * when creating the bonding device.
00040  *
00041  * @note When letting the kernel assign a name, it will become
00042  *       difficult to retrieve the interface afterwards because
00043  *       you have to guess the name the kernel has chosen. It is
00044  *       therefore not recommended to not provide a device name.
00045  *
00046  * @see rtnl_link_bond_enslave()
00047  * @see rtnl_link_bond_release()
00048  *
00049  * @return 0 on success or a negative error code
00050  */
00051 int rtnl_link_bond_add(struct nl_sock *sock, const char *name,
00052                        struct rtnl_link *opts)
00053 {
00054         struct rtnl_link *link;
00055         int err;
00056 
00057         if (!(link = rtnl_link_alloc()))
00058                 return -NLE_NOMEM;
00059 
00060         if (!name) {
00061                 if (opts)
00062                         name = rtnl_link_get_name(opts);
00063 
00064                 if (!name)
00065                         return -NLE_MISSING_ATTR;
00066         }
00067 
00068         if ((err = rtnl_link_set_type(link, "bond")) < 0)
00069                 goto errout;
00070         
00071 
00072                 rtnl_link_set_name(link, name);
00073 
00074         err = rtnl_link_add(sock, link, NLM_F_CREATE);
00075 errout:
00076         rtnl_link_put(link);
00077 
00078         return err;
00079 }
00080 
00081 /**
00082  * Add a link to a bond (enslave)
00083  * @arg sock            netlink socket
00084  * @arg master          ifindex of bonding master
00085  * @arg slave           ifindex of slave link to add to bond
00086  *
00087  * This function is identical to rtnl_link_bond_enslave() except that
00088  * it takes interface indices instead of rtnl_link objcets.
00089  *
00090  * @see rtnl_link_bond_enslave()
00091  *
00092  * @return 0 on success or a negative error code.
00093  */
00094 int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master,
00095                                    int slave)
00096 {
00097         struct rtnl_link *link;
00098         int err;
00099 
00100         if (!(link = rtnl_link_alloc()))
00101                 return -NLE_NOMEM;
00102 
00103         if ((err = rtnl_link_set_type(link, "bond")) < 0)
00104                 goto errout;
00105 
00106         rtnl_link_set_ifindex(link, slave);
00107         rtnl_link_set_master(link, master);
00108         
00109         if ((err = rtnl_link_change(sock, link, link, 0)) < 0)
00110                 goto errout;
00111 
00112         rtnl_link_put(link);
00113 
00114         /*
00115          * Due to the kernel not signaling whether this opertion is
00116          * supported or not, we will retrieve the attribute to see  if the
00117          * request was successful. If the master assigned remains unchanged
00118          * we will return NLE_OPNOTSUPP to allow performing backwards
00119          * compatibility of some sort.
00120          */
00121         if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0)
00122                 return err;
00123 
00124         if (rtnl_link_get_master(link) != master)
00125                 err = -NLE_OPNOTSUPP;
00126 
00127 errout:
00128         rtnl_link_put(link);
00129 
00130         return err;
00131 }
00132 
00133 /**
00134  * Add a link to a bond (enslave)
00135  * @arg sock            netlink socket
00136  * @arg master          bonding master
00137  * @arg slave           slave link to add to bond
00138  *
00139  * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to
00140  * the master and sends the request via the specified netlink socket.
00141  *
00142  * @note The feature of enslaving/releasing via netlink has only been added
00143  *       recently to the kernel (Feb 2011). Also, the kernel does not signal
00144  *       if the operation is not supported. Therefore this function will
00145  *       verify if the master assignment has changed and will return
00146  *       -NLE_OPNOTSUPP if it did not.
00147  *
00148  * @see rtnl_link_bond_enslave_ifindex()
00149  * @see rtnl_link_bond_release()
00150  *
00151  * @return 0 on success or a negative error code.
00152  */
00153 int rtnl_link_bond_enslave(struct nl_sock *sock, struct rtnl_link *master,
00154                            struct rtnl_link *slave)
00155 {
00156         return rtnl_link_bond_enslave_ifindex(sock,
00157                                 rtnl_link_get_ifindex(master),
00158                                 rtnl_link_get_ifindex(slave));
00159 }
00160 
00161 /**
00162  * Release a link from a bond
00163  * @arg sock            netlink socket
00164  * @arg slave           slave link to be released
00165  *
00166  * This function is identical to rtnl_link_bond_release() except that
00167  * it takes an interface index instead of a rtnl_link object.
00168  *
00169  * @see rtnl_link_bond_release()
00170  *
00171  * @return 0 on success or a negative error code.
00172  */
00173 int rtnl_link_bond_release_ifindex(struct nl_sock *sock, int slave)
00174 {
00175         return rtnl_link_bond_enslave_ifindex(sock, 0, slave);
00176 }
00177 
00178 /**
00179  * Release a link from a bond
00180  * @arg sock            netlink socket
00181  * @arg slave           slave link to be released
00182  *
00183  * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from
00184  * its master and sends the request via the specified netlink socket.
00185  *
00186  * @note The feature of enslaving/releasing via netlink has only been added
00187  *       recently to the kernel (Feb 2011). Also, the kernel does not signal
00188  *       if the operation is not supported. Therefore this function will
00189  *       verify if the master assignment has changed and will return
00190  *       -NLE_OPNOTSUPP if it did not.
00191  *
00192  * @see rtnl_link_bond_release_ifindex()
00193  * @see rtnl_link_bond_enslave()
00194  *
00195  * @return 0 on success or a negative error code.
00196  */
00197 int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave)
00198 {
00199         return rtnl_link_bond_release_ifindex(sock,
00200                                 rtnl_link_get_ifindex(slave));
00201 }
00202 
00203 static struct rtnl_link_info_ops bonding_info_ops = {
00204         .io_name                = "bond",
00205 };
00206 
00207 static void __init bonding_init(void)
00208 {
00209         rtnl_link_register_info(&bonding_info_ops);
00210 }
00211 
00212 static void __exit bonding_exit(void)
00213 {
00214         rtnl_link_unregister_info(&bonding_info_ops);
00215 }
00216 
00217 /** @} */