diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2017-02-10 06:30:17 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2017-02-11 21:48:38 +0100 |
commit | 6397f5edb977b5963aa8eec1deaa709355bbbc7d (patch) | |
tree | e8e8bf3c162794e574e458b06a3b9d6d8c2c0afb /system-linux.c | |
parent | 6228d0f21b2dcf20d7b2223c43f8b90b9b51bc4d (diff) |
device: add veth support
The veth config code mostly handles the primary interface of a veth pair,
the secondary interface is not explicitly referenced and will be found as
an unrelated interface after the pair has been created.
This doesn't only allow us to keep the veth code simple (and similar to
existing device handlers), but will also avoid complicating handling
unnecessarily in case the secondary interface is moved into another network
namespace.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Diffstat (limited to 'system-linux.c')
-rw-r--r-- | system-linux.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/system-linux.c b/system-linux.c index 8a1173c..e0cb5bc 100644 --- a/system-linux.c +++ b/system-linux.c @@ -38,6 +38,7 @@ #include <linux/ip6_tunnel.h> #include <linux/ethtool.h> #include <linux/fib_rules.h> +#include <linux/veth.h> #include <linux/version.h> #ifndef RTN_FAILED_POLICY @@ -1131,6 +1132,66 @@ int system_macvlan_del(struct device *macvlan) return system_link_del(macvlan->ifname); } +int system_veth_add(struct device *veth, struct veth_config *cfg) +{ + struct nl_msg *msg; + struct ifinfomsg empty_iim = {}; + struct nlattr *linkinfo, *data, *veth_info; + int rv; + + msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); + + if (!msg) + return -1; + + nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0); + + if (cfg->flags & VETH_OPT_MACADDR) + nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr); + nla_put_string(msg, IFLA_IFNAME, veth->ifname); + + if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) + goto nla_put_failure; + + nla_put_string(msg, IFLA_INFO_KIND, "veth"); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER))) + goto nla_put_failure; + + nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0); + + if (cfg->flags & VETH_OPT_PEER_NAME) + nla_put_string(msg, IFLA_IFNAME, cfg->peer_name); + if (cfg->flags & VETH_OPT_PEER_MACADDR) + nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr); + + nla_nest_end(msg, veth_info); + nla_nest_end(msg, data); + nla_nest_end(msg, linkinfo); + + rv = system_rtnl_call(msg); + if (rv) { + if (cfg->flags & VETH_OPT_PEER_NAME) + D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv); + else + D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv); + } + + return rv; + +nla_put_failure: + nlmsg_free(msg); + return -ENOMEM; +} + +int system_veth_del(struct device *veth) +{ + return system_link_del(veth->ifname); +} + static int system_vlan(struct device *dev, int id) { struct vlan_ioctl_args ifr = { |