Merge pull request #111 from ifupdown-ng/feature/deprecate-brctl
vlan aware bridging
This commit is contained in:
commit
19a5a671eb
14 changed files with 471 additions and 36 deletions
1
Makefile
1
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 \
|
||||
|
|
|
@ -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);
|
||||
|
|
16
dist/ifupdown-ng.conf.example
vendored
16
dist/ifupdown-ng.conf.example
vendored
|
@ -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 <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:
|
||||
# In some legacy configs, a template may be declared as an iface, and
|
||||
# ifupdown-ng automatically converts those declarations to a proper
|
||||
|
|
|
@ -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 <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
|
||||
may be declared as an iface, and ifupdown-ng automatically converts
|
||||
those declarations to a proper template. If this setting is
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
70
doc/ifupdown-ng.conf.scd
Normal file
70
doc/ifupdown-ng.conf.scd
Normal file
|
@ -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 <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_.
|
||||
|
||||
# FILES
|
||||
|
||||
/etc/network/ifupdown-ng.conf
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
*interfaces*(5)
|
||||
|
||||
# AUTHORS
|
||||
|
||||
Maximilian Wilhelm <max@sdn.clinic>
|
|
@ -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
|
||||
|
||||
|
|
|
@ -216,6 +216,7 @@ iface eth0
|
|||
|
||||
# SEE ALSO
|
||||
|
||||
*ifupdown-ng.conf*(5)
|
||||
*ifup*(8)
|
||||
*ifdown*(8)
|
||||
*ifquery*(8)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
[ -n "$VERBOSE" ] && set -x
|
||||
|
||||
# Copyright (C) 2012, 2020 Natanael Copa <ncopa@alpinelinux.org>
|
||||
# Copyright (C) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||
|
@ -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
|
||||
|
|
|
@ -14,14 +14,100 @@
|
|||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 <token> */
|
||||
while (isspace (*bufp))
|
||||
bufp++;
|
||||
|
|
Loading…
Reference in a new issue