Merge pull request #19458 from yuwata/network-route-remove

network: fix route removal logic a bit
This commit is contained in:
Lennart Poettering 2021-04-29 21:39:30 +02:00 committed by GitHub
commit c3a5240e3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 80 additions and 40 deletions

View file

@ -1274,7 +1274,9 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
if (link->network->dhcp_send_release) {
r = sd_dhcp_client_send_release(client);
if (r < 0)
log_link_warning_errno(link, r, "Failed to send DHCP RELEASE, ignoring: %m");
log_link_full_errno(link,
ERRNO_IS_DISCONNECT(r) ? LOG_DEBUG : LOG_WARNING,
r, "Failed to send DHCP RELEASE, ignoring: %m");
}
r = dhcp_lease_lost(link);

View file

@ -2967,15 +2967,3 @@ static const char* const link_state_table[_LINK_STATE_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
const char *err_msg = NULL;
(void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
return log_link_full_errno(link, level, err,
"%s: %s%s%s%m",
msg,
strempty(err_msg),
err_msg && !endswith(err_msg, ".") ? "." : "",
err_msg ? " " : "");
}

View file

@ -237,10 +237,3 @@ int link_reconfigure(Link *link, bool force);
int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata);
int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
#define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg)
#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
#define log_link_message_notice_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_NOTICE, err, msg)
#define log_link_message_info_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_INFO, err, msg)
#define log_link_message_debug_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_DEBUG, err, msg)

View file

@ -87,8 +87,8 @@ struct Manager {
usec_t speed_meter_usec_new;
usec_t speed_meter_usec_old;
bool dhcp4_prefix_root_cannot_set_table:1;
bool bridge_mdb_on_master_not_supported:1;
bool dhcp4_prefix_root_cannot_set_table;
bool bridge_mdb_on_master_not_supported;
FirewallContext *fw_ctx;
};

View file

