This almost copy-paste from macvlan device with corresponding changes.
Signed-off-by: Alexey Smirnov
---
CMakeLists.txt | 2 +-
ipvlan.c | 263 +
system-dummy.c | 10 ++
system-linux.c | 76 ++
system.h | 8 ++
5 files changed, 358 insertions(+), 1 deletion(-)
create mode 100644 ipvlan.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3bf411..0af7af5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,7 +20,7 @@ SET(SOURCES
interface.c interface-ip.c interface-event.c
iprule.c proto.c proto-static.c proto-shell.c
config.c device.c bridge.c veth.c vlan.c alias.c
- macvlan.c ubus.c vlandev.c wireless.c
+ ipvlan.c macvlan.c ubus.c vlandev.c wireless.c
extdev.c bonding.c)
diff --git a/ipvlan.c b/ipvlan.c
new file mode 100644
index 000..af597cb
--- /dev/null
+++ b/ipvlan.c
@@ -0,0 +1,263 @@
+/*
+ * netifd - network interface daemon
+ * Copyright (C) 2012 Felix Fietkau
+ * Copyright (C) 2013 Jo-Philipp Wich
+ *
+ * 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 "netifd.h"
+#include "device.h"
+#include "interface.h"
+#include "system.h"
+
+enum {
+ IPVLAN_ATTR_IFNAME,
+ IPVLAN_ATTR_MODE,
+ IPVLAN_ATTR_FLAG,
+ __IPVLAN_ATTR_MAX
+};
+
+static const struct blobmsg_policy ipvlan_attrs[__IPVLAN_ATTR_MAX] = {
+ [IPVLAN_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_STRING },
+ [IPVLAN_ATTR_MODE] = { "mode", BLOBMSG_TYPE_STRING },
+ [IPVLAN_ATTR_FLAG] = { "flag", BLOBMSG_TYPE_STRING },
+};
+
+static const struct uci_blob_param_list ipvlan_attr_list = {
+ .n_params = __IPVLAN_ATTR_MAX,
+ .params = ipvlan_attrs,
+
+ .n_next = 1,
+ .next = { &device_attr_list },
+};
+
+struct ipvlan_device {
+ struct device dev;
+ struct device_user parent;
+
+ device_state_cb set_state;
+
+ struct blob_attr *config_data;
+ struct blob_attr *ifname;
+ struct ipvlan_config config;
+};
+
+static void
+ipvlan_base_cb(struct device_user *dev, enum device_event ev)
+{
+ struct ipvlan_device *mvdev = container_of(dev, struct ipvlan_device,
parent);
+
+ switch (ev) {
+ case DEV_EVENT_ADD:
+ device_set_present(&mvdev->dev, true);
+ break;
+ case DEV_EVENT_REMOVE:
+ device_set_present(&mvdev->dev, false);
+ break;
+ default:
+ return;
+ }
+}
+
+static int
+ipvlan_set_down(struct ipvlan_device *mvdev)
+{
+ mvdev->set_state(&mvdev->dev, false);
+ system_ipvlan_del(&mvdev->dev);
+ device_release(&mvdev->parent);
+
+ return 0;
+}
+
+static int
+ipvlan_set_up(struct ipvlan_device *mvdev)
+{
+ int ret;
+
+ ret = device_claim(&mvdev->parent);
+ if (ret < 0)
+ return ret;
+
+ ret = system_ipvlan_add(&mvdev->dev, mvdev->parent.dev, &mvdev->config);
+ if (ret < 0)
+ goto release;
+
+ ret = mvdev->set_state(&mvdev->dev, true);
+ if (ret)
+ goto delete;
+
+ return 0;
+
+delete:
+ system_ipvlan_del(&mvdev->dev);
+release:
+ device_release(&mvdev->parent);
+ return ret;
+}
+
+static int
+ipvlan_set_state(struct device *dev, bool up)
+{
+ struct ipvlan_device *mvdev;
+
+ D(SYSTEM, "ipvlan_set_state(%s, %u)\n", dev->ifname, up);
+
+ mvdev = container_of(dev, struct ipvlan_device, dev);
+ if (up)
+ return ipvlan_set_up(mvdev);
+ else
+ return ipvlan_set_down(mvdev);
+}
+
+static void
+ipvlan_free(struct device *dev)
+{
+ struct ipvlan_device *mvdev;
+
+ mvdev = container_of(dev, struct ipvlan_device, dev);
+ device_remove_user(&mvdev->parent);
+ free(mvdev->config_data);
+ free(mvdev);
+}
+
+static void
+ipvlan_dump_info(struct device *dev, struct blob_buf *b)
+{
+ struct ipvlan_device *mvdev;
+
+ mvdev = container_of(dev, struct ipvlan_device, dev);
+ blobmsg_add_string(b, "parent", mvdev->parent.dev->ifname);
+ system_if_dump_info(dev, b);
+}
+
+static void
+ipvlan_config_init(struct device *dev)
+{
+ struct ipvlan_device *mvdev;
+ struct device *basedev = NULL;
+
+ mvdev = container_of(dev, struct ipvlan_d