compat: Add glue for ifupdown2 bridge port VLAN inheritance.
Add config options <compat_ifupdown2_bridge_ports_inherit_vlans>. In ifupdown2 <bridge-vids> as well as the <bridge-pvid> set on a bridge interface will be inherited by all member ports if not set explicitly. When set to 1 ifupdown-ng behaves the same way and will internally copy both options from the bridge member ports if they are not set on the member port. Valid values are 0 and 1, the default is 1. Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
This commit is contained in:
parent
56beefdd28
commit
d86297f29c
6 changed files with 103 additions and 4 deletions
8
dist/ifupdown-ng.conf.example
vendored
8
dist/ifupdown-ng.conf.example
vendored
|
@ -17,6 +17,14 @@ allow_addon_scripts = 1
|
||||||
# templates. Valid values are 0 and 1, the default is 1.
|
# templates. Valid values are 0 and 1, the default is 1.
|
||||||
allow_any_iface_as_template = 1
|
allow_any_iface_as_template = 1
|
||||||
|
|
||||||
|
# compat_ifupdown2_bridge_ports_inherit_vlans:
|
||||||
|
# In ifupdown2 <bridge-vids> as well as the <bridge-pvid> set on a bridge
|
||||||
|
# interface will be inherited by all member ports if not set explicitly.
|
||||||
|
# When set to 1 ifupdown-ng behaves the same way and will internally copy
|
||||||
|
# both options from the bridge member ports if they are not set on the
|
||||||
|
# member port. Valid values are 0 and 1, the default is 1.
|
||||||
|
compat_ifupdown2_bridge_ports_inherit_vlans = 1
|
||||||
|
|
||||||
# implicit_template_conversion:
|
# implicit_template_conversion:
|
||||||
# In some legacy configs, a template may be declared as an iface, and
|
# In some legacy configs, a template may be declared as an iface, and
|
||||||
# ifupdown-ng automatically converts those declarations to a proper
|
# ifupdown-ng automatically converts those declarations to a proper
|
||||||
|
|
|
@ -60,6 +60,13 @@ Currently the following settings are supported in
|
||||||
in order to require inheritance from specified templates.
|
in order to require inheritance from specified templates.
|
||||||
Valid values are `0` and `1`, the default is `1`.
|
Valid values are `0` and `1`, the default is `1`.
|
||||||
|
|
||||||
|
* `compat_ifupdown2_bridge_ports_inherit_vlans`: In ifupdown2 `bridge-vids`
|
||||||
|
as well as the <bridge-pvid> set on a bridge interface will be inherited
|
||||||
|
by all member ports if not set explicitly. When set to `1` ifupdown-ng
|
||||||
|
behaves the same way and will internally copy both options from the
|
||||||
|
bridge member ports if they are not set on the member port.
|
||||||
|
Valid values are `0` and `1`, the default is `1`.
|
||||||
|
|
||||||
* `implicit_template_conversion`: In some legacy configs, a template
|
* `implicit_template_conversion`: In some legacy configs, a template
|
||||||
may be declared as an iface, and ifupdown-ng automatically converts
|
may be declared as an iface, and ifupdown-ng automatically converts
|
||||||
those declarations to a proper template. If this setting is
|
those declarations to a proper template. If this setting is
|
||||||
|
|
|
@ -14,14 +14,91 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "libifupdown/config-file.h"
|
||||||
#include "libifupdown/dict.h"
|
#include "libifupdown/dict.h"
|
||||||
|
#include "libifupdown/interface.h"
|
||||||
|
#include "libifupdown/tokenize.h"
|
||||||
|
|
||||||
|
static bool
|
||||||
|
compat_ifupdown2_bridge_ports_inherit_vlans(struct lif_dict *collection)
|
||||||
|
{
|
||||||
|
struct lif_node *iter;
|
||||||
|
|
||||||
|
/* Loop through all interfaces and search for bridges */
|
||||||
|
LIF_DICT_FOREACH(iter, collection)
|
||||||
|
{
|
||||||
|
struct lif_dict_entry *entry = iter->data;
|
||||||
|
struct lif_interface *bridge = entry->data;
|
||||||
|
|
||||||
|
/* We only care for bridges */
|
||||||
|
if (!bridge->is_bridge)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct lif_dict_entry *bridge_pvid = lif_dict_find(&bridge->vars, "bridge-pvid");
|
||||||
|
struct lif_dict_entry *bridge_vids = lif_dict_find(&bridge->vars, "bridge-vids");
|
||||||
|
|
||||||
|
/* If there's nothing to inherit here, carry on */
|
||||||
|
if (bridge_pvid == NULL && bridge_vids == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct lif_dict_entry *bridge_ports_entry = lif_dict_find(&bridge->vars, "bridge-ports");
|
||||||
|
|
||||||
|
/* This SHOULD not happen, but better save than sorry */
|
||||||
|
if (bridge_ports_entry == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char bridge_ports_str[4096] = {};
|
||||||
|
strlcpy(bridge_ports_str, bridge_ports_entry->data, sizeof bridge_ports_str);
|
||||||
|
|
||||||
|
/* If there are no bridge-ports configured, carry on */
|
||||||
|
if (strcmp(bridge_ports_str, "none") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Loop over all bridge-ports and set bridge-pvid and bridge-vid if not set already */
|
||||||
|
char *bufp = bridge_ports_str;
|
||||||
|
for (char *tokenp = lif_next_token(&bufp); *tokenp; tokenp = lif_next_token(&bufp))
|
||||||
|
{
|
||||||
|
entry = lif_dict_find(collection, tokenp);
|
||||||
|
|
||||||
|
/* There might be interfaces give within the bridge-ports for which there is no
|
||||||
|
* interface stanza. If this is the case, we add one, so we can inherit the
|
||||||
|
* bridge-vids/pvid to it. */
|
||||||
|
struct lif_interface *bridge_port;
|
||||||
|
if (entry)
|
||||||
|
bridge_port = entry->data;
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bridge_port = lif_interface_collection_find(collection, tokenp);
|
||||||
|
if (bridge_port == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to add interface \"%s\"", tokenp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maybe pimp bridge-pvid */
|
||||||
|
struct lif_dict_entry *port_pvid = lif_dict_find(&bridge_port->vars, "bridge-pvid");
|
||||||
|
if (bridge_pvid && !port_pvid)
|
||||||
|
lif_dict_add(&bridge_port->vars, "bridge-pvid", bridge_pvid->data);
|
||||||
|
|
||||||
|
/* Maybe pimp bridge-vids */
|
||||||
|
struct lif_dict_entry *port_vids = lif_dict_find(&bridge_port->vars, "bridge-vids");
|
||||||
|
if (bridge_vids && !port_vids)
|
||||||
|
lif_dict_add(&bridge_port->vars, "bridge-vids", bridge_vids->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
lif_compat_apply(struct lif_dict *collection)
|
lif_compat_apply(struct lif_dict *collection)
|
||||||
{
|
{
|
||||||
(void) collection;
|
if (lif_config.compat_ifupdown2_bridge_ports_inherit_vlans &&
|
||||||
|
!compat_ifupdown2_bridge_ports_inherit_vlans(collection))
|
||||||
/* Mangle interfaces according to some config options here */
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
struct lif_config_file lif_config = {
|
struct lif_config_file lif_config = {
|
||||||
.allow_addon_scripts = true,
|
.allow_addon_scripts = true,
|
||||||
.allow_any_iface_as_template = true,
|
.allow_any_iface_as_template = true,
|
||||||
|
.compat_ifupdown2_bridge_ports_inherit_vlans = true,
|
||||||
.implicit_template_conversion = true,
|
.implicit_template_conversion = true,
|
||||||
.use_hostname_for_dhcp = true,
|
.use_hostname_for_dhcp = true,
|
||||||
};
|
};
|
||||||
|
@ -47,6 +48,7 @@ set_bool_value(const char *key, const char *value, void *opaque)
|
||||||
static struct lif_config_handler handlers[] = {
|
static struct lif_config_handler handlers[] = {
|
||||||
{"allow_addon_scripts", set_bool_value, &lif_config.allow_addon_scripts},
|
{"allow_addon_scripts", set_bool_value, &lif_config.allow_addon_scripts},
|
||||||
{"allow_any_iface_as_template", set_bool_value, &lif_config.allow_any_iface_as_template},
|
{"allow_any_iface_as_template", set_bool_value, &lif_config.allow_any_iface_as_template},
|
||||||
|
{"compat_ifupdown2_bridge_ports_inherit_vlans", set_bool_value, &lif_config.compat_ifupdown2_bridge_ports_inherit_vlans},
|
||||||
{"implicit_template_conversion", set_bool_value, &lif_config.implicit_template_conversion},
|
{"implicit_template_conversion", set_bool_value, &lif_config.implicit_template_conversion},
|
||||||
{"use_hostname_for_dhcp", set_bool_value, &lif_config.use_hostname_for_dhcp},
|
{"use_hostname_for_dhcp", set_bool_value, &lif_config.use_hostname_for_dhcp},
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
struct lif_config_file {
|
struct lif_config_file {
|
||||||
bool allow_addon_scripts;
|
bool allow_addon_scripts;
|
||||||
bool allow_any_iface_as_template;
|
bool allow_any_iface_as_template;
|
||||||
|
bool compat_ifupdown2_bridge_ports_inherit_vlans;
|
||||||
bool implicit_template_conversion;
|
bool implicit_template_conversion;
|
||||||
bool use_hostname_for_dhcp;
|
bool use_hostname_for_dhcp;
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,6 +203,10 @@ handle_generic(struct lif_interface_file_parse_state *state, char *token, char *
|
||||||
|
|
||||||
token = maybe_remap_token(token);
|
token = maybe_remap_token(token);
|
||||||
|
|
||||||
|
/* This smells like a bridge */
|
||||||
|
if (strcmp(token, "bridge-ports") == 0)
|
||||||
|
state->cur_iface->is_bridge = true;
|
||||||
|
|
||||||
/* Skip any leading whitespaces in value for <token> */
|
/* Skip any leading whitespaces in value for <token> */
|
||||||
while (isspace (*bufp))
|
while (isspace (*bufp))
|
||||||
bufp++;
|
bufp++;
|
||||||
|
|
Loading…
Reference in a new issue