Merge pull request #34 from ifupdown-ng/feature/vrf-static-route

vrf static route support
This commit is contained in:
Ariadne Conill 2020-08-20 03:21:44 -06:00 committed by GitHub
commit a7dc005b8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 44 deletions

View file

@ -1,5 +1,8 @@
#!/bin/sh #!/bin/sh
VRF_TABLE=""
[ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE"
addr_family() { addr_family() {
if [ "$1" != "${1#*[0-9].[0-9]}" ]; then if [ "$1" != "${1#*[0-9].[0-9]}" ]; then
echo "-4" echo "-4"
@ -20,7 +23,7 @@ configure_addresses() {
configure_gateways() { configure_gateways() {
for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do
addrfam=$(addr_family $i) addrfam=$(addr_family $i)
${MOCK} ip $addrfam route $1 default via $i ${MOCK} ip $addrfam route $1 default via $i $VRF_TABLE
done done
} }

View file

@ -123,14 +123,9 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename)
while (*token) while (*token)
{ {
if (!strcmp(token, "dhcp")) if (!strcmp(token, "dhcp"))
{ lif_interface_use_executor(cur_iface, "dhcp");
cur_iface->is_dhcp = true;
lif_dict_add(&cur_iface->vars, "use", strdup("dhcp"));
}
else if (!strcmp(token, "ppp")) else if (!strcmp(token, "ppp"))
{ lif_interface_use_executor(cur_iface, "ppp");
lif_dict_add(&cur_iface->vars, "use", strdup("ppp"));
}
else if (!strcmp(token, "inherits")) else if (!strcmp(token, "inherits"))
{ {
token = lif_next_token(&bufp); token = lif_next_token(&bufp);
@ -162,21 +157,12 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename)
} }
/* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */
if (!strcmp(executor, "dhcp")) if (!strcmp(executor, "bridge"))
cur_iface->is_dhcp = true;
else if (!strcmp(executor, "bridge"))
cur_iface->is_bridge = true; cur_iface->is_bridge = true;
else if (!strcmp(executor, "bond")) else if (!strcmp(executor, "bond"))
cur_iface->is_bond = true; cur_iface->is_bond = true;
else if (!strcmp(executor, "static"))
{
cur_iface->is_static = true;
continue;
}
else if (!strcmp(executor, "link"))
continue;
lif_dict_add(&cur_iface->vars, token, strdup(executor)); lif_interface_use_executor(cur_iface, executor);
} }
else if (!strcmp(token, "inherit")) else if (!strcmp(token, "inherit"))
{ {
@ -206,6 +192,19 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename)
lif_interface_address_add(cur_iface, addr); lif_interface_address_add(cur_iface, addr);
} }
else if (!strcmp(token, "gateway"))
{
char *addr = lif_next_token(&bufp);
if (cur_iface == NULL)
{
fprintf(stderr, "%s: gateway '%s' without interface\n", filename, addr);
goto parse_error;
}
lif_interface_use_executor(cur_iface, "static");
lif_dict_add(&cur_iface->vars, token, strdup(addr));
}
else if (cur_iface != NULL) else if (cur_iface != NULL)
{ {
token = maybe_remap_token(token); token = maybe_remap_token(token);
@ -214,17 +213,15 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename)
/* Check if token looks like <word1>-<word*> and assume <word1> is an addon */ /* Check if token looks like <word1>-<word*> and assume <word1> is an addon */
char *word_end = strchr(token, '-'); char *word_end = strchr(token, '-');
if (word_end) if (word_end != NULL)
{ {
/* Copy word1 to not mangle *token */ /* Copy word1 to not mangle *token */
char *addon = strndup(token, word_end - token); char *addon = strndup(token, word_end - token);
if (lif_dict_add_once(&cur_iface->vars, "use", addon, (lif_dict_cmp_t) strcmp) == NULL) lif_interface_use_executor(cur_iface, addon);
free(addon); free(addon);
/* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */
if (!strcmp(addon, "dhcp")) if (!strcmp(addon, "bridge"))
cur_iface->is_dhcp = true;
else if (!strcmp(addon, "bridge"))
cur_iface->is_bridge = true; cur_iface->is_bridge = true;
else if (!strcmp(addon, "bond")) else if (!strcmp(addon, "bond"))
cur_iface->is_bond = true; cur_iface->is_bond = true;

View file

@ -63,10 +63,7 @@ lif_interface_init(struct lif_interface *interface, const char *ifname)
interface->ifname = strdup(ifname); interface->ifname = strdup(ifname);
if (strchr(ifname, '.') == NULL) lif_interface_use_executor(interface, strchr(ifname, '.') == NULL ? "link" : "vlan");
lif_dict_add(&interface->vars, "use", strdup("link"));
else
lif_dict_add(&interface->vars, "use", strdup("vlan"));
} }
bool bool
@ -80,11 +77,7 @@ lif_interface_address_add(struct lif_interface *interface, const char *address)
return false; return false;
} }
if (!interface->is_static) lif_interface_use_executor(interface, "static");
{
lif_dict_add(&interface->vars, "use", strdup("static"));
interface->is_static = true;
}
lif_dict_add(&interface->vars, "address", addr); lif_dict_add(&interface->vars, "address", addr);
@ -137,6 +130,15 @@ lif_interface_fini(struct lif_interface *interface)
free(interface->ifname); free(interface->ifname);
} }
void
lif_interface_use_executor(struct lif_interface *interface, const char *executor)
{
char *exec_addon = strdup(executor);
if (lif_dict_add_once(&interface->vars, "use", exec_addon, (lif_dict_cmp_t) strcmp) == NULL)
free(exec_addon);
}
void void
lif_interface_collection_init(struct lif_dict *collection) lif_interface_collection_init(struct lif_dict *collection)
{ {
@ -147,7 +149,7 @@ lif_interface_collection_init(struct lif_dict *collection)
/* always enable loopback interface as part of a collection */ /* always enable loopback interface as part of a collection */
if_lo = lif_interface_collection_find(collection, "lo"); if_lo = lif_interface_collection_find(collection, "lo");
if_lo->is_auto = true; if_lo->is_auto = true;
lif_dict_add(&if_lo->vars, "use", strdup("loopback")); lif_interface_use_executor(if_lo, "loopback");
} }
void void
@ -228,8 +230,6 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic
return false; return false;
lif_dict_add(&interface->vars, "inherit", strdup(ifname)); lif_dict_add(&interface->vars, "inherit", strdup(ifname));
interface->is_static = parent->is_static;
interface->is_dhcp = parent->is_dhcp;
interface->is_bond = parent->is_bond; interface->is_bond = parent->is_bond;
interface->is_bridge = parent->is_bridge; interface->is_bridge = parent->is_bridge;

