diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 3f816d7fa2..67fc725f98 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -200,6 +200,17 @@ bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) { return check_ready_for_all_sr_iov_ports(link, allow_unmanaged, link_is_ready_to_configure_one); } +bool link_is_ready_to_configure_by_name(Manager *manager, const char *name, bool allow_unmanaged) { + assert(manager); + assert(name); + + Link *link; + if (link_get_by_name(manager, name, &link) < 0) + return false; + + return link_is_ready_to_configure(link, allow_unmanaged); +} + void link_ntp_settings_clear(Link *link) { link->ntp = strv_free(link->ntp); } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 113217cdb6..c5806cea33 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -225,6 +225,7 @@ typedef struct Link { typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*); bool link_is_ready_to_configure(Link *link, bool allow_unmanaged); +bool link_is_ready_to_configure_by_name(Manager *manager, const char *name, bool allow_unmanaged); void link_ntp_settings_clear(Link *link); void link_dns_settings_clear(Link *link); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 87dcaa4fc4..3b8d217757 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -872,6 +872,31 @@ int link_drop_routing_policy_rules(Link *link, bool only_static) { return r; } +static int routing_policy_rule_is_ready_to_configure(const RoutingPolicyRule *rule, Link *link) { + assert(rule); + assert(link); + assert(link->manager); + + /* For routing policy rules, it is not necessary to check operstate and friends of the interface. + * Hence, here we refuse to configure rules only when the interface is already removed, or in the + * failed state. */ + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return false; + + /* Strictly speaking checking existence of IIF and OIF below is not necessary. But, configuring + * routing policy rule with non-existent IIF or OIF is mostly meaningless, and 'ip rule' command + * shows [detached] for such rules, that may confuse users. Let's postpone to configure if one of + * IIF/OIF does not exist. */ + + if (rule->iif && !link_is_ready_to_configure_by_name(link->manager, rule->iif, /* allow_unmanaged = */ true)) + return false; + + if (rule->oif && !link_is_ready_to_configure_by_name(link->manager, rule->oif, /* allow_unmanaged = */ true)) + return false; + + return true; +} + static int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) { RoutingPolicyRule *existing; int r; @@ -881,7 +906,7 @@ static int routing_policy_rule_process_request(Request *req, Link *link, Routing assert(link->manager); assert(rule); - if (!link_is_ready_to_configure(link, false)) + if (!routing_policy_rule_is_ready_to_configure(rule, link)) return 0; r = routing_policy_rule_configure(rule, link, req);