[lxc-devel] [lxc/master] network: Adds IPVLAN support

tomponline on Github lxc-bot at linuxcontainers.org
Fri Apr 26 10:28:12 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 570 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190426/d4d8b0b5/attachment-0001.bin>
-------------- next part --------------
From 9f658c8d7069999f50c75507b34fcf7aaee5daa2 Mon Sep 17 00:00:00 2001
From: tomponline <thomas.parrott at canonical.com>
Date: Fri, 26 Apr 2019 11:26:45 +0100
Subject: [PATCH] network: Adds IPVLAN support

Example usage:

	lxc.net[i].type=ipvlan
	lxc.net[i].ipvlan.mode=[l3|l3s|l2] (defaults to l3)
	lxc.net[i].ipvlan.flags=[bridge|private|vepa] (defaults to bridge)
	lxc.net[i].link=eth0
	lxc.net[i].flags=up

Signed-off-by: tomponline <thomas.parrott at canonical.com>
---
 src/lxc/confile.c       | 146 ++++++++++++++++++++++++++++++++++++++++
 src/lxc/confile_utils.c |  88 ++++++++++++++++++++++++
 src/lxc/confile_utils.h |   4 ++
 src/lxc/macro.h         |  24 +++++++
 src/lxc/network.c       |  15 +++++
 src/lxc/network.h       |   7 ++
 6 files changed, 284 insertions(+)

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index da5e45ce3c..40eb9fcbf9 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -130,6 +130,8 @@ lxc_config_define(net_ipv6_address);
 lxc_config_define(net_ipv6_gateway);
 lxc_config_define(net_link);
 lxc_config_define(net_macvlan_mode);
+lxc_config_define(net_ipvlan_mode);
+lxc_config_define(net_ipvlan_flags);
 lxc_config_define(net_mtu);
 lxc_config_define(net_name);
 lxc_config_define(net_nic);
@@ -219,6 +221,8 @@ static struct lxc_config_t config_jump_table[] = {
 	{ "lxc.net.ipv6.gateway",          set_config_net_ipv6_gateway,            get_config_net_ipv6_gateway,            clr_config_net_ipv6_gateway,          },
 	{ "lxc.net.link",                  set_config_net_link,                    get_config_net_link,                    clr_config_net_link,                  },
 	{ "lxc.net.macvlan.mode",          set_config_net_macvlan_mode,            get_config_net_macvlan_mode,            clr_config_net_macvlan_mode,          },
+	{ "lxc.net.ipvlan.mode",           set_config_net_ipvlan_mode,             get_config_net_ipvlan_mode,             clr_config_net_ipvlan_mode,           },
+	{ "lxc.net.ipvlan.flags",          set_config_net_ipvlan_flags,            get_config_net_ipvlan_flags,            clr_config_net_ipvlan_flags,          },
 	{ "lxc.net.mtu",                   set_config_net_mtu,                     get_config_net_mtu,                     clr_config_net_mtu,                   },
 	{ "lxc.net.name",                  set_config_net_name,                    get_config_net_name,                    clr_config_net_name,                  },
 	{ "lxc.net.script.down",           set_config_net_script_down,             get_config_net_script_down,             clr_config_net_script_down,           },
@@ -432,6 +436,34 @@ static int set_config_net_macvlan_mode(const char *key, const char *value,
 	return lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode, value);
 }
 
