diff --git a/src/lxc/confile.c b/src/lxc/confile.c index b08aa0174..36d62cbca 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -139,6 +139,7 @@ lxc_config_define(net_nic); lxc_config_define(net_script_down); lxc_config_define(net_script_up); lxc_config_define(net_type); +lxc_config_define(net_veth_mode); lxc_config_define(net_veth_pair); lxc_config_define(net_veth_ipv4_route); lxc_config_define(net_veth_ipv6_route); @@ -234,6 +235,7 @@ static struct lxc_config_t config_jump_table[] = { { "lxc.net.script.up", set_config_net_script_up, get_config_net_script_up, clr_config_net_script_up, }, { "lxc.net.type", set_config_net_type, get_config_net_type, clr_config_net_type, }, { "lxc.net.vlan.id", set_config_net_vlan_id, get_config_net_vlan_id, clr_config_net_vlan_id, }, + { "lxc.net.veth.mode", set_config_net_veth_mode, get_config_net_veth_mode, clr_config_net_veth_mode, }, { "lxc.net.veth.pair", set_config_net_veth_pair, get_config_net_veth_pair, clr_config_net_veth_pair, }, { "lxc.net.veth.ipv4.route", set_config_net_veth_ipv4_route, get_config_net_veth_ipv4_route, clr_config_net_veth_ipv4_route, }, { "lxc.net.veth.ipv6.route", set_config_net_veth_ipv6_route, get_config_net_veth_ipv6_route, clr_config_net_veth_ipv6_route, }, @@ -303,6 +305,7 @@ static int set_config_net_type(const char *key, const char *value, netdev->type = LXC_NET_VETH; lxc_list_init(&netdev->priv.veth_attr.ipv4_routes); lxc_list_init(&netdev->priv.veth_attr.ipv6_routes); + lxc_veth_mode_to_flag(&netdev->priv.veth_attr.mode, "bridge"); } else if (strcmp(value, "macvlan") == 0) { netdev->type = LXC_NET_MACVLAN; lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode, "private"); @@ -450,6 +453,21 @@ static int set_config_net_name(const char *key, const char *value, return network_ifname(netdev->name, value, sizeof(netdev->name)); } + +static int set_config_net_veth_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_veth_mode(key, lxc_conf, data); + + if (!netdev) + return -1; + + return lxc_veth_mode_to_flag(&netdev->priv.veth_attr.mode, value); +} + static int set_config_net_veth_pair(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { @@ -5094,6 +5112,22 @@ static int clr_config_net_ipvlan_isolation(const char *key, return 0; } +static int clr_config_net_veth_mode(const char *key, + struct lxc_conf *lxc_conf, void *data) +{ + struct lxc_netdev *netdev = data; + + if (!netdev) + return minus_one_set_errno(EINVAL); + + if (netdev->type != LXC_NET_VETH) + return 0; + + netdev->priv.veth_attr.mode = -1; + + return 0; +} + static int clr_config_net_veth_pair(const char *key, struct lxc_conf *lxc_conf, void *data) { @@ -5516,6 +5550,42 @@ static int get_config_net_ipvlan_isolation(const char *key, char *retv, int inle return fulllen; } +static int get_config_net_veth_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 minus_one_set_errno(EINVAL); + + if (netdev->type != LXC_NET_VETH) + return 0; + + switch (netdev->priv.veth_attr.mode) { + case VETH_MODE_BRIDGE: + mode = "bridge"; + break; + case VETH_MODE_ROUTER: + mode = "router"; + 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) { diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c index 439445885..6941f4026 100644 --- a/src/lxc/confile_utils.c +++ b/src/lxc/confile_utils.c @@ -501,6 +501,28 @@ void lxc_free_networks(struct lxc_list *networks) lxc_list_init(networks); } + +static struct lxc_veth_mode { + char *name; + int mode; +} veth_mode[] = { + { "bridge", VETH_MODE_BRIDGE }, + { "router", VETH_MODE_ROUTER }, +}; + +int lxc_veth_mode_to_flag(int *mode, const char *value) +{ + for (size_t i = 0; i < sizeof(veth_mode) / sizeof(veth_mode[0]); i++) { + if (strcmp(veth_mode[i].name, value) != 0) + continue; + + *mode = veth_mode[i].mode; + return 0; + } + + return minus_one_set_errno(EINVAL); +} + static struct lxc_macvlan_mode { char *name; int mode; diff --git a/src/lxc/confile_utils.h b/src/lxc/confile_utils.h index cfed91dc0..f68f9604f 100644 --- a/src/lxc/confile_utils.h +++ b/src/lxc/confile_utils.h @@ -56,6 +56,7 @@ lxc_get_netdev_by_idx(struct lxc_conf *conf, unsigned int idx, bool allocate); extern void lxc_log_configured_netdevs(const struct lxc_conf *conf); 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_veth_mode_to_flag(int *mode, const char *value); 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); diff --git a/src/lxc/macro.h b/src/lxc/macro.h index 288f5a8e6..a054176c6 100644 --- a/src/lxc/macro.h +++ b/src/lxc/macro.h @@ -281,6 +281,14 @@ extern int __build_bug_on_failed; #define VETH_INFO_PEER 1 #endif +#ifndef VETH_MODE_BRIDGE +#define VETH_MODE_BRIDGE 1 +#endif + +#ifndef VETH_MODE_ROUTER +#define VETH_MODE_ROUTER 2 +#endif + #ifndef IFLA_MACVLAN_MODE #define IFLA_MACVLAN_MODE 1 #endif diff --git a/src/lxc/network.h b/src/lxc/network.h index 483fbb8cd..7361ce5c1 100644 --- a/src/lxc/network.h +++ b/src/lxc/network.h @@ -98,6 +98,7 @@ struct ifla_veth { int ifindex; struct lxc_list ipv4_routes; struct lxc_list ipv6_routes; + int mode; /* bridge, router */ }; struct ifla_vlan {