diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0197eac..c834aa3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,5 +15,8 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Build and run tests + - name: Build + run: make + + - name: Run tests run: make check diff --git a/Makefile b/Makefile index 736e0b6..9357aae 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ clean: rm -f ${MANPAGES} check: ${LIBIFUPDOWN_LIB} ${CMDS} - kyua test + kyua test || (kyua report --verbose && exit 1) install: all install -D -m755 ${MULTICALL} ${DESTDIR}/sbin/${MULTICALL} diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 2aafd67..aec3a7c 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -1,9 +1,63 @@ #!/bin/sh -[ -z "$VERBOSE" ] || set -x -OPTIONS="" + +[ -n "$VERBOSE" ] && set -x + +IF_LINK_OPTIONS="$IF_LINK_OPTIONS" +[ -n "$IF_MTU" ] && IF_LINK_OPTIONS="$IF_LINK_OPTIONS mtu $IF_MTU" + +is_vlan() { + case "$IFACE" in + *#*) return 1 ;; + *:*) return 1 ;; + vlan*.*) return 1 ;; + vlan*) + IF_VLAN_ID="${IFACE#vlan}" + [ -n "${IF_VLAN_RAW_DEVICE:-}" ] && return 0 + return 1 + ;; + *.*) + IF_VLAN_RAW_DEVICE="${IFACE%.*}" + IF_VLAN_ID="${IFACE##*.}" + return 0 + ;; + *) + [ -z "${IF_VLAN_ID:-}" ] && return 1 + [ -z "${IF_VLAN_RAW_DEVICE:-}" ] && return 1 + return 0 + ;; + esac +} + case "$PHASE" in up|down) - [ -n "$IF_MTU" ] && OPTIONS="$OPTIONS mtu $IF_MTU" - ${MOCK} ip link set $PHASE dev $IFACE $OPTIONS + if is_vlan; then + ADD_DEL="add" + [ "$PHASE" = "down" ] && ADD_DEL="delete" + + if [ -e /sys/class/net/$IFACE ]; then + exit 0 + fi + + if [ -z "$MOCK" ]; then + if ! ip link show "$IF_VLAN_RAW_DEVICE" >/dev/null; then + echo "Device $IF_VLAN_RAW_DEVICE for $IFACE does not exist" + exit 1 + fi + fi + + if ! [ -d /proc/net/vlan ]; then + echo "Loading 8021q kernel module for VLAN support" + ${MOCK} modprobe 8021q + fi + + ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" + else + ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS + fi + ;; +depend) + if is_vlan; then + echo "$IF_VLAN_RAW_DEVICE" + fi ;; esac diff --git a/executor-scripts/stub/vlan b/executor-scripts/stub/vlan deleted file mode 100755 index ba37599..0000000 --- a/executor-scripts/stub/vlan +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -case "$PHASE" in -depend) - RAW_DEVICE="${IFACE%.*}" - echo "$RAW_DEVICE" - ;; -esac diff --git a/libifupdown/interface.c b/libifupdown/interface.c index fe9acea..4f348dc 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -63,7 +63,11 @@ lif_interface_init(struct lif_interface *interface, const char *ifname) interface->ifname = strdup(ifname); - lif_interface_use_executor(interface, strchr(ifname, '.') == NULL ? "link" : "vlan"); + lif_interface_use_executor(interface, "link"); + + /* keep the 'vlan' executor as a config hint for backwards compatibility */ + if (strchr(ifname, '.') != NULL) + lif_interface_use_executor(interface, "vlan"); } bool diff --git a/tests/fixtures/vlan-named.interfaces b/tests/fixtures/vlan-named.interfaces new file mode 100644 index 0000000..73e8ae2 --- /dev/null +++ b/tests/fixtures/vlan-named.interfaces @@ -0,0 +1,4 @@ +iface servers + vlan-raw-device eth0 + vlan-id 8 + address 2001:db8:1000:2::2/64 diff --git a/tests/ifquery_test b/tests/ifquery_test index a53c22c..26c0c6f 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -30,7 +30,9 @@ tests_init \ tunnel_legacy_rewrite \ tunnel_ifupdown2_dependency \ tunnel_ifupdown2_rewrite \ - gre_dependency + gre_dependency \ + vlan_explicit_learned_dependency \ + vlan_guessed_learned_dependency noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -192,3 +194,15 @@ gre_dependency_body() { atf_check -s exit:0 -o match:"requires eth0" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/gre.interfaces tun0 } + +vlan_explicit_learned_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + -o match:"use vlan" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan-named.interfaces servers +} + +vlan_guessed_learned_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + -o match:"use vlan" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan.interfaces eth0.8 +} diff --git a/tests/linux/link_test b/tests/linux/link_test index 717d462..1cb2784 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -3,7 +3,16 @@ . $(atf_get_srcdir)/../test_env.sh EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/link" -tests_init up down mtu +tests_init \ + up \ + down \ + mtu \ + vlan_explicit_up \ + vlan_explicit_down \ + vlan_guessed_up \ + vlan_guessed_down \ + vlan_explicit_depend \ + vlan_guessed_depend up_body() { export IFACE=lo PHASE=up MOCK=echo @@ -22,3 +31,42 @@ mtu_body() { atf_check -s exit:0 -o match:'ip link set up dev eth0 mtu 1492' \ ${EXECUTOR} } + +vlan_explicit_up_body() { + export IFACE=servers PHASE=up MOCK=echo \ + IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" + atf_check -s exit:0 -o match:'ip link add link eth0 name servers type vlan id 123' \ + ${EXECUTOR} +} + +vlan_explicit_down_body() { + export IFACE=servers PHASE=down MOCK=echo \ + IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" + atf_check -s exit:0 -o match:'ip link delete link eth0 name servers type vlan id 123' \ + ${EXECUTOR} +} + +vlan_guessed_up_body() { + export IFACE=eth0.8 PHASE=up MOCK=echo + atf_check -s exit:0 -o match:'ip link add link eth0 name eth0.8 type vlan id 8' \ + ${EXECUTOR} +} + +vlan_guessed_down_body() { + export IFACE=eth0.8 PHASE=down MOCK=echo + atf_check -s exit:0 -o match:'ip link delete link eth0 name eth0.8 type vlan id 8' \ + ${EXECUTOR} +} + +vlan_explicit_depend_body() { + export IFACE=servers PHASE=up MOCK=echo \ + IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" + atf_check -s exit:0 -o match:'eth0' \ + ${EXECUTOR} +} + +vlan_guessed_depend_body() { + export IFACE=eth0.8 PHASE=depend + atf_check -s exit:0 -o match:'eth0' \ + ${EXECUTOR} +}