Merge pull request #38 from ifupdown-ng/bugfix/vlan-complex

vlan and assorted fixes
This commit is contained in:
Ariadne Conill 2020-08-24 11:14:45 -06:00 committed by GitHub
commit 3997b6a952
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 86 additions and 28 deletions

View file

@ -29,12 +29,14 @@ is_vlan() {
} }
case "$PHASE" in case "$PHASE" in
up|down) pre-up|post-down)
UP_DOWN="${PHASE##*-}"
if is_vlan; then if is_vlan; then
ADD_DEL="add" ADD_DEL="add"
[ "$PHASE" = "down" ] && ADD_DEL="delete" [ "$UP_DOWN" = "down" ] && ADD_DEL="delete"
if [ -e /sys/class/net/$IFACE ]; then if [ "$UP_DOWN" = "up" -a -e /sys/class/net/$IFACE ]; then
exit 0 exit 0
fi fi
@ -43,16 +45,19 @@ up|down)
echo "Device $IF_VLAN_RAW_DEVICE for $IFACE does not exist" echo "Device $IF_VLAN_RAW_DEVICE for $IFACE does not exist"
exit 1 exit 1
fi fi
fi
if ! [ -d /proc/net/vlan ]; then if ! [ -d /proc/net/vlan ]; then
echo "Loading 8021q kernel module for VLAN support" echo "Loading 8021q kernel module for VLAN support"
${MOCK} modprobe 8021q ${MOCK} modprobe 8021q
fi
fi fi
${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID"
[ "$UP_DOWN" = "down" ] && exit 0
${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS
else else
${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS ${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS
fi fi
;; ;;
depend) depend)

View file

@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
[ -z "$IF_METRIC" ] && IF_METRIC="1"
[ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE" [ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE"
[ -n "$IF_METRIC" ] && METRIC="metric $IF_METRIC" [ -n "$IF_METRIC" ] && METRIC="metric $IF_METRIC"

View file

@ -35,6 +35,9 @@ struct lif_dict_entry {
#define LIF_DICT_FOREACH_SAFE(iter, iter_next, dict) \ #define LIF_DICT_FOREACH_SAFE(iter, iter_next, dict) \
LIF_LIST_FOREACH_SAFE((iter), (iter_next), (dict)->list.head) LIF_LIST_FOREACH_SAFE((iter), (iter_next), (dict)->list.head)
#define LIF_DICT_FOREACH_REVERSE(iter, dict) \
LIF_LIST_FOREACH_REVERSE((iter), (dict)->list.tail)
typedef int (*lif_dict_cmp_t)(const void *, const void *); typedef int (*lif_dict_cmp_t)(const void *, const void *);
extern void lif_dict_init(struct lif_dict *dict); extern void lif_dict_init(struct lif_dict *dict);

View file

@ -43,21 +43,33 @@ handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[
return true; return true;
} }
static inline bool
handle_single_executor_for_phase(const struct lif_dict_entry *entry, const struct lif_execute_opts *opts, char *const envp[])
{
if (strcmp(entry->key, "use"))
return true;
const char *cmd = entry->data;
if (!lif_maybe_run_executor(opts, envp, cmd))
return false;
return true;
}
static bool static bool
handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface) handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, bool up)
{ {
struct lif_node *iter; struct lif_node *iter;
LIF_DICT_FOREACH(iter, &iface->vars) if (up)
{ {
struct lif_dict_entry *entry = iter->data; LIF_DICT_FOREACH(iter, &iface->vars)
handle_single_executor_for_phase(iter->data, opts, envp);
if (strcmp(entry->key, "use")) }
continue; else
{
const char *cmd = entry->data; LIF_DICT_FOREACH_REVERSE(iter, &iface->vars)
if (!lif_maybe_run_executor(opts, envp, cmd)) handle_single_executor_for_phase(iter->data, opts, envp);
return false;
} }
return true; return true;
@ -219,7 +231,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac
build_environment(&envp, opts, iface, lifname, phase, up ? "start" : "stop"); build_environment(&envp, opts, iface, lifname, phase, up ? "start" : "stop");
if (!handle_executors_for_phase(opts, envp, iface)) if (!handle_executors_for_phase(opts, envp, iface, up))
goto handle_error; goto handle_error;
if (!handle_commands_for_phase(opts, envp, iface, phase)) if (!handle_commands_for_phase(opts, envp, iface, phase))
@ -255,7 +267,11 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par
/* already up or down, skip */ /* already up or down, skip */
if (up == iface->is_up) if (up == iface->is_up)
{
fprintf(stderr, "ifupdown: skipping dependent interface %s (of %s)\n",
iface->ifname, parent->ifname);
continue; continue;
}
if (opts->verbose) if (opts->verbose)
fprintf(stderr, "ifupdown: changing state of dependent interface %s (of %s) to %s\n", fprintf(stderr, "ifupdown: changing state of dependent interface %s (of %s) to %s\n",

View file

@ -42,4 +42,7 @@ extern void lif_node_delete(struct lif_node *node, struct lif_list *list);
#define LIF_LIST_FOREACH_SAFE(iter, iter_next, head) \ #define LIF_LIST_FOREACH_SAFE(iter, iter_next, head) \
for ((iter) = (head), (iter_next) = (iter)->next; (iter) != NULL; (iter) = (iter_next), (iter_next) = (iter) != NULL ? (iter)->next : NULL) for ((iter) = (head), (iter_next) = (iter)->next; (iter) != NULL; (iter) = (iter_next), (iter_next) = (iter) != NULL ? (iter)->next : NULL)
#define LIF_LIST_FOREACH_REVERSE(iter, tail) \
for ((iter) = (tail); (iter) != NULL; (iter) = (iter)->prev)
#endif #endif

18
tests/fixtures/vlan-complex.interfaces vendored Normal file
View file

@ -0,0 +1,18 @@
# From Alpine issue #11885.
iface lo inet loopback
auto eth0
iface eth0
address 1.2.3.4/24
address abcd:ef12:3456:3::4/64
mtu 8000
auto servers
iface servers
address 1.2.10.4/24
gateway 1.2.10.1
address abcd:ef12:3456:10::4/64
gateway abcd:ef12:3456:10::1
mtu 8000
vlan-raw-device eth0
vlan_id 5

View file

@ -32,7 +32,8 @@ tests_init \
tunnel_ifupdown2_rewrite \ tunnel_ifupdown2_rewrite \
gre_dependency \ gre_dependency \
vlan_explicit_learned_dependency \ vlan_explicit_learned_dependency \
vlan_guessed_learned_dependency vlan_guessed_learned_dependency \
vlan_complex_learned_dependency
noargs_body() { noargs_body() {
atf_check -s exit:1 -e ignore ifquery -S/dev/null atf_check -s exit:1 -e ignore ifquery -S/dev/null
@ -206,3 +207,14 @@ vlan_guessed_learned_dependency_body() {
-o match:"use vlan" \ -o match:"use vlan" \
ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan.interfaces eth0.8 ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan.interfaces eth0.8
} }
vlan_complex_learned_dependency_body() {
atf_check -s exit:0 -o match:"requires eth0" \
-o match:"use vlan" \
-o match:"address 1.2.10.4/24" \
-o match:"gateway 1.2.10.1" \
-o match:"address abcd:ef12:3456:10::4/64" \
-o match:"gateway abcd:ef12:3456:10::1" \
-o match:"vlan-raw-device eth0" \
ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan-complex.interfaces servers
}

View file

@ -15,51 +15,51 @@ tests_init \
vlan_guessed_depend vlan_guessed_depend
up_body() { up_body() {
export IFACE=lo PHASE=up MOCK=echo export IFACE=lo PHASE=pre-up MOCK=echo
atf_check -s exit:0 -o match:'ip link set up dev lo' \ atf_check -s exit:0 -o match:'ip link set up dev lo' \
${EXECUTOR} ${EXECUTOR}
} }
down_body() { down_body() {
export IFACE=lo PHASE=down MOCK=echo export IFACE=lo PHASE=post-down MOCK=echo
atf_check -s exit:0 -o match:'ip link set down dev lo' \ atf_check -s exit:0 -o match:'ip link set down dev lo' \
${EXECUTOR} ${EXECUTOR}
} }
mtu_body() { mtu_body() {
export IFACE=eth0 PHASE=up MOCK=echo IF_MTU=1492 export IFACE=eth0 PHASE=pre-up MOCK=echo IF_MTU=1492
atf_check -s exit:0 -o match:'ip link set up dev eth0 mtu 1492' \ atf_check -s exit:0 -o match:'ip link set up dev eth0 mtu 1492' \
${EXECUTOR} ${EXECUTOR}
} }
vlan_explicit_up_body() { vlan_explicit_up_body() {
export IFACE=servers PHASE=up MOCK=echo \ export IFACE=servers PHASE=pre-up MOCK=echo \
IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" 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' \ atf_check -s exit:0 -o match:'ip link add link eth0 name servers type vlan id 123' \
${EXECUTOR} ${EXECUTOR}
} }
vlan_explicit_down_body() { vlan_explicit_down_body() {
export IFACE=servers PHASE=down MOCK=echo \ export IFACE=servers PHASE=post-down MOCK=echo \
IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" 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' \ atf_check -s exit:0 -o match:'ip link delete link eth0 name servers type vlan id 123' \
${EXECUTOR} ${EXECUTOR}
} }
vlan_guessed_up_body() { vlan_guessed_up_body() {
export IFACE=eth0.8 PHASE=up MOCK=echo export IFACE=eth0.8 PHASE=pre-up MOCK=echo
atf_check -s exit:0 -o match:'ip link add link eth0 name eth0.8 type vlan id 8' \ atf_check -s exit:0 -o match:'ip link add link eth0 name eth0.8 type vlan id 8' \
${EXECUTOR} ${EXECUTOR}
} }
vlan_guessed_down_body() { vlan_guessed_down_body() {
export IFACE=eth0.8 PHASE=down MOCK=echo export IFACE=eth0.8 PHASE=post-down MOCK=echo
atf_check -s exit:0 -o match:'ip link delete link eth0 name eth0.8 type vlan id 8' \ atf_check -s exit:0 -o match:'ip link delete link eth0 name eth0.8 type vlan id 8' \
${EXECUTOR} ${EXECUTOR}
} }
vlan_explicit_depend_body() { vlan_explicit_depend_body() {
export IFACE=servers PHASE=up MOCK=echo \ export IFACE=servers PHASE=pre-up MOCK=echo \
IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123"
atf_check -s exit:0 -o match:'eth0' \ atf_check -s exit:0 -o match:'eth0' \
${EXECUTOR} ${EXECUTOR}