From 249ff3407981a00cd032f5c9b4cf9859f36447ff Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 10 Feb 2017 06:34:46 +0100 Subject: [PATCH] netifd: device: add veth support --- .../0011-netifd-device-add-veth-support.patch | 447 ++++++++++++++++++ 1 file changed, 447 insertions(+) create mode 100644 patches/lede/0011-netifd-device-add-veth-support.patch diff --git a/patches/lede/0011-netifd-device-add-veth-support.patch b/patches/lede/0011-netifd-device-add-veth-support.patch new file mode 100644 index 00000000..2c475060 --- /dev/null +++ b/patches/lede/0011-netifd-device-add-veth-support.patch @@ -0,0 +1,447 @@ +From: Matthias Schiffer +Date: Fri, 10 Feb 2017 06:33:03 +0100 +Subject: netifd: device: add veth support + +diff --git a/package/network/config/netifd/patches/0001-device-add-veth-support.patch b/package/network/config/netifd/patches/0001-device-add-veth-support.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..9fdc184e98c070d0636fda5c6e5716295b86ecba +--- /dev/null ++++ b/package/network/config/netifd/patches/0001-device-add-veth-support.patch +@@ -0,0 +1,437 @@ ++From 006a6d3084cfd034f7d66cde3a0cbf58ab34c5a7 Mon Sep 17 00:00:00 2001 ++Message-Id: <006a6d3084cfd034f7d66cde3a0cbf58ab34c5a7.1486704740.git.mschiffer@universe-factory.net> ++From: Matthias Schiffer ++Date: Fri, 10 Feb 2017 04:29:09 +0100 ++Subject: [PATCH] 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 ++--- ++ CMakeLists.txt | 2 +- ++ system-dummy.c | 10 +++ ++ system-linux.c | 61 ++++++++++++++ ++ system.h | 18 +++++ ++ veth.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ 5 files changed, 337 insertions(+), 1 deletion(-) ++ create mode 100644 veth.c ++ ++diff --git a/CMakeLists.txt b/CMakeLists.txt ++index 1f35d26..d54b6fa 100644 ++--- a/CMakeLists.txt +++++ b/CMakeLists.txt ++@@ -9,7 +9,7 @@ SET(SOURCES ++ main.c utils.c system.c tunnel.c handler.c ++ interface.c interface-ip.c interface-event.c ++ iprule.c proto.c proto-static.c proto-shell.c ++- config.c device.c bridge.c vlan.c alias.c +++ config.c device.c bridge.c veth.c vlan.c alias.c ++ macvlan.c ubus.c vlandev.c wireless.c) ++ ++ ++diff --git a/system-dummy.c b/system-dummy.c ++index 9c734ea..2dd27c7 100644 ++--- a/system-dummy.c +++++ b/system-dummy.c ++@@ -275,6 +275,16 @@ int system_macvlan_del(struct device *macvlan) ++ return 0; ++ } ++ +++int system_veth_add(struct device *veth, struct veth_config *cfg) +++{ +++ return 0; +++} +++ +++int system_veth_del(struct device *veth) +++{ +++ return 0; +++} +++ ++ int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg) ++ { ++ return 0; ++diff --git a/system-linux.c b/system-linux.c ++index 2f15bf1..73e841b 100644 ++--- a/system-linux.c +++++ b/system-linux.c ++@@ -38,6 +38,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #ifndef RTN_FAILED_POLICY ++@@ -1132,6 +1133,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 = { ++diff --git a/system.h b/system.h ++index d5cb4e3..f4dd02b 100644 ++--- a/system.h +++++ b/system.h ++@@ -14,6 +14,7 @@ ++ #ifndef __NETIFD_SYSTEM_H ++ #define __NETIFD_SYSTEM_H ++ +++#include ++ #include ++ #include ++ #include ++@@ -82,6 +83,20 @@ struct macvlan_config { ++ unsigned char macaddr[6]; ++ }; ++ +++enum veth_opt { +++ VETH_OPT_MACADDR = (1 << 0), +++ VETH_OPT_PEER_NAME = (1 << 1), +++ VETH_OPT_PEER_MACADDR = (1 << 2), +++}; +++ +++struct veth_config { +++ enum veth_opt flags; +++ +++ unsigned char macaddr[6]; +++ char peer_name[IFNAMSIZ]; +++ unsigned char peer_macaddr[6]; +++}; +++ ++ enum vlan_proto { ++ VLAN_PROTO_8021Q = 0x8100, ++ VLAN_PROTO_8021AD = 0x88A8 ++@@ -118,6 +133,9 @@ int system_bridge_delif(struct device *bridge, struct device *dev); ++ int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg); ++ int system_macvlan_del(struct device *macvlan); ++ +++int system_veth_add(struct device *veth, struct veth_config *cfg); +++int system_veth_del(struct device *veth); +++ ++ int system_vlan_add(struct device *dev, int id); ++ int system_vlan_del(struct device *dev); ++ ++diff --git a/veth.c b/veth.c ++new file mode 100644 ++index 0000000..e109f27 ++--- /dev/null +++++ b/veth.c ++@@ -0,0 +1,247 @@ +++/* +++ * netifd - network interface daemon +++ * Copyright (C) 2012 Felix Fietkau +++ * Copyright (C) 2013 Jo-Philipp Wich +++ * Copyright (C) 2017 Matthias Schiffer +++ * +++ * This program is free software; you can redistribute it and/or modify +++ * it under the terms of the GNU General Public License version 2 +++ * as published by the Free Software Foundation +++ * +++ * This program is distributed in the hope that it will be useful, +++ * but WITHOUT ANY WARRANTY; without even the implied warranty of +++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +++ * GNU General Public License for more details. +++ */ +++#include +++#include +++#include +++#include +++#include +++#include +++ +++#ifdef linux +++#include +++#endif +++ +++#include "netifd.h" +++#include "device.h" +++#include "interface.h" +++#include "system.h" +++ +++enum { +++ VETH_ATTR_MACADDR, +++ VETH_ATTR_PEER_NAME, +++ VETH_ATTR_PEER_MACADDR, +++ __VETH_ATTR_MAX +++}; +++ +++static const struct blobmsg_policy veth_attrs[__VETH_ATTR_MAX] = { +++ [VETH_ATTR_MACADDR] = { "macaddr", BLOBMSG_TYPE_STRING }, +++ [VETH_ATTR_PEER_NAME] = { "peer_name", BLOBMSG_TYPE_STRING }, +++ [VETH_ATTR_PEER_MACADDR] = { "peer_macaddr", BLOBMSG_TYPE_STRING }, +++}; +++ +++static const struct uci_blob_param_list veth_attr_list = { +++ .n_params = __VETH_ATTR_MAX, +++ .params = veth_attrs, +++ +++ .n_next = 1, +++ .next = { &device_attr_list }, +++}; +++ +++struct veth { +++ struct device dev; +++ +++ device_state_cb set_state; +++ +++ struct blob_attr *config_data; +++ struct veth_config config; +++}; +++ +++static int +++veth_set_down(struct veth *veth) +++{ +++ veth->set_state(&veth->dev, false); +++ system_veth_del(&veth->dev); +++ +++ return 0; +++} +++ +++static int +++veth_set_up(struct veth *veth) +++{ +++ int ret; +++ +++ ret = system_veth_add(&veth->dev, &veth->config); +++ if (ret < 0) +++ return ret; +++ +++ ret = veth->set_state(&veth->dev, true); +++ if (ret) +++ goto delete; +++ +++ return 0; +++ +++delete: +++ system_veth_del(&veth->dev); +++ return ret; +++} +++ +++static int +++veth_set_state(struct device *dev, bool up) +++{ +++ struct veth *veth; +++ +++ D(SYSTEM, "veth_set_state(%s, %u)\n", dev->ifname, up); +++ +++ veth = container_of(dev, struct veth, dev); +++ if (up) +++ return veth_set_up(veth); +++ else +++ return veth_set_down(veth); +++} +++ +++static void +++veth_free(struct device *dev) +++{ +++ struct veth *veth; +++ +++ veth = container_of(dev, struct veth, dev); +++ free(veth->config_data); +++ free(veth); +++} +++ +++static void +++veth_dump_info(struct device *dev, struct blob_buf *b) +++{ +++ struct veth *veth; +++ +++ veth = container_of(dev, struct veth, dev); +++ if (veth->config.flags & VETH_OPT_PEER_NAME) +++ blobmsg_add_string(b, "peer", veth->config.peer_name); +++ system_if_dump_info(dev, b); +++} +++ +++static void +++veth_config_init(struct device *dev) +++{ +++ device_set_present(dev, true); +++} +++ +++static void +++veth_apply_settings(struct veth *veth, struct blob_attr **tb) +++{ +++ struct veth_config *cfg = &veth->config; +++ struct blob_attr *cur; +++ struct ether_addr *ea; +++ +++ cfg->flags = 0; +++ +++ if ((cur = tb[VETH_ATTR_MACADDR])) +++ { +++ ea = ether_aton(blobmsg_data(cur)); +++ if (ea) { +++ memcpy(cfg->macaddr, ea, 6); +++ cfg->flags |= VETH_OPT_MACADDR; +++ } +++ } +++ +++ if ((cur = tb[VETH_ATTR_PEER_NAME])) +++ { +++ strncpy(cfg->peer_name, blobmsg_get_string(cur), sizeof(cfg->peer_name)-1); +++ cfg->flags |= VETH_OPT_PEER_NAME; +++ } +++ +++ if ((cur = tb[VETH_ATTR_PEER_MACADDR])) +++ { +++ ea = ether_aton(blobmsg_data(cur)); +++ if (ea) { +++ memcpy(cfg->peer_macaddr, ea, 6); +++ cfg->flags |= VETH_OPT_PEER_MACADDR; +++ } +++ } +++} +++ +++static enum dev_change_type +++veth_reload(struct device *dev, struct blob_attr *attr) +++{ +++ struct blob_attr *tb_dev[__DEV_ATTR_MAX]; +++ struct blob_attr *tb_mv[__VETH_ATTR_MAX]; +++ enum dev_change_type ret = DEV_CONFIG_APPLIED; +++ struct veth *veth; +++ +++ veth = container_of(dev, struct veth, dev); +++ attr = blob_memdup(attr); +++ +++ blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev, +++ blob_data(attr), blob_len(attr)); +++ blobmsg_parse(veth_attrs, __VETH_ATTR_MAX, tb_mv, +++ blob_data(attr), blob_len(attr)); +++ +++ device_init_settings(dev, tb_dev); +++ veth_apply_settings(veth, tb_mv); +++ +++ if (veth->config_data) { +++ struct blob_attr *otb_dev[__DEV_ATTR_MAX]; +++ struct blob_attr *otb_mv[__VETH_ATTR_MAX]; +++ +++ blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, otb_dev, +++ blob_data(veth->config_data), blob_len(veth->config_data)); +++ +++ if (uci_blob_diff(tb_dev, otb_dev, &device_attr_list, NULL)) +++ ret = DEV_CONFIG_RESTART; +++ +++ blobmsg_parse(veth_attrs, __VETH_ATTR_MAX, otb_mv, +++ blob_data(veth->config_data), blob_len(veth->config_data)); +++ +++ if (uci_blob_diff(tb_mv, otb_mv, &veth_attr_list, NULL)) +++ ret = DEV_CONFIG_RESTART; +++ +++ veth_config_init(dev); +++ } +++ +++ free(veth->config_data); +++ veth->config_data = attr; +++ return ret; +++} +++ +++static struct device * +++veth_create(const char *name, struct device_type *devtype, +++ struct blob_attr *attr) +++{ +++ struct veth *veth; +++ struct device *dev = NULL; +++ +++ veth = calloc(1, sizeof(*veth)); +++ if (!veth) +++ return NULL; +++ +++ dev = &veth->dev; +++ device_init(dev, devtype, name); +++ dev->config_pending = true; +++ +++ veth->set_state = dev->set_state; +++ dev->set_state = veth_set_state; +++ +++ dev->hotplug_ops = NULL; +++ +++ veth_reload(dev, attr); +++ +++ return dev; +++} +++ +++static struct device_type veth_device_type = { +++ .name = "veth", +++ .config_params = &veth_attr_list, +++ .create = veth_create, +++ .config_init = veth_config_init, +++ .reload = veth_reload, +++ .free = veth_free, +++ .dump_info = veth_dump_info, +++}; +++ +++static void __init veth_device_type_init(void) +++{ +++ device_type_add(&veth_device_type); +++} ++-- ++2.11.1 ++