@ -645,7 +645,7 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
/* link may be NULL */
if (in_addr_is_set(route->gw_family, &route->gw)) {
if (in_addr_is_set(route->gw_family, &route->gw) && route->nexthop_id == 0) {
if (route->gw_family == route->family) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
if (r < 0)
@ -717,10 +717,6 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
}
}
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m");
if (!route_type_is_reject(route) && route->nexthop_id == 0) {
assert(link); /* Those routes must be attached to a specific link */
@ -769,6 +765,7 @@ int route_remove(
link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
unsigned char type;
int r;
assert(link || manager);
@ -786,6 +783,21 @@ int route_remove(
if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
if (route->family == AF_INET && route->nexthop_id > 0 && route->type == RTN_BLACKHOLE)
/* When IPv4 route has nexthop id and the nexthop type is blackhole, even though kernel
* sends RTM_NEWROUTE netlink message with blackhole type, kernel's internal route type
* fib_rt_info::type may not be blackhole. Thus, we cannot know the internal value.
* Moreover, on route removal, the matching is done with the hidden value if we set
* non-zero type in RTM_DELROUTE message. Note, sd_rtnl_message_new_route() sets
* RTN_UNICAST by default. So, we need to clear the type here. */
type = RTN_UNSPEC;
else
type = route->type;
r = sd_rtnl_message_route_set_type(req, type);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m");
r = route_set_netlink_message(route, req, link);
if (r < 0)
return r;
@ -842,6 +854,9 @@ static int manager_drop_routes_internal(Manager *manager, bool foreign, const Li
routes = foreign ? manager->routes_foreign : manager->routes;
SET_FOREACH(route, routes) {
if (route->removing)
continue;
/* Do not touch routes managed by the kernel. */
if (route->protocol == RTPROT_KERNEL)
continue;
@ -855,6 +870,8 @@ static int manager_drop_routes_internal(Manager *manager, bool foreign, const Li
k = route_remove(route, manager, NULL, NULL);
if (k < 0 && r >= 0)
r = k;
route->removing = true;
}
return r;
@ -1083,8 +1100,8 @@ int route_configure(
Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r, k = 0;
Route *nr;
int r, k;
assert(link);
assert(link->manager);
@ -1106,6 +1123,10 @@ int route_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m");
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m");
r = route_set_netlink_message(route, req, link);
if (r < 0)
return r;
@ -1167,19 +1188,22 @@ int route_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
r = append_nexthops(route, req);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
if (ordered_set_isempty(route->multipath_routes)) {
if (route->nexthop_id != 0 ||
in_addr_is_set(route->gw_family, &route->gw) ||
ordered_set_isempty(route->multipath_routes)) {
k = route_add_and_setup_timer(link, route, NULL, &nr);
if (k < 0)
return k;
} else {
MultipathRoute *m;
r = append_nexthops(route, req);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
assert(!ret);
k = 0;
ORDERED_SET_FOREACH(m, route->multipath_routes) {
r = route_add_and_setup_timer(link, route, m, NULL);
if (r < 0)
@ -2745,8 +2769,17 @@ static int route_section_verify(Route *route, Network *network) {
route->section->filename, route->section->line);
}
if ((route->gateway_from_dhcp_or_ra ||
in_addr_is_set(route->gw_family, &route->gw)) &&
!ordered_set_isempty(route->multipath_routes))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Gateway= cannot be specified with MultiPathRoute=. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
if (route->nexthop_id > 0 &&
(in_addr_is_set(route->gw_family, &route->gw) ||
(route->gateway_from_dhcp_or_ra ||
in_addr_is_set(route->gw_family, &route->gw) ||
!ordered_set_isempty(route->multipath_routes)))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: NextHopId= cannot be specified with Gateway= or MultiPathRoute=. "

View file

@ -52,6 +52,7 @@ typedef struct Route {
bool protocol_set:1;
bool pref_set:1;
bool gateway_from_dhcp_or_ra:1;
bool removing:1;
union in_addr_union gw;
union in_addr_union dst;

View file

@ -2,6 +2,7 @@
#include "condition.h"
#include "conf-parser.h"
#include "networkd-link.h"
#include "networkd-util.h"
#include "parse-util.h"
#include "string-table.h"
@ -223,3 +224,17 @@ unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
return n + 1;
}
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
const char *err_msg = NULL;
/* link may be NULL. */
(void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
return log_link_full_errno(link, level, err,
"%s: %s%s%s%m",
msg,
strempty(err_msg),
err_msg && !endswith(err_msg, ".") ? "." : "",
err_msg ? " " : "");
}

View file

@ -11,6 +11,8 @@
#include "network-util.h"
#include "string-util.h"
typedef struct Link Link;
typedef struct NetworkConfigSection {
unsigned line;
bool invalid;
@ -73,9 +75,15 @@ static inline bool section_is_invalid(NetworkConfigSection *section) {
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
static inline int log_message_warning_errno(sd_netlink_message *m, int err, const char *msg) {
const char *err_msg = NULL;
(void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
return log_warning_errno(err, "%s: %s%s%m", msg, strempty(err_msg), err_msg ? " " : "");
}
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
#define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg)
#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
#define log_link_message_notice_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_NOTICE, err, msg)
#define log_link_message_info_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_INFO, err, msg)
#define log_link_message_debug_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_DEBUG, err, msg)
#define log_message_full_errno(m, level, err, msg) log_link_message_full_errno(NULL, m, level, err, msg)
#define log_message_error_errno(m, err, msg) log_message_full_errno(m, LOG_ERR, err, msg)
#define log_message_warning_errno(m, err, msg) log_message_full_errno(m, LOG_WARNING, err, msg)
#define log_message_notice_errno(m, err, msg) log_message_full_errno(m, LOG_NOTICE, err, msg)
#define log_message_info_errno(m, err, msg) log_message_full_errno(m, LOG_INFO, err, msg)
#define log_message_debug_errno(m, err, msg) log_message_full_errno(m, LOG_DEBUG, err, msg)