summaryrefslogtreecommitdiff
path: root/system-linux.c
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2017-02-10 06:30:17 +0100
committerFelix Fietkau <nbd@nbd.name>2017-02-11 21:48:38 +0100
commit6397f5edb977b5963aa8eec1deaa709355bbbc7d (patch)
treee8e8bf3c162794e574e458b06a3b9d6d8c2c0afb /system-linux.c
parent6228d0f21b2dcf20d7b2223c43f8b90b9b51bc4d (diff)
downloadnetifd-6397f5edb977b5963aa8eec1deaa709355bbbc7d.tar.gz
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.c61
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 = {