bonding.c 5.9 KB

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