0009-netifd-device-add-veth-support.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. From: Matthias Schiffer <mschiffer@universe-factory.net>
  2. Date: Fri, 10 Feb 2017 06:33:03 +0100
  3. Subject: netifd: device: add veth support
  4. 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
  5. new file mode 100644
  6. index 0000000000000000000000000000000000000000..9fdc184e98c070d0636fda5c6e5716295b86ecba
  7. --- /dev/null
  8. +++ b/package/network/config/netifd/patches/0001-device-add-veth-support.patch
  9. @@ -0,0 +1,437 @@
  10. +From 006a6d3084cfd034f7d66cde3a0cbf58ab34c5a7 Mon Sep 17 00:00:00 2001
  11. +Message-Id: <006a6d3084cfd034f7d66cde3a0cbf58ab34c5a7.1486704740.git.mschiffer@universe-factory.net>
  12. +From: Matthias Schiffer <mschiffer@universe-factory.net>
  13. +Date: Fri, 10 Feb 2017 04:29:09 +0100
  14. +Subject: [PATCH] device: add veth support
  15. +
  16. +The veth config code mostly handles the primary interface of a veth pair,
  17. +the secondary interface is not explicitly referenced and will be found as
  18. +an unrelated interface after the pair has been created.
  19. +
  20. +This doesn't only allow us to keep the veth code simple (and similar to
  21. +existing device handlers), but will also avoid complicating handling
  22. +unnecessarily in case the secondary interface is moved into another network
  23. +namespace.
  24. +
  25. +Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
  26. +---
  27. + CMakeLists.txt | 2 +-
  28. + system-dummy.c | 10 +++
  29. + system-linux.c | 61 ++++++++++++++
  30. + system.h | 18 +++++
  31. + veth.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  32. + 5 files changed, 337 insertions(+), 1 deletion(-)
  33. + create mode 100644 veth.c
  34. +
  35. +diff --git a/CMakeLists.txt b/CMakeLists.txt
  36. +index 1f35d26..d54b6fa 100644
  37. +--- a/CMakeLists.txt
  38. ++++ b/CMakeLists.txt
  39. +@@ -9,7 +9,7 @@ SET(SOURCES
  40. + main.c utils.c system.c tunnel.c handler.c
  41. + interface.c interface-ip.c interface-event.c
  42. + iprule.c proto.c proto-static.c proto-shell.c
  43. +- config.c device.c bridge.c vlan.c alias.c
  44. ++ config.c device.c bridge.c veth.c vlan.c alias.c
  45. + macvlan.c ubus.c vlandev.c wireless.c)
  46. +
  47. +
  48. +diff --git a/system-dummy.c b/system-dummy.c
  49. +index 9c734ea..2dd27c7 100644
  50. +--- a/system-dummy.c
  51. ++++ b/system-dummy.c
  52. +@@ -275,6 +275,16 @@ int system_macvlan_del(struct device *macvlan)
  53. + return 0;
  54. + }
  55. +
  56. ++int system_veth_add(struct device *veth, struct veth_config *cfg)
  57. ++{
  58. ++ return 0;
  59. ++}
  60. ++
  61. ++int system_veth_del(struct device *veth)
  62. ++{
  63. ++ return 0;
  64. ++}
  65. ++
  66. + int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
  67. + {
  68. + return 0;
  69. +diff --git a/system-linux.c b/system-linux.c
  70. +index 2f15bf1..73e841b 100644
  71. +--- a/system-linux.c
  72. ++++ b/system-linux.c
  73. +@@ -38,6 +38,7 @@
  74. + #include <linux/ip6_tunnel.h>
  75. + #include <linux/ethtool.h>
  76. + #include <linux/fib_rules.h>
  77. ++#include <linux/veth.h>
  78. + #include <linux/version.h>
  79. +
  80. + #ifndef RTN_FAILED_POLICY
  81. +@@ -1132,6 +1133,66 @@ int system_macvlan_del(struct device *macvlan)
  82. + return system_link_del(macvlan->ifname);
  83. + }
  84. +
  85. ++int system_veth_add(struct device *veth, struct veth_config *cfg)
  86. ++{
  87. ++ struct nl_msg *msg;
  88. ++ struct ifinfomsg empty_iim = {};
  89. ++ struct nlattr *linkinfo, *data, *veth_info;
  90. ++ int rv;
  91. ++
  92. ++ msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
  93. ++
  94. ++ if (!msg)
  95. ++ return -1;
  96. ++
  97. ++ nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
  98. ++
  99. ++ if (cfg->flags & VETH_OPT_MACADDR)
  100. ++ nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
  101. ++ nla_put_string(msg, IFLA_IFNAME, veth->ifname);
  102. ++
  103. ++ if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
  104. ++ goto nla_put_failure;
  105. ++
  106. ++ nla_put_string(msg, IFLA_INFO_KIND, "veth");
  107. ++
  108. ++ if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
  109. ++ goto nla_put_failure;
  110. ++
  111. ++ if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
  112. ++ goto nla_put_failure;
  113. ++
  114. ++ nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
  115. ++
  116. ++ if (cfg->flags & VETH_OPT_PEER_NAME)
  117. ++ nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
  118. ++ if (cfg->flags & VETH_OPT_PEER_MACADDR)
  119. ++ nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
  120. ++
  121. ++ nla_nest_end(msg, veth_info);
  122. ++ nla_nest_end(msg, data);
  123. ++ nla_nest_end(msg, linkinfo);
  124. ++
  125. ++ rv = system_rtnl_call(msg);
  126. ++ if (rv) {
  127. ++ if (cfg->flags & VETH_OPT_PEER_NAME)
  128. ++ D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
  129. ++ else
  130. ++ D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
  131. ++ }
  132. ++
  133. ++ return rv;
  134. ++
  135. ++nla_put_failure:
  136. ++ nlmsg_free(msg);
  137. ++ return -ENOMEM;
  138. ++}
  139. ++
  140. ++int system_veth_del(struct device *veth)
  141. ++{
  142. ++ return system_link_del(veth->ifname);
  143. ++}
  144. ++
  145. + static int system_vlan(struct device *dev, int id)
  146. + {
  147. + struct vlan_ioctl_args ifr = {
  148. +diff --git a/system.h b/system.h
  149. +index d5cb4e3..f4dd02b 100644
  150. +--- a/system.h
  151. ++++ b/system.h
  152. +@@ -14,6 +14,7 @@
  153. + #ifndef __NETIFD_SYSTEM_H
  154. + #define __NETIFD_SYSTEM_H
  155. +
  156. ++#include <net/if.h>
  157. + #include <sys/time.h>
  158. + #include <sys/socket.h>
  159. + #include <arpa/inet.h>
  160. +@@ -82,6 +83,20 @@ struct macvlan_config {
  161. + unsigned char macaddr[6];
  162. + };
  163. +
  164. ++enum veth_opt {
  165. ++ VETH_OPT_MACADDR = (1 << 0),
  166. ++ VETH_OPT_PEER_NAME = (1 << 1),
  167. ++ VETH_OPT_PEER_MACADDR = (1 << 2),
  168. ++};
  169. ++
  170. ++struct veth_config {
  171. ++ enum veth_opt flags;
  172. ++
  173. ++ unsigned char macaddr[6];
  174. ++ char peer_name[IFNAMSIZ];
  175. ++ unsigned char peer_macaddr[6];
  176. ++};
  177. ++
  178. + enum vlan_proto {
  179. + VLAN_PROTO_8021Q = 0x8100,
  180. + VLAN_PROTO_8021AD = 0x88A8
  181. +@@ -118,6 +133,9 @@ int system_bridge_delif(struct device *bridge, struct device *dev);
  182. + int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg);
  183. + int system_macvlan_del(struct device *macvlan);
  184. +
  185. ++int system_veth_add(struct device *veth, struct veth_config *cfg);
  186. ++int system_veth_del(struct device *veth);
  187. ++
  188. + int system_vlan_add(struct device *dev, int id);
  189. + int system_vlan_del(struct device *dev);
  190. +
  191. +diff --git a/veth.c b/veth.c
  192. +new file mode 100644
  193. +index 0000000..e109f27
  194. +--- /dev/null
  195. ++++ b/veth.c
  196. +@@ -0,0 +1,247 @@
  197. ++/*
  198. ++ * netifd - network interface daemon
  199. ++ * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
  200. ++ * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
  201. ++ * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
  202. ++ *
  203. ++ * This program is free software; you can redistribute it and/or modify
  204. ++ * it under the terms of the GNU General Public License version 2
  205. ++ * as published by the Free Software Foundation
  206. ++ *
  207. ++ * This program is distributed in the hope that it will be useful,
  208. ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  209. ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  210. ++ * GNU General Public License for more details.
  211. ++ */
  212. ++#include <string.h>
  213. ++#include <stdlib.h>
  214. ++#include <stdio.h>
  215. ++#include <assert.h>
  216. ++#include <errno.h>
  217. ++#include <net/ethernet.h>
  218. ++
  219. ++#ifdef linux
  220. ++#include <netinet/ether.h>
  221. ++#endif
  222. ++
  223. ++#include "netifd.h"
  224. ++#include "device.h"
  225. ++#include "interface.h"
  226. ++#include "system.h"
  227. ++
  228. ++enum {
  229. ++ VETH_ATTR_MACADDR,
  230. ++ VETH_ATTR_PEER_NAME,
  231. ++ VETH_ATTR_PEER_MACADDR,
  232. ++ __VETH_ATTR_MAX
  233. ++};
  234. ++
  235. ++static const struct blobmsg_policy veth_attrs[__VETH_ATTR_MAX] = {
  236. ++ [VETH_ATTR_MACADDR] = { "macaddr", BLOBMSG_TYPE_STRING },
  237. ++ [VETH_ATTR_PEER_NAME] = { "peer_name", BLOBMSG_TYPE_STRING },
  238. ++ [VETH_ATTR_PEER_MACADDR] = { "peer_macaddr", BLOBMSG_TYPE_STRING },
  239. ++};
  240. ++
  241. ++static const struct uci_blob_param_list veth_attr_list = {
  242. ++ .n_params = __VETH_ATTR_MAX,
  243. ++ .params = veth_attrs,
  244. ++
  245. ++ .n_next = 1,
  246. ++ .next = { &device_attr_list },
  247. ++};
  248. ++
  249. ++struct veth {
  250. ++ struct device dev;
  251. ++
  252. ++ device_state_cb set_state;
  253. ++
  254. ++ struct blob_attr *config_data;
  255. ++ struct veth_config config;
  256. ++};
  257. ++
  258. ++static int
  259. ++veth_set_down(struct veth *veth)
  260. ++{
  261. ++ veth->set_state(&veth->dev, false);
  262. ++ system_veth_del(&veth->dev);
  263. ++
  264. ++ return 0;
  265. ++}
  266. ++
  267. ++static int
  268. ++veth_set_up(struct veth *veth)
  269. ++{
  270. ++ int ret;
  271. ++
  272. ++ ret = system_veth_add(&veth->dev, &veth->config);
  273. ++ if (ret < 0)
  274. ++ return ret;
  275. ++
  276. ++ ret = veth->set_state(&veth->dev, true);
  277. ++ if (ret)
  278. ++ goto delete;
  279. ++
  280. ++ return 0;
  281. ++
  282. ++delete:
  283. ++ system_veth_del(&veth->dev);
  284. ++ return ret;
  285. ++}
  286. ++
  287. ++static int
  288. ++veth_set_state(struct device *dev, bool up)
  289. ++{
  290. ++ struct veth *veth;
  291. ++
  292. ++ D(SYSTEM, "veth_set_state(%s, %u)\n", dev->ifname, up);
  293. ++
  294. ++ veth = container_of(dev, struct veth, dev);
  295. ++ if (up)
  296. ++ return veth_set_up(veth);
  297. ++ else
  298. ++ return veth_set_down(veth);
  299. ++}
  300. ++
  301. ++static void
  302. ++veth_free(struct device *dev)
  303. ++{
  304. ++ struct veth *veth;
  305. ++
  306. ++ veth = container_of(dev, struct veth, dev);
  307. ++ free(veth->config_data);
  308. ++ free(veth);
  309. ++}
  310. ++
  311. ++static void
  312. ++veth_dump_info(struct device *dev, struct blob_buf *b)
  313. ++{
  314. ++ struct veth *veth;
  315. ++
  316. ++ veth = container_of(dev, struct veth, dev);
  317. ++ if (veth->config.flags & VETH_OPT_PEER_NAME)
  318. ++ blobmsg_add_string(b, "peer", veth->config.peer_name);
  319. ++ system_if_dump_info(dev, b);
  320. ++}
  321. ++
  322. ++static void
  323. ++veth_config_init(struct device *dev)
  324. ++{
  325. ++ device_set_present(dev, true);
  326. ++}
  327. ++
  328. ++static void
  329. ++veth_apply_settings(struct veth *veth, struct blob_attr **tb)
  330. ++{
  331. ++ struct veth_config *cfg = &veth->config;
  332. ++ struct blob_attr *cur;
  333. ++ struct ether_addr *ea;
  334. ++
  335. ++ cfg->flags = 0;
  336. ++
  337. ++ if ((cur = tb[VETH_ATTR_MACADDR]))
  338. ++ {
  339. ++ ea = ether_aton(blobmsg_data(cur));
  340. ++ if (ea) {
  341. ++ memcpy(cfg->macaddr, ea, 6);
  342. ++ cfg->flags |= VETH_OPT_MACADDR;
  343. ++ }
  344. ++ }
  345. ++
  346. ++ if ((cur = tb[VETH_ATTR_PEER_NAME]))
  347. ++ {
  348. ++ strncpy(cfg->peer_name, blobmsg_get_string(cur), sizeof(cfg->peer_name)-1);
  349. ++ cfg->flags |= VETH_OPT_PEER_NAME;
  350. ++ }
  351. ++
  352. ++ if ((cur = tb[VETH_ATTR_PEER_MACADDR]))
  353. ++ {
  354. ++ ea = ether_aton(blobmsg_data(cur));
  355. ++ if (ea) {
  356. ++ memcpy(cfg->peer_macaddr, ea, 6);
  357. ++ cfg->flags |= VETH_OPT_PEER_MACADDR;
  358. ++ }
  359. ++ }
  360. ++}
  361. ++
  362. ++static enum dev_change_type
  363. ++veth_reload(struct device *dev, struct blob_attr *attr)
  364. ++{
  365. ++ struct blob_attr *tb_dev[__DEV_ATTR_MAX];
  366. ++ struct blob_attr *tb_mv[__VETH_ATTR_MAX];
  367. ++ enum dev_change_type ret = DEV_CONFIG_APPLIED;
  368. ++ struct veth *veth;
  369. ++
  370. ++ veth = container_of(dev, struct veth, dev);
  371. ++ attr = blob_memdup(attr);
  372. ++
  373. ++ blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev,
  374. ++ blob_data(attr), blob_len(attr));
  375. ++ blobmsg_parse(veth_attrs, __VETH_ATTR_MAX, tb_mv,
  376. ++ blob_data(attr), blob_len(attr));
  377. ++
  378. ++ device_init_settings(dev, tb_dev);
  379. ++ veth_apply_settings(veth, tb_mv);
  380. ++
  381. ++ if (veth->config_data) {
  382. ++ struct blob_attr *otb_dev[__DEV_ATTR_MAX];
  383. ++ struct blob_attr *otb_mv[__VETH_ATTR_MAX];
  384. ++
  385. ++ blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, otb_dev,
  386. ++ blob_data(veth->config_data), blob_len(veth->config_data));
  387. ++
  388. ++ if (uci_blob_diff(tb_dev, otb_dev, &device_attr_list, NULL))
  389. ++ ret = DEV_CONFIG_RESTART;
  390. ++
  391. ++ blobmsg_parse(veth_attrs, __VETH_ATTR_MAX, otb_mv,
  392. ++ blob_data(veth->config_data), blob_len(veth->config_data));
  393. ++
  394. ++ if (uci_blob_diff(tb_mv, otb_mv, &veth_attr_list, NULL))
  395. ++ ret = DEV_CONFIG_RESTART;
  396. ++
  397. ++ veth_config_init(dev);
  398. ++ }
  399. ++
  400. ++ free(veth->config_data);
  401. ++ veth->config_data = attr;
  402. ++ return ret;
  403. ++}
  404. ++
  405. ++static struct device *
  406. ++veth_create(const char *name, struct device_type *devtype,
  407. ++ struct blob_attr *attr)
  408. ++{
  409. ++ struct veth *veth;
  410. ++ struct device *dev = NULL;
  411. ++
  412. ++ veth = calloc(1, sizeof(*veth));
  413. ++ if (!veth)
  414. ++ return NULL;
  415. ++
  416. ++ dev = &veth->dev;
  417. ++ device_init(dev, devtype, name);
  418. ++ dev->config_pending = true;
  419. ++
  420. ++ veth->set_state = dev->set_state;
  421. ++ dev->set_state = veth_set_state;
  422. ++
  423. ++ dev->hotplug_ops = NULL;
  424. ++
  425. ++ veth_reload(dev, attr);
  426. ++
  427. ++ return dev;
  428. ++}
  429. ++
  430. ++static struct device_type veth_device_type = {
  431. ++ .name = "veth",
  432. ++ .config_params = &veth_attr_list,
  433. ++ .create = veth_create,
  434. ++ .config_init = veth_config_init,
  435. ++ .reload = veth_reload,
  436. ++ .free = veth_free,
  437. ++ .dump_info = veth_dump_info,
  438. ++};
  439. ++
  440. ++static void __init veth_device_type_init(void)
  441. ++{
  442. ++ device_type_add(&veth_device_type);
  443. ++}
  444. +--
  445. +2.11.1
  446. +