diff --git a/Makefile b/Makefile index a362e75..febe3b4 100644 --- a/Makefile +++ b/Makefile @@ -138,6 +138,7 @@ install: all ${SCDOC} < $< > $@ MANPAGES_5 = \ + doc/ifupdown-ng.conf.5 \ doc/interfaces.5 \ doc/interfaces-bond.5 \ doc/interfaces-batman.5 \ diff --git a/cmd/ifquery.c b/cmd/ifquery.c index ffb62f2..621b9d7 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -272,6 +272,12 @@ ifquery_main(int argc, char *argv[]) return EXIT_FAILURE; } + if (!lif_compat_apply(&collection)) + { + fprintf(stderr, "%s: failed to apply compatibility glue\n", argv0); + return EXIT_FAILURE; + } + /* --list --state is not allowed */ if (listing && (listing_stat || listing_running)) generic_usage(self_applet, EXIT_FAILURE); diff --git a/dist/ifupdown-ng.conf.example b/dist/ifupdown-ng.conf.example index 7dac1f4..ceffba8 100644 --- a/dist/ifupdown-ng.conf.example +++ b/dist/ifupdown-ng.conf.example @@ -17,6 +17,22 @@ allow_addon_scripts = 1 # templates. Valid values are 0 and 1, the default is 1. allow_any_iface_as_template = 1 +# compat_create_interfaces: +# Denotes where or not to create interfaces when compat_* settings are +# active and it would be necessary to create an interface to be fully +# compliant. This could happen when inheriting bridge VLAN settings to +# an interface within a bridges bridge-ports setting but no interface +# stanza is found. Valid values are 0 and 1, the default is 1. +compat_create_interfaces = 1 + +# compat_ifupdown2_bridge_ports_inherit_vlans: +# In ifupdown2 as well as the 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: # In some legacy configs, a template may be declared as an iface, and # ifupdown-ng automatically converts those declarations to a proper diff --git a/doc/ADMIN-GUIDE.md b/doc/ADMIN-GUIDE.md index 203541b..9242954 100644 --- a/doc/ADMIN-GUIDE.md +++ b/doc/ADMIN-GUIDE.md @@ -60,6 +60,20 @@ Currently the following settings are supported in in order to require inheritance from specified templates. Valid values are `0` and `1`, the default is `1`. +* `compat_create_interfaces`: + Denotes where or not to create interfaces when compat\_* settings are + active and it would be necessary to create an interface to be fully + compliant. This could happen when inheriting bridge VLAN settings to + an interface within a bridges bridge-ports setting but no interface + stanza is found. Valid values are `0` and `1`, the default is `1`. + +* `compat_ifupdown2_bridge_ports_inherit_vlans`: In ifupdown2 `bridge-vids` + as well as the 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 may be declared as an iface, and ifupdown-ng automatically converts those declarations to a proper template. If this setting is diff --git a/doc/ifdown.scd b/doc/ifdown.scd index 15ff53d..0215954 100644 --- a/doc/ifdown.scd +++ b/doc/ifdown.scd @@ -54,8 +54,9 @@ configured in the configuration database. # SEE ALSO -*ifup*(8)++ -*ifquery*(8)++ +*ifupdown-ng.conf*(5) +*ifup*(8) +*ifquery*(8) *interfaces*(5) # AUTHORS diff --git a/doc/ifup.scd b/doc/ifup.scd index c315e6d..0af9150 100644 --- a/doc/ifup.scd +++ b/doc/ifup.scd @@ -57,8 +57,9 @@ configured in the configuration database. # SEE ALSO -*ifdown*(8)++ -*ifquery*(8)++ +*ifupdown-ng.conf*(5) +*ifdown*(8) +*ifquery*(8) *interfaces*(5) # AUTHORS diff --git a/doc/ifupdown-ng.conf.scd b/doc/ifupdown-ng.conf.scd new file mode 100644 index 0000000..124643f --- /dev/null +++ b/doc/ifupdown-ng.conf.scd @@ -0,0 +1,70 @@ +ifupdown-ng.conf(5) + +# NAME + +*ifupdown-ng.conf* - Global configuration file for ifupdown-ng + +# DESCRIPTION + +ifupdown-ng allows to configure some parts of it's behaviour via global +configuration options. + +# GENERAL CONFIGURATION OPTIONS + +*allow_addon_scripts* _bool_ + Enable support for /etc/if-X.d addon scripts. These are used for + compatibility with legacy setups, and may be disabled for + performance improvements in setups where only ifupdown-ng executors + are used. Valid values are _0_ and _1_, the default is _1_. + +*use_hostname_for_dhcp* _bool_ + Automatically learn the hostname property, used for DHCP + configuration by querying the system hostname using uname(2). + This is basically equivalent to `hostname $(hostname)` without + having to specify any configuration. Valid values are _0_ and + _1_, the default is _1_. + +# TEMPLATE RELATED OPTIONS + +*allow_any_iface_as_template* _bool_ + Enable any interface to act as a template for another interface. + This is presently the default, but is deprecated. An admin may + choose to disable this setting in order to require inheritance + from specified templates. Valid values are _0_ and _1_, the + default is _1_. + +*implicit_template_conversion* _bool_ + In some legacy configs, a template may be declared as an iface, and + ifupdown-ng automatically converts those declarations to a proper + template. If this setting is disabled, inheritance will continue + to work against non-template interfaces without converting them to + a template. Valid values are _0_ and _1_, the default is _1_. + +# COMPATIBILITY RELATED OPTIONS + +*compat_create_interfaces* _bool_ + Denotes where or not to create interfaces when compat_* settings are + active and it would be necessary to create an interface to be fully + compliant. This could happen when inheriting bridge VLAN settings to + an interface within a bridges bridge-ports setting but no interface + stanza is found. Valid values are _0_ and _1_, the default is _1_. + +compat_ifupdown2_bridge_ports_inherit_vlans _bool_ + In ifupdown2 as well as the 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_. + +# FILES + +/etc/network/ifupdown-ng.conf + +# SEE ALSO + +*interfaces*(5) + +# AUTHORS + +Maximilian Wilhelm diff --git a/doc/interfaces-bridge.scd b/doc/interfaces-bridge.scd index 15aff2e..4ad3eb6 100644 --- a/doc/interfaces-bridge.scd +++ b/doc/interfaces-bridge.scd @@ -27,6 +27,11 @@ See *ip-link*(8) for more details about the options listed below. removed from the Forwarding DataBase (FDB) after not having seen a frame with this source address. +*bridge-vlan-aware* _bool_ + Denotes wether or not the bridge should be aware of 802.1q VLANs. + _bool_ can be given as _yes_/_no_ or _0_/_1_. The defaul is _no_. + See related options for configuring vlan-aware bridges, below. + # SPANNING TREE RELATED BRIDGE OPTIONS *bridge-stp* _state_ @@ -52,6 +57,51 @@ See *ip-link*(8) for more details about the options listed below. after reception of its last STP hello message. Valid values are between 6 and 40. +# OPTIONS FOR VLAN-AWARE-BRIDGES + +The following options only have an effect on vlan-aware bridges and +their ports. + +All settings can be applied on the bridge interface itself and all member +port iface stanzas. If applied on the bridge interface they take effect +for the bridge interface itself and might be inherited to _bridge-ports_ +depending on the compatibility settings configured in *ifupdown-ng.conf*(5). + +Configuring VLAN options on the bridge interface might be required for +setting up a VLAN interface to one of the VLANs carried within the bridge. +See the EXAMPLES section for an example for this scenario. + +See *ifupdown-ng.conf*(5) for more information about compatiblity settings +mentioned below. + +*bridge-access* _vlan ID_ + Configure the given _vlan ID_ for untagged ingress and egress + on this interface. The common description for this kind of + configuration is called "access port". + +*bridge-pvid* _vlan ID_ + Denotes the _vlan ID_ to considered a PVID at ingress. + Any untagged frames received on this interface will be + assigned to this _vlan ID_. The default PVID is _1_. + + If compatibility to ifupdown2 bridge port inheritance is active + a _bridge-pvid_ set on the bridge will be inherited to any + interface configured in _bridge-ports_ without a _bridge-pvid_ set. + +*bridge-vids* _list of vlan IDs_ + Denotes the space separated list of VLANs to be allowed tagged + ingress/egress on this interface. + + If compatibility to ifupdown2 bridge port inheritance is active + a _bridge-vids_ set on the bridge will be inherited to any + interface configured in _bridge-ports_ without _bridge-vids_ set. + +*bridge-allow-untagged* _bool_ + Denotes wether or not the bridge should allow untagged frames on + ingress as well as egress. If set to _no_ untagged frames will be + droppped on ingress and none will be sent. _bool_ can be given as + _yes_/_no_ or _0_/_1_. The defaul is _yes_. + # EXAMPLES A simple layer 2 only bridge: @@ -77,10 +127,46 @@ iface br0 address 2001:db8::42/64 ``` +A layer 2 only vlan-aware bridge: + +``` +auto bond0 +iface bond0 + bond-members eth0 eth1 + bridge-vids 23 42 84 1337 + +auto br0 +iface br0 + bridge-ports bond0 +``` + +A vlan-aware bridge with a VLAN interface on top: + +``` +auto eth0 +iface eth0 + bridge-vids 23 42 84 1337 + +auto br0 +iface br0 + bridge-ports eth0 + bridge-vlan-aware yes + bridge-vids 42 + +auto vlan42 +iface vlan42 + vlan-raw-device br0 + # + address 192.0.2.42/24 + address 2001:db8::42/64 +``` + # SEE ALSO -*ip-link*(8) *interfaces*(5) +*ifupdown-ng.conf*(5) +*ip-link*(8) +*bridge*(8) # AUTHORS diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 6b3d4fb..3c8dd23 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -216,6 +216,7 @@ iface eth0 # SEE ALSO +*ifupdown-ng.conf*(5) *ifup*(8) *ifdown*(8) *ifquery*(8) diff --git a/executor-scripts/linux/bridge b/executor-scripts/linux/bridge index 5d92061..384d30e 100755 --- a/executor-scripts/linux/bridge +++ b/executor-scripts/linux/bridge @@ -1,6 +1,7 @@ #!/bin/sh set -e +[ -n "$VERBOSE" ] && set -x # Copyright (C) 2012, 2020 Natanael Copa # Copyright (C) 2020 Ariadne Conill @@ -14,6 +15,10 @@ set -e # implied. In no event shall the authors be liable for any damages arising # from the use of this software. +################################################################################ +# Bridge management functions # +################################################################################ + all_ports_exist() { local i= for i in "$@"; do @@ -52,13 +57,10 @@ all_ports() { add_ports() { local port= for port in $PORTS; do - if [ -x /etc/network/if-pre-up.d/vlan ]; then - env IFACE=$port /etc/network/if-pre-up.d/vlan - fi if [ -n "$IF_BRIDGE_HW" ]; then ip link set dev $port addr $IF_BRIDGE_HW fi - brctl addif $IFACE $port && ip link set dev $port up + ip link set dev $port master $IFACE && ip link set dev $port up done } @@ -66,22 +68,17 @@ del_ports() { local port= for port in $PORTS; do ip link set dev $port down - brctl delif $IFACE $port - if [ -x /etc/network/ip-post-down.d/vlan ]; then - env IFACE=$port /etc/network/if-post-down.d/vlan - fi + ip link set dev $port nomaster done } -set_bridge_opts() { +set_bridge_opts_brctl() { [ -n "$IF_BRIDGE_AGEING" ] \ && brctl setageing $IFACE $IF_BRIDGE_AGEING [ -n "$IF_BRIDGE_BRIDGEPRIO" ] \ && brctl setbridgeprio $IFACE $IF_BRIDGE_BRIDGEPRIO [ -n "$IF_BRIDGE_FD" ] \ && brctl setfd $IFACE $IF_BRIDGE_FD - [ -n "$IF_BRIDGE_GCINT" ] \ - && brctl setgcint $IFACE $IF_BRIDGE_GCINT [ -n "$IF_BRIDGE_HELLO" ] \ && brctl sethello $IFACE $IF_BRIDGE_HELLO [ -n "$IF_BRIDGE_MAXAGE" ] \ @@ -94,6 +91,44 @@ set_bridge_opts() { && brctl stp $IFACE $IF_BRIDGE_STP } +yesno() { + case "$1" in + yes|YES|true|TRUE|1) + echo 1 + ;; + *) + echo 0 + ;; + esac +} + +set_bridge_opts_iproute2() { + [ -n "$IF_BRIDGE_AGEING" ] \ + && ip link set dev $IFACE type bridge ageing_time $IF_BRIDGE_AGEING + [ -n "$IF_BRIDGE_BRIDGEPRIO" ] \ + && ip link set dev $IFACE type bridge priority $IF_BRIDGE_BRIDGEPRIO + [ -n "$IF_BRIDGE_FD" ] \ + && ip link set dev $IFACE type bridge forward_delay $IF_BRIDGE_FD + [ -n "$IF_BRIDGE_HELLO" ] \ + && ip link set dev $IFACE type bridge hello_time $IF_BRIDGE_HELLO + [ -n "$IF_BRIDGE_MAXAGE" ] \ + && ip link set dev $IFACE type bridge max_age $IF_BRIDGE_MAXAGE + [ -n "$IF_BRIDGE_PATHCOST" ] \ + && bridge link set dev $IFACE cost $IF_BRIDGE_PATHCOST + [ -n "$IF_BRIDGE_PORTPRIO" ] \ + && bridge link set dev $IFACE priority $IF_BRIDGE_PORTPRIO + [ -n "$IF_BRIDGE_STP" ] \ + && ip link set dev $IFACE type bridge stp $(yesno $IF_BRIDGE_STP) + [ -n "$IF_BRIDGE_VLAN_AWARE" ] \ + && ip link set dev $IFACE type bridge vlan_filtering $(yesno $IF_BRIDGE_VLAN_AWARE) +} + +set_bridge_opts() { + [ -x /sbin/bridge ] && set_bridge_opts_iproute2 && return 0 + [ -x /sbin/brctl ] && set_bridge_opts_brctl && return 0 +} + + all_ports_ready() { local port= for port in $PORTS; do @@ -123,7 +158,92 @@ wait_bridge() { done } -[ -z "$IF_BRIDGE_PORTS" ] && IF_BRIDGE_PORTS="$IF_REQUIRES" + +################################################################################ +# Bridge port management functions # +################################################################################ + +configure_access_port() { + port="$1" + vlan="$2" + self="$3" + + # Cleans all existing VLANs (probably at least VLAN 1) + bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | while read vid flags; do + bridge vlan del vid "${vid}" dev "${port}" ${self} + done + + bridge vlan add vid "${vlan}" pvid untagged dev "${port}" ${self} +} + +configure_trunk_port() { + port="$1" + self="$2" + + # Working on the bridge itself? + if [ "${self}" ]; then + allow_untagged="${IF_BRIDGE_ALLOW_UNTAGGED}" + pvid="${IF_BRIDGE_PVID}" + vids="${IF_BRIDGE_VIDS}" + else + allow_untagged=$(ifquery -p bridge-allow-untagged ${port} 2>/dev/null || true) + pvid=$(ifquery -p bridge-pvid ${port} 2>/dev/null || true) + vids=$(ifquery -p bridge-vids ${port} 2>/dev/null || true) + fi + + # If bridge-allow-untagged if set to off, remove untagged VLAN. If it's + # one of our bridge-vids, it will be set again later. + if [ "${allow_untagged}" -a "$(yesno ${allow_untagged})" = 0 ]; then + untagged_vid=$(bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | awk '/Untagged/ { print $1 }') + if [ "${untagged_vid}" ]; then + bridge vlan del vid "${untagged_vid}" dev "${port}" ${self} + fi + fi + + # The vlan specified is to be considered a PVID at ingress. + # Any untagged frames will be assigned to this VLAN. + if [ "${pvid}" ]; then + cur_pvid=$(bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | awk '/PVID/ { print $1 }') + if [ "${cur_pvid}" ]; then + bridge vlan del vid ${cur_pvid} dev "${port}" ${self} + fi + + bridge vlan add vid "${pvid}" dev "${port}" pvid untagged ${self} + fi + + # Add regular tagged VLANs + for vid in ${vids}; do + bridge vlan add vid $vid dev "${port}" ${self} + done +} + +# Configure VLANs on the bridge interface itself +set_bridge_vlans() { + # Shall the bridge interface be an untagged port? + if [ "${IF_BRIDGE_ACCESS}" ]; then + configure_access_port "${IFACE}" "${IF_BRIDGE_ACCESS}" "self" + + # Configure bridge interface as trunk port + else + configure_trunk_port "${IFACE}" "self" + fi +} + +# Configure VLANs on the bridge-ports +set_bridge_port_vlans() { + for port in ${PORTS}; do + access_vlan=$(ifquery -p bridge-access ${port} 2>/dev/null || true) + + # Shall this prot interface be an untagged port? + if [ "${access_vlan}" ]; then + configure_access_port "${port}" "${access_vlan}" + + # Configure port as trunk + else + configure_trunk_port "${port}" + fi + done +} case "$IF_BRIDGE_PORTS" in "") ;; @@ -132,30 +252,53 @@ all) PORTS=$(all_ports);; *) PORTS="$IF_BRIDGE_PORTS";; esac -[ -z "$PORTS" ] && ! env | grep -q "^IF_BRIDGE" && exit - case "$PHASE" in depend) - echo "$PORTS" - ;; -create) - if [ ! -d "/sys/class/net/${IFACE}" ]; then - brctl addbr "${IFACE}" + # Called for the bridge interface + if [ "${IF_BRIDGE_PORTS}" ]; then + echo "$PORTS" fi ;; + +create) + # Called for the bridge interface + if [ "${IF_BRIDGE_PORTS}" -a ! -d "/sys/class/net/${IFACE}" ]; then + ip link add "${IFACE}" type bridge + fi + ;; + pre-up) - wait_ports - set_bridge_opts - add_ports - wait_bridge + # Called for the bridge interface + if [ "${IF_BRIDGE_PORTS}" ]; then + wait_ports + set_bridge_opts + set_bridge_vlans + add_ports + set_bridge_port_vlans + wait_bridge + + # Called for a bridge member port + elif [ "${IF_BRIDGE_VIDS}" -o "${IF_BRIDGE_PVID}" -o "${IF_BRIDGE_ACCESS}" -o "${IF_BRIDGE_ALLOW_UNTAGGED}" ]; then + # Eventually we want to configure VLAN settings of member ports here. + # The current execution model does not allow this, so this is a no-op + # for now and we work around this by configuring ports while configuring + # the bridge. + true + fi ;; + post-down) - del_ports - ip link set dev $IFACE down + # Called for the bridge interface + if [ "${IF_BRIDGE_PORTS}" ]; then + del_ports + ip link set dev $IFACE down + fi ;; + destroy) - if [ -d "/sys/class/net/${IFACE}" ]; then - brctl delbr "${IFACE}" + # Called for the bridge interface + if [ "${IF_BRIDGE_PORTS}" -a -d "/sys/class/net/${IFACE}" ]; then + ip link del "${IFACE}" fi ;; esac diff --git a/libifupdown/compat.c b/libifupdown/compat.c index 10a16d7..b6e5547 100644 --- a/libifupdown/compat.c +++ b/libifupdown/compat.c @@ -14,14 +14,100 @@ */ #include +#include +#include +#include "libifupdown/config-file.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 if (lif_config.compat_create_interfaces) + { + bridge_port = lif_interface_collection_find(collection, tokenp); + if (bridge_port == NULL) + { + fprintf(stderr, "Failed to add interface \"%s\"", tokenp); + return false; + } + } + + /* We would have to creaet an interface, but shouldn't */ + else + { + fprintf(stderr, "compat: Missing interface stanza for bridge-port \"%s\" but should not create one.\n", + tokenp); + continue; + } + + /* 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 lif_compat_apply(struct lif_dict *collection) { - (void) collection; - - /* Mangle interfaces according to some config options here */ + if (lif_config.compat_ifupdown2_bridge_ports_inherit_vlans && + !compat_ifupdown2_bridge_ports_inherit_vlans(collection)) + return false; return true; } diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c index 2438e15..e5c79ff 100644 --- a/libifupdown/config-file.c +++ b/libifupdown/config-file.c @@ -21,6 +21,8 @@ struct lif_config_file lif_config = { .allow_addon_scripts = true, .allow_any_iface_as_template = true, + .compat_create_interfaces = true, + .compat_ifupdown2_bridge_ports_inherit_vlans = true, .implicit_template_conversion = true, .use_hostname_for_dhcp = true, }; @@ -31,7 +33,7 @@ set_bool_value(const char *key, const char *value, void *opaque) (void) key; if (*value == '1' || - *value == 'Y' || *value == 'y' || + *value == 'Y' || *value == 'y' || *value == 'T' || *value == 't') *(bool *) opaque = true; else if (*value == '0' || @@ -47,6 +49,8 @@ set_bool_value(const char *key, const char *value, void *opaque) static struct lif_config_handler handlers[] = { {"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}, + {"compat_create_interfaces", set_bool_value, &lif_config.compat_create_interfaces}, + {"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}, {"use_hostname_for_dhcp", set_bool_value, &lif_config.use_hostname_for_dhcp}, }; diff --git a/libifupdown/config-file.h b/libifupdown/config-file.h index b264148..4364f5b 100644 --- a/libifupdown/config-file.h +++ b/libifupdown/config-file.h @@ -21,6 +21,8 @@ struct lif_config_file { bool allow_addon_scripts; bool allow_any_iface_as_template; + bool compat_create_interfaces; + bool compat_ifupdown2_bridge_ports_inherit_vlans; bool implicit_template_conversion; bool use_hostname_for_dhcp; }; diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 6481be8..4628a70 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -206,6 +206,10 @@ handle_generic(struct lif_interface_file_parse_state *state, char *token, char * 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 */ while (isspace (*bufp)) bufp++;