+static int set_config_net_ipvlan_mode(const char *key, const char *value,
+				       struct lxc_conf *lxc_conf, void *data)
+{
+	struct lxc_netdev *netdev = data;
+
+	if (lxc_config_value_empty(value))
+		return clr_config_net_ipvlan_mode(key, lxc_conf, data);
+
+	if (!netdev)
+		return -1;
+
+	return lxc_ipvlan_mode_to_flag(&netdev->priv.ipvlan_attr.mode, value);
+}
+
+static int set_config_net_ipvlan_flags(const char *key, const char *value,
+				       struct lxc_conf *lxc_conf, void *data)
+{
+	struct lxc_netdev *netdev = data;
+
+	if (lxc_config_value_empty(value))
+		return clr_config_net_ipvlan_flags(key, lxc_conf, data);
+
+	if (!netdev)
+		return -1;
+
+	return lxc_ipvlan_flags_to_flag(&netdev->priv.ipvlan_attr.mode, value);
+}
+
 static int set_config_net_hwaddr(const char *key, const char *value,
 				 struct lxc_conf *lxc_conf, void *data)
 {
@@ -4784,6 +4816,38 @@ static int clr_config_net_macvlan_mode(const char *key,
 	return 0;
 }
 
+static int clr_config_net_ipvlan_mode(const char *key,
+				       struct lxc_conf *lxc_conf, void *data)
+{
+	struct lxc_netdev *netdev = data;
+
+	if (!netdev)
+		return -1;
+
+	if (netdev->type != LXC_NET_IPVLAN)
+		return 0;
+
+	netdev->priv.ipvlan_attr.mode = -1;
+
+	return 0;
+}
+
+static int clr_config_net_ipvlan_flags(const char *key,
+				       struct lxc_conf *lxc_conf, void *data)
+{
+	struct lxc_netdev *netdev = data;
+
+	if (!netdev)
+		return -1;
+
+	if (netdev->type != LXC_NET_IPVLAN)
+		return 0;
+
+	netdev->priv.ipvlan_attr.flags = -1;
+
+	return 0;
+}
+
 static int clr_config_net_veth_pair(const char *key, struct lxc_conf *lxc_conf,
 				    void *data)
 {
@@ -5085,6 +5149,84 @@ static int get_config_net_macvlan_mode(const char *key, char *retv, int inlen,
 	return fulllen;
 }
 
+static int get_config_net_ipvlan_mode(const char *key, char *retv, int inlen,
+				       struct lxc_conf *c, void *data)
+{
+	int len;
+	int fulllen = 0;
+	const char *mode;
+	struct lxc_netdev *netdev = data;
+
+	if (!retv)
+		inlen = 0;
+	else
+		memset(retv, 0, inlen);
+
+	if (!netdev)
+		return -1;
+
+	if (netdev->type != LXC_NET_IPVLAN)
+		return 0;
+
+	switch (netdev->priv.ipvlan_attr.mode) {
+	case IPVLAN_MODE_L3:
+		mode = "l3";
+		break;
+	case IPVLAN_MODE_L3S:
+		mode = "ls3";
+		break;
+	case IPVLAN_MODE_L2:
+		mode = "l2";
+		break;
+	default:
+		mode = "(invalid)";
+		break;
+	}
+
+	strprint(retv, inlen, "%s", mode);
+
+	return fulllen;
+}
+
+static int get_config_net_ipvlan_flags(const char *key, char *retv, int inlen,
+				       struct lxc_conf *c, void *data)
+{
+	int len;
+	int fulllen = 0;
+	const char *mode;
+	struct lxc_netdev *netdev = data;
+
+	if (!retv)
+		inlen = 0;
+	else
+		memset(retv, 0, inlen);
+
+	if (!netdev)
+		return -1;
+
+	if (netdev->type != LXC_NET_IPVLAN)
+		return 0;
+
+	switch (netdev->priv.ipvlan_attr.mode) {
+	case IPVLAN_FLAGS_BRIDGE:
+		mode = "bridge";
+		break;
+	case IPVLAN_FLAGS_PRIVATE:
+		mode = "private";
+		break;
+	case IPVLAN_FLAGS_VEPA:
+		mode = "vepa";
+		break;
+	default:
+		mode = "(invalid)";
+		break;
+	}
+
+	strprint(retv, inlen, "%s", mode);
+
+	return fulllen;
+}
+
 static int get_config_net_veth_pair(const char *key, char *retv, int inlen,
 				    struct lxc_conf *c, void *data)
 {
@@ -5467,6 +5609,10 @@ int lxc_list_net(struct lxc_conf *c, const char *key, char *retv, int inlen)
 	case LXC_NET_MACVLAN:
 		strprint(retv, inlen, "macvlan.mode\n");
 		break;
+	case LXC_NET_IPVLAN:
+		strprint(retv, inlen, "ipvlan.mode\n");
+		strprint(retv, inlen, "ipvlan.flags\n");
+		break;
 	case LXC_NET_VLAN:
 		strprint(retv, inlen, "vlan.id\n");
 		break;
diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c
index 50777c4481..7ca7c11ee6 100644
--- a/src/lxc/confile_utils.c
+++ b/src/lxc/confile_utils.c
@@ -299,6 +299,18 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
 				      mode ? mode : "(invalid mode)");
 			}
 			break;
+		case LXC_NET_IPVLAN:
+			TRACE("type: ipvlan");
+
+			if (netdev->priv.ipvlan_attr.mode > 0) {
+				char *mode;
+
+				mode = lxc_ipvlan_flag_to_mode(
+				    netdev->priv.ipvlan_attr.mode);
+				TRACE("ipvlan mode: %s",
+				      mode ? mode : "(invalid mode)");
+			}
+			break;
 		case LXC_NET_VLAN:
 			TRACE("type: vlan");
 			TRACE("vlan id: %d", netdev->priv.vlan_attr.vid);
@@ -483,6 +495,82 @@ char *lxc_macvlan_flag_to_mode(int mode)
 	return NULL;
 }
 
