summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/netlink/route/link/bonding.h37
-rw-r--r--lib/route/link/bonding.c176
-rw-r--r--src/Makefile.am4
-rw-r--r--src/nl-link-enslave.c50
-rw-r--r--src/nl-link-release.c45
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;
+}
+