View file

@ -47,11 +47,9 @@ extern bool lif_address_unparse(const struct lif_address *address, char *buf, si
struct lif_interface { struct lif_interface {
char *ifname; char *ifname;
bool is_dhcp;
bool is_auto; bool is_auto;
bool is_bridge; bool is_bridge;
bool is_bond; bool is_bond;
bool is_static;
struct lif_dict vars; struct lif_dict vars;
@ -68,6 +66,7 @@ extern void lif_interface_init(struct lif_interface *interface, const char *ifna
extern bool lif_interface_address_add(struct lif_interface *interface, const char *address); extern bool lif_interface_address_add(struct lif_interface *interface, const char *address);
extern void lif_interface_address_delete(struct lif_interface *interface, const char *address); extern void lif_interface_address_delete(struct lif_interface *interface, const char *address);
extern void lif_interface_fini(struct lif_interface *interface); extern void lif_interface_fini(struct lif_interface *interface);
extern void lif_interface_use_executor(struct lif_interface *interface, const char *executor);
extern void lif_interface_collection_init(struct lif_dict *collection); extern void lif_interface_collection_init(struct lif_dict *collection);
extern void lif_interface_collection_fini(struct lif_dict *collection); extern void lif_interface_collection_fini(struct lif_dict *collection);

View file

@ -104,10 +104,7 @@ build_environment(char **envp[], const struct lif_execute_opts *opts, struct lif
lif_environment_push(envp, "IFACE", lifname); lif_environment_push(envp, "IFACE", lifname);
lif_environment_push(envp, "PHASE", phase); lif_environment_push(envp, "PHASE", phase);
lif_environment_push(envp, "MODE", mode); lif_environment_push(envp, "MODE", mode);
lif_environment_push(envp, "METHOD", "none");
/* try to provide $METHOD for ifupdown1 scripts if we can */
if (iface->is_dhcp)
lif_environment_push(envp, "METHOD", "dhcp");
if (opts->verbose) if (opts->verbose)
lif_environment_push(envp, "VERBOSE", "1"); lif_environment_push(envp, "VERBOSE", "1");

View file

@ -1,5 +1,6 @@
iface vrf-red iface vrf-red
vrf-table 1 vrf-table 1
gateway 203.0.113.2
auto eth0 auto eth0
iface eth0 iface eth0

View file

@ -22,6 +22,7 @@ tests_init \
vrf_dependency \ vrf_dependency \
vrf_ifupdown2_rewrite \ vrf_ifupdown2_rewrite \
vrf_ifupdown2_dependency \ vrf_ifupdown2_dependency \
vrf_implicit_static_gateway \
ppp_dependency \ ppp_dependency \
ppp_legacy_rewrite \ ppp_legacy_rewrite \
tunnel_dependency \ tunnel_dependency \
@ -139,6 +140,11 @@ vrf_ifupdown2_dependency_body() {
ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf-ifupdown2.interfaces eth0 ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf-ifupdown2.interfaces eth0
} }
vrf_implicit_static_gateway_body() {
atf_check -s exit:0 -o match:"use static" \
ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf.interfaces vrf-red
}
ppp_dependency_body() { ppp_dependency_body() {
atf_check -s exit:0 -o match:"requires eth0" \ atf_check -s exit:0 -o match:"requires eth0" \
ifquery -E $EXECUTORS_LINUX -i $FIXTURES/ppp.interfaces ppp0 ifquery -E $EXECUTORS_LINUX -i $FIXTURES/ppp.interfaces ppp0

View file

@ -4,7 +4,7 @@
EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/static" EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/static"
FIXTURES="$(atf_get_srcdir)/../fixtures" FIXTURES="$(atf_get_srcdir)/../fixtures"
tests_init up down tests_init up down vrf_up vrf_down
up_body() { up_body() {
export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces"
@ -25,3 +25,19 @@ down_body() {
-o match:'route del default via 2001:db8:1000:2::1' \ -o match:'route del default via 2001:db8:1000:2::1' \
${EXECUTOR} ${EXECUTOR}
} }
vrf_up_body() {
export IFACE=vrf-red PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \
IF_VRF_TABLE=1
atf_check -s exit:0 \
-o match:'route add default via 203.0.113.2 table 1' \
${EXECUTOR}
}
vrf_down_body() {
export IFACE=vrf-red PHASE=down MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \
IF_VRF_TABLE=1
atf_check -s exit:0 \
-o match:'route del default via 203.0.113.2 table 1' \
${EXECUTOR}
}