diff options
-rw-r--r-- | include/netlink/route/link/bonding.h | 37 | ||||
-rw-r--r-- | lib/route/link/bonding.c | 176 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/nl-link-enslave.c | 50 | ||||
-rw-r--r-- | src/nl-link-release.c | 45 |
5 files changed, 311 insertions, 1 deletions
diff --git a/include/netlink/route/link/bonding.h b/include/netlink/route/link/bonding.h new file mode 100644 index 0000000..cca777a --- /dev/null +++ b/include/netlink/route/link/bonding.h @@ -0,0 +1,37 @@ +/* + * netlink/route/link/bonding.h Bonding Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf <tgraf@suug.ch> + */ + +#ifndef NETLINK_LINK_VLAN_H_ +#define NETLINK_LINK_VLAN_H_ + +#include <netlink/netlink.h> +#include <netlink/route/link.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_link_bond_add(struct nl_sock *, const char *, + struct rtnl_link *); + +extern int rtnl_link_bond_enslave_ifindex(struct nl_sock *, int, int); +extern int rtnl_link_bond_enslave(struct nl_sock *, struct rtnl_link *, + struct rtnl_link *); + +extern int rtnl_link_bond_release_ifindex(struct nl_sock *, int); +extern int rtnl_link_bond_release(struct nl_sock *, struct rtnl_link *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c index 176be27..5788f69 100644 --- a/lib/route/link/bonding.c +++ b/lib/route/link/bonding.c @@ -24,6 +24,182 @@ #include <netlink/netlink.h> #include <netlink/route/link/api.h> +/** + * Create a new kernel bonding device + * @arg sock netlink socket + * @arg name name of bonding device or NULL + * @arg opts bonding options (currently unused) + * + * Creates a new bonding device in the kernel. If no name is + * provided, the kernel will automatically pick a name of the + * form "type%d" (e.g. bond0, vlan1, etc.) + * + * The \a opts argument is currently unused. In the future, it + * may be used to carry additional bonding options to be set + * when creating the bonding device. + * + * @note When letting the kernel assign a name, it will become + * difficult to retrieve the interface afterwards because + * you have to guess the name the kernel has chosen. It is + * therefore not recommended to not provide a device name. + * + * @see rtnl_link_bond_enslave() + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code + */ +int rtnl_link_bond_add(struct nl_sock *sock, const char *name, + struct rtnl_link *opts) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return -NLE_NOMEM; + + if (!name) { + if (opts) + name = rtnl_link_get_name(opts); + + if (!name) + return -NLE_MISSING_ATTR; + } + + if ((err = rtnl_link_set_type(link, "bond")) < 0) + goto errout; + + + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sock, link, NLM_F_CREATE); +errout: + rtnl_link_put(link); + + return err; +} + +/** + * Add a link to a bond (enslave) + * @arg sock netlink socket + * @arg master ifindex of bonding master + * @arg slave ifindex of slave link to add to bond + * + * This function is identical to rtnl_link_bond_enslave() except that + * it takes interface indices instead of rtnl_link objcets. + * + * @see rtnl_link_bond_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master, + int slave) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return -NLE_NOMEM; + + if ((err = rtnl_link_set_type(link, "bond")) < 0) + goto errout; + + rtnl_link_set_ifindex(link, slave); + rtnl_link_set_master(link, master); + + if ((err = rtnl_link_change(sock, link, link, 0)) < 0) + goto errout; + + rtnl_link_put(link); + + /* + * Due to the kernel not signaling whether this opertion is + * supported or not, we will retrieve the attribute to see if the + * request was successful. If the master assigned remains unchanged + * we will return NLE_OPNOTSUPP to allow performing backwards + * compatibility of some sort. + */ + if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) + return err; + + if (rtnl_link_get_master(link) != master) + err = -NLE_OPNOTSUPP; + +errout: + rtnl_link_put(link); + + return err; +} + +/** + * Add a link to a bond (enslave) + * @arg sock netlink socket + * @arg master bonding master + * @arg slave slave link to add to bond + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to + * the master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_bond_enslave_ifindex() + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_enslave(struct nl_sock *sock, struct rtnl_link *master, + struct rtnl_link *slave) +{ + return rtnl_link_bond_enslave_ifindex(sock, + rtnl_link_get_ifindex(master), + rtnl_link_get_ifindex(slave)); +} + +/** + * Release a link from a bond + * @arg sock netlink socket + * @arg slave slave link to be released + * + * This function is identical to rtnl_link_bond_release() except that + * it takes an interface index instead of a rtnl_link object. + * + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_release_ifindex(struct nl_sock *sock, int slave) +{ + return rtnl_link_bond_enslave_ifindex(sock, 0, slave); +} + +/** + * Release a link from a bond + * @arg sock netlink socket + * @arg slave slave link to be released + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from + * its master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_bond_release_ifindex() + * @see rtnl_link_bond_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave) +{ + return rtnl_link_bond_release_ifindex(sock, + rtnl_link_get_ifindex(slave)); +} + static struct rtnl_link_info_ops bonding_info_ops = { .io_name = "bond", }; diff --git a/src/Makefile.am b/src/Makefile.am index 3b5c140..b59f96a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,7 +33,9 @@ noinst_PROGRAMS = \ nl-route-add nl-route-delete nl-route-get nl-route-list \ nl-fib-lookup \ nl-list-caches nl-list-sockets \ - nl-util-addr + nl-util-addr \ + nl-link-enslave \ + nl-link-release genl_ctrl_list_SOURCES = genl-ctrl-list.c diff --git a/src/nl-link-enslave.c b/src/nl-link-enslave.c new file mode 100644 index 0000000..2b5d47d --- /dev/null +++ b/src/nl-link-enslave.c @@ -0,0 +1,50 @@ +/* + * src/nl-link-enslave.c Enslave a link + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/link.h> +#include <netlink/route/link/bonding.h> + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct rtnl_link *master, *slave; + int err; + + if (argc < 3) { + fprintf(stderr, "Usage: nl-link-enslave master slave\n"); + return 1; + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + if (!(master = rtnl_link_get_by_name(link_cache, argv[1]))) { + fprintf(stderr, "Unknown link: %s\n", argv[1]); + return 1; + } + + if (!(slave = rtnl_link_get_by_name(link_cache, argv[2]))) { + fprintf(stderr, "Unknown link: %s\n", argv[2]); + return 1; + } + + if ((err = rtnl_link_bond_enslave(sock, master, slave)) < 0) { + fprintf(stderr, "Unable to enslave %s to %s: %s\n", + argv[2], argv[1], nl_geterror(err)); + return 1; + } + + return 0; +} + diff --git a/src/nl-link-release.c b/src/nl-link-release.c new file mode 100644 index 0000000..4c9f15a --- /dev/null +++ b/src/nl-link-release.c @@ -0,0 +1,45 @@ +/* + * src/nl-link-release.c release a link + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf <tgraf@suug.ch> + */ + +#include <netlink/cli/utils.h> +#include <netlink/cli/link.h> +#include <netlink/route/link/bonding.h> + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct rtnl_link *slave; + int err; + + if (argc < 2) { + fprintf(stderr, "Usage: nl-link-release slave\n"); + return 1; + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + if (!(slave = rtnl_link_get_by_name(link_cache, argv[1]))) { + fprintf(stderr, "Unknown link: %s\n", argv[1]); + return 1; + } + + if ((err = rtnl_link_bond_release(sock, slave)) < 0) { + fprintf(stderr, "Unable to release slave %s: %s\n", + argv[1], nl_geterror(err)); + return 1; + } + + return 0; +} + |