+static struct lxc_ipvlan_mode {
+	char *name;
+	int mode;
+} ipvlan_mode[] = {
+    { "l3",  IPVLAN_MODE_L3  },
+    { "l3s", IPVLAN_MODE_L3S },
+    { "l3",  IPVLAN_MODE_L2  },
+};
+
+int lxc_ipvlan_mode_to_flag(int *mode, const char *value)
+{
+	size_t i;
+
+	for (i = 0; i < sizeof(ipvlan_mode) / sizeof(ipvlan_mode[0]); i++) {
+		if (strcmp(ipvlan_mode[i].name, value))
+			continue;
+
+		*mode = ipvlan_mode[i].mode;
+		return 0;
+	}
+
+	return -1;
+}
+
+char *lxc_ipvlan_flag_to_mode(int mode)
+{
+	size_t i;
+
+	for (i = 0; i < sizeof(ipvlan_mode) / sizeof(ipvlan_mode[0]); i++) {
+		if (ipvlan_mode[i].mode == mode)
+			continue;
+
+		return ipvlan_mode[i].name;
+	}
+
+	return NULL;
+}
+
+static struct lxc_ipvlan_flags {
+	char *name;
+	int mode;
+} ipvlan_flags[] = {
+    { "bridge",  IPVLAN_FLAGS_BRIDGE  },
+    { "private", IPVLAN_FLAGS_PRIVATE },
+    { "vepa",    IPVLAN_FLAGS_VEPA    },
+};
+
+int lxc_ipvlan_flags_to_flag(int *mode, const char *value)
+{
+	size_t i;
+
+	for (i = 0; i < sizeof(ipvlan_flags) / sizeof(ipvlan_flags[0]); i++) {
+		if (strcmp(ipvlan_flags[i].name, value))
+			continue;
+
+		*mode = ipvlan_flags[i].mode;
+		return 0;
+	}
+
+	return -1;
+}
+
+char *lxc_ipvlan_flag_to_flags(int mode)
+{
+	size_t i;
+
+	for (i = 0; i < sizeof(ipvlan_flags) / sizeof(ipvlan_flags[0]); i++) {
+		if (ipvlan_flags[i].mode == mode)
+			continue;
+
+		return ipvlan_flags[i].name;
+	}
+
+	return NULL;
+}
+
 int set_config_string_item(char **conf_item, const char *value)
 {
 	char *new_value;
diff --git a/src/lxc/confile_utils.h b/src/lxc/confile_utils.h
index 5a3bcc914c..c91f47398b 100644
--- a/src/lxc/confile_utils.h
+++ b/src/lxc/confile_utils.h
@@ -58,6 +58,10 @@ extern bool lxc_remove_nic_by_idx(struct lxc_conf *conf, unsigned int idx);
 extern void lxc_free_networks(struct lxc_list *networks);
 extern int lxc_macvlan_mode_to_flag(int *mode, const char *value);
 extern char *lxc_macvlan_flag_to_mode(int mode);
+extern int lxc_ipvlan_mode_to_flag(int *mode, const char *value);
+extern char *lxc_ipvlan_flag_to_mode(int mode);
+extern int lxc_ipvlan_flags_to_flag(int *mode, const char *value);
+extern char *lxc_ipvlan_flag_to_flags(int mode);
 
 extern int set_config_string_item(char **conf_item, const char *value);
 extern int set_config_string_item_max(char **conf_item, const char *value,
diff --git a/src/lxc/macro.h b/src/lxc/macro.h
index 7df3b56f03..c392dfac01 100644
--- a/src/lxc/macro.h
+++ b/src/lxc/macro.h
@@ -333,6 +333,30 @@ extern int __build_bug_on_failed;
 #define MACVLAN_MODE_PASSTHRU 8
 #endif
 
+#ifndef IPVLAN_MODE_L3
+#define IPVLAN_MODE_L3 1
+#endif
+
+#ifndef IPVLAN_MODE_L3S
+#define IPVLAN_MODE_L3S 2
+#endif
+
+#ifndef IPVLAN_MODE_L2
+#define IPVLAN_MODE_L2 4
+#endif
+
+#ifndef IPVLAN_FLAGS_BRIDGE
+#define IPVLAN_FLAGS_BRIDGE 1
+#endif
+
+#ifndef IPVLAN_FLAGS_PRIVATE
+#define IPVLAN_FLAGS_PRIVATE 2
+#endif
+
+#ifndef IPVLAN_FLAGS_VEPA
+#define IPVLAN_FLAGS_VEPA 3
+#endif
+
 /* Attributes of RTM_NEWNSID/RTM_GETNSID messages */
 enum {
 	__LXC_NETNSA_NONE,
diff --git a/src/lxc/network.c b/src/lxc/network.c
index d1b4d43ada..2ac72b5391 100644
--- a/src/lxc/network.c
+++ b/src/lxc/network.c
@@ -266,6 +266,11 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
 	return -1;
 }
 
+static int instantiate_ipvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
+{
+	return 0;
+}
+
 static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
 	char peer[IFNAMSIZ];
@@ -320,6 +325,8 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
 	return 0;
 }
 
+
+
 static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
 	int ret;
@@ -392,6 +399,7 @@ static int instantiate_none(struct lxc_handler *handler, struct lxc_netdev *netd
 static  instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
 	[LXC_NET_VETH]    = instantiate_veth,
 	[LXC_NET_MACVLAN] = instantiate_macvlan,
+	[LXC_NET_IPVLAN]  = instantiate_ipvlan,
 	[LXC_NET_VLAN]    = instantiate_vlan,
 	[LXC_NET_PHYS]    = instantiate_phys,
 	[LXC_NET_EMPTY]   = instantiate_empty,
@@ -445,6 +453,11 @@ static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netd
 	return 0;
 }
 
+static int shutdown_ipvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
+{
+	return 0;
+}
+
 static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
 	return 0;
@@ -497,6 +510,7 @@ static int shutdown_none(struct lxc_handler *handler, struct lxc_netdev *netdev)
 static  instantiate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
 	[LXC_NET_VETH]    = shutdown_veth,
 	[LXC_NET_MACVLAN] = shutdown_macvlan,
+	[LXC_NET_IPVLAN]  = shutdown_ipvlan,
 	[LXC_NET_VLAN]    = shutdown_vlan,
 	[LXC_NET_PHYS]    = shutdown_phys,
 	[LXC_NET_EMPTY]   = shutdown_empty,
@@ -1932,6 +1946,7 @@ static const char *const lxc_network_types[LXC_NET_MAXCONFTYPE + 1] = {
 	[LXC_NET_EMPTY]   = "empty",
 	[LXC_NET_VETH]    = "veth",
 	[LXC_NET_MACVLAN] = "macvlan",
+	[LXC_NET_IPVLAN]  = "ipvlan",
 	[LXC_NET_PHYS]    = "phys",
 	[LXC_NET_VLAN]    = "vlan",
 	[LXC_NET_NONE]    = "none",
diff --git a/src/lxc/network.h b/src/lxc/network.h
index ef1b41b897..aaa663dbbd 100644
--- a/src/lxc/network.h
+++ b/src/lxc/network.h
@@ -40,6 +40,7 @@ enum {
 	LXC_NET_EMPTY,
 	LXC_NET_VETH,
 	LXC_NET_MACVLAN,
+	LXC_NET_IPVLAN,
 	LXC_NET_PHYS,
 	LXC_NET_VLAN,
 	LXC_NET_NONE,
@@ -108,6 +109,11 @@ struct ifla_macvlan {
 	int mode; /* private, vepa, bridge, passthru */
 };
 
+struct ifla_ipvlan {
+	int mode; /* l3, l3s, l2 */
+	int flags; /* bridge, private, vepa */
+};
+
 /* Contains information about the physical network device as seen from the host.
  * @ifindex : The ifindex of the physical network device in the host's network
  *            namespace.
@@ -118,6 +124,7 @@ struct ifla_phys {
 
 union netdev_p {
 	struct ifla_macvlan macvlan_attr;
+	struct ifla_ipvlan ipvlan_attr;
 	struct ifla_phys phys_attr;
 	struct ifla_veth veth_attr;
 	struct ifla_vlan vlan_attr;


More information about the lxc-devel mailing list