1
0
mirror of https://github.com/systemd/systemd synced 2026-04-21 22:44:51 +02:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek
fb70f1de69
Merge pull request #22620 from yuwata/network-drop-detailed-log-messages
network: drop detailed log messages
2022-02-25 10:31:50 +01:00
Yu Watanabe
745f0620ed network: dhcp-server: add two more log messages 2022-02-25 11:01:51 +09:00
Yu Watanabe
2971e2adf1 network: bridge mdb: add missing assertion 2022-02-25 11:01:50 +09:00
Yu Watanabe
e1e4cd1eed network: move more functions
No functional change. Preparation for later commits.
2022-02-25 11:01:50 +09:00
Yu Watanabe
8bed7c55bf network: move functions
No functional change. Preparation for later commits.
2022-02-25 11:01:50 +09:00
Yu Watanabe
d3aff22f19 network: address: drop unnecessary call of address_get()
As here `req->address` and the result `existing` are always equivalent.
2022-02-25 11:01:50 +09:00
Yu Watanabe
a79a8d16d5 network: drop detailed log messages
This also renames netlink message `req` -> `m` for preparation of later
commits.

Follow-ups for #22014.
2022-02-25 11:01:50 +09:00
Yu Watanabe
cae162a79c network: make link_down() independent of link_up_or_down()
And rename it to link_down_now() to emphasize it does not use request
queue.
2022-02-25 11:01:50 +09:00
12 changed files with 710 additions and 629 deletions

View File

@ -96,7 +96,7 @@ static int address_label_configure_handler(sd_netlink *rtnl, sd_netlink_message
} }
static int address_label_configure(AddressLabel *label, Link *link, link_netlink_message_handler_t callback) { static int address_label_configure(AddressLabel *label, Link *link, link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r; int r;
assert(label); assert(label);
@ -106,29 +106,48 @@ static int address_label_configure(AddressLabel *label, Link *link, link_netlink
assert(link->manager->rtnl); assert(link->manager->rtnl);
assert(callback); assert(callback);
r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL, r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &m, RTM_NEWADDRLABEL,
link->ifindex, AF_INET6); link->ifindex, AF_INET6);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m"); return r;
r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen); r = sd_rtnl_message_addrlabel_set_prefixlen(m, label->prefixlen);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m"); return r;
r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label); r = sd_netlink_message_append_u32(m, IFAL_LABEL, label->label);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFAL_LABEL attribute: %m"); return r;
r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->prefix); r = sd_netlink_message_append_in6_addr(m, IFA_ADDRESS, &label->prefix);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return r;
link_ref(link); link_ref(link);
return 0;
}
int request_process_address_label(Request *req) {
Link *link;
int r;
assert(req);
assert(req->label);
assert(req->type == REQUEST_TYPE_ADDRESS_LABEL);
link = ASSERT_PTR(req->link);
if (!link_is_ready_to_configure(link, false))
return 0;
r = address_label_configure(req->label, link, req->netlink_handler);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure address label: %m");
return 1; return 1;
} }
@ -160,18 +179,6 @@ int link_request_static_address_labels(Link *link) {
return 0; return 0;
} }
int request_process_address_label(Request *req) {
assert(req);
assert(req->link);
assert(req->label);
assert(req->type == REQUEST_TYPE_ADDRESS_LABEL);
if (!link_is_ready_to_configure(req->link, false))
return 0;
return address_label_configure(req->label, req->link, req->netlink_handler);
}
static int address_label_section_verify(AddressLabel *label) { static int address_label_section_verify(AddressLabel *label) {
assert(label); assert(label);
assert(label->section); assert(label->section);

View File

@ -656,36 +656,36 @@ static void log_address_debug(const Address *address, const char *str, const Lin
strna(flags_str), strna(scope_str)); strna(flags_str), strna(scope_str));
} }
static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) { static int address_set_netlink_message(const Address *address, sd_netlink_message *m, Link *link) {
uint32_t flags; uint32_t flags;
int r; int r;
assert(address); assert(address);
assert(req); assert(m);
assert(link); assert(link);
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); r = sd_rtnl_message_addr_set_prefixlen(m, address->prefixlen);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m"); return r;
/* On remove, only IFA_F_MANAGETEMPADDR flag for IPv6 addresses are used. But anyway, set all /* On remove, only IFA_F_MANAGETEMPADDR flag for IPv6 addresses are used. But anyway, set all
* flags except tentative flag here unconditionally. Without setting the flag, the template * flags except tentative flag here unconditionally. Without setting the flag, the template
* addresses generated by kernel will not be removed automatically when the main address is * addresses generated by kernel will not be removed automatically when the main address is
* removed. */ * removed. */
flags = address->flags & ~IFA_F_TENTATIVE; flags = address->flags & ~IFA_F_TENTATIVE;
r = sd_rtnl_message_addr_set_flags(req, flags & 0xff); r = sd_rtnl_message_addr_set_flags(m, flags & 0xff);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m"); return r;
if ((flags & ~0xff) != 0) { if ((flags & ~0xff) != 0) {
r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags); r = sd_netlink_message_append_u32(m, IFA_FLAGS, flags);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set extended flags: %m"); return r;
} }
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr); r = netlink_message_append_in_addr_union(m, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m"); return r;
return 0; return 0;
} }
@ -707,7 +707,7 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
} }
int address_remove(Address *address) { int address_remove(Address *address) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
Link *link; Link *link;
int r; int r;
@ -722,20 +722,20 @@ int address_remove(Address *address) {
log_address_debug(address, "Removing", link); log_address_debug(address, "Removing", link);
r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR, r = sd_rtnl_message_new_addr(link->manager->rtnl, &m, RTM_DELADDR,
link->ifindex, address->family); link->ifindex, address->family);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m"); return log_link_warning_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
r = address_set_netlink_message(address, req, link); r = address_set_netlink_message(address, m, link);
if (r < 0) if (r < 0)
return r; return log_link_warning_errno(link, r, "Could not set netlink attributes: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req, r = netlink_call_async(link->manager->rtnl, NULL, m,
address_remove_handler, address_remove_handler,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link); link_ref(link);
@ -1025,7 +1025,7 @@ static int address_configure(
Link *link, Link *link,
link_netlink_message_handler_t callback) { link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r; int r;
assert(address); assert(address);
@ -1038,89 +1038,87 @@ static int address_configure(
log_address_debug(address, "Configuring", link); log_address_debug(address, "Configuring", link);
r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req, r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &m, link->ifindex, address->family);
link->ifindex, address->family);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
r = address_set_netlink_message(address, req, link);
if (r < 0) if (r < 0)
return r; return r;
r = sd_rtnl_message_addr_set_scope(req, address->scope); r = address_set_netlink_message(address, m, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set scope: %m"); return r;
r = sd_rtnl_message_addr_set_scope(m, address->scope);
if (r < 0)
return r;
if (in_addr_is_set(address->family, &address->in_addr_peer)) { if (in_addr_is_set(address->family, &address->in_addr_peer)) {
r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer); r = netlink_message_append_in_addr_union(m, IFA_ADDRESS, address->family, &address->in_addr_peer);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); return r;
} else if (in4_addr_is_set(&address->broadcast)) { } else if (in4_addr_is_set(&address->broadcast)) {
r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); r = sd_netlink_message_append_in_addr(m, IFA_BROADCAST, &address->broadcast);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m"); return r;
} }
if (address->family == AF_INET && address->label) { if (address->family == AF_INET && address->label) {
r = sd_netlink_message_append_string(req, IFA_LABEL, address->label); r = sd_netlink_message_append_string(m, IFA_LABEL, address->label);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m"); return r;
} }
r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, r = sd_netlink_message_append_cache_info(m, IFA_CACHEINFO,
address_set_cinfo(address, &(struct ifa_cacheinfo) {})); address_set_cinfo(address, &(struct ifa_cacheinfo) {}));
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m"); return r;
r = sd_netlink_message_append_u32(req, IFA_RT_PRIORITY, address->route_metric); r = sd_netlink_message_append_u32(m, IFA_RT_PRIORITY, address->route_metric);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_RT_PRIORITY attribute: %m"); return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link); r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return r;
link_ref(link); link_ref(link);
return 0; return 0;
} }
void address_cancel_request(Address *address) { static bool address_is_ready_to_configure(Link *link, const Address *address) {
Request req; assert(link);
assert(address); assert(address);
assert(address->link);
if (!address_is_requesting(address)) if (!link_is_ready_to_configure(link, false))
return; return false;
req = (Request) { if (FLAGS_SET(address->state, NETWORK_CONFIG_STATE_PROBING))
.link = address->link, return false;
.type = REQUEST_TYPE_ADDRESS,
.address = address,
};
request_drop(ordered_set_get(address->link->manager->request_queue, &req)); /* Refuse adding more than the limit */
address_cancel_requesting(address); if (set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
return false;
return true;
} }
static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int request_process_address(Request *req) {
Address *address;
Link *link;
int r; int r;
assert(link); assert(req);
assert(link->static_address_messages > 0); assert(req->type == REQUEST_TYPE_ADDRESS);
link->static_address_messages--; address = ASSERT_PTR(req->address);
link = ASSERT_PTR(req->link);
r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address"); if (!address_is_ready_to_configure(link, address))
if (r <= 0) return 0;
return r;
if (link->static_address_messages == 0) { r = address_configure(address, link, req->netlink_handler);
log_link_debug(link, "Addresses set"); if (r < 0)
link->static_addresses_configured = true; return log_link_warning_errno(link, r, "Failed to configure address: %m");
link_check_ready(link);
}
address_enter_configuring(address);
return 1; return 1;
} }
@ -1210,6 +1208,27 @@ int link_request_address(
return 1; return 1;
} }
static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(link);
assert(link->static_address_messages > 0);
link->static_address_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address");
if (r <= 0)
return r;
if (link->static_address_messages == 0) {
log_link_debug(link, "Addresses set");
link->static_addresses_configured = true;
link_check_ready(link);
}
return 1;
}
int link_request_static_address(Link *link, Address *address, bool consume) { int link_request_static_address(Link *link, Address *address, bool consume) {
assert(link); assert(link);
assert(address); assert(address);
@ -1253,49 +1272,23 @@ int link_request_static_addresses(Link *link) {
return 0; return 0;
} }
static bool address_is_ready_to_configure(Link *link, const Address *address) { void address_cancel_request(Address *address) {
assert(link); Request req;
assert(address); assert(address);
assert(address->link);
if (!link_is_ready_to_configure(link, false)) if (!address_is_requesting(address))
return false; return;
if (FLAGS_SET(address->state, NETWORK_CONFIG_STATE_PROBING)) req = (Request) {
return false; .link = address->link,
.type = REQUEST_TYPE_ADDRESS,
.address = address,
};
/* Refuse adding more than the limit */ request_drop(ordered_set_get(address->link->manager->request_queue, &req));
if (set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX) address_cancel_requesting(address);
return false;
return true;
}
int request_process_address(Request *req) {
Address *existing;
Link *link;
int r;
assert(req);
assert(req->link);
assert(req->address);
assert(req->type == REQUEST_TYPE_ADDRESS);
link = req->link;
r = address_get(link, req->address, &existing);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to get address: %m");
if (!address_is_ready_to_configure(link, existing))
return 0;
r = address_configure(req->address, link, req->netlink_handler);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure address: %m");
address_enter_configuring(existing);
return 1;
} }
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {

View File

@ -168,30 +168,29 @@ static int bridge_fdb_configure_message(const BridgeFDB *fdb, Link *link, sd_net
return 0; return 0;
} }
int link_request_static_bridge_fdb(Link *link) { static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, link_netlink_message_handler_t callback) {
BridgeFDB *fdb; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r; int r;
assert(fdb);
assert(link); assert(link);
assert(link->network); assert(link->manager);
assert(callback);
link->static_bridge_fdb_configured = false; r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_BRIDGE);
if (r < 0)
return r;
HASHMAP_FOREACH(fdb, link->network->bridge_fdb_entries_by_section) { r = bridge_fdb_configure_message(fdb, link, m);
r = link_queue_request(link, REQUEST_TYPE_BRIDGE_FDB, fdb, false, if (r < 0)
&link->static_bridge_fdb_messages, bridge_fdb_configure_handler, NULL); return r;
if (r < 0)
return log_link_error_errno(link, r, "Failed to request static bridge FDB entry: %m");
}
if (link->static_bridge_fdb_messages == 0) { r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link->static_bridge_fdb_configured = true; link_netlink_destroy_callback, link);
link_check_ready(link); if (r < 0)
} else { return r;
log_link_debug(link, "Setting bridge FDB entries");
link_set_state(link, LINK_STATE_CONFIGURING);
}
link_ref(link);
return 0; return 0;
} }
@ -221,38 +220,52 @@ static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) {
} }
int request_process_bridge_fdb(Request *req) { int request_process_bridge_fdb(Request *req) {
BridgeFDB *fdb;
Link *link; Link *link;
int r; int r;
assert(req); assert(req);
assert(req->fdb);
assert(req->type == REQUEST_TYPE_BRIDGE_FDB); assert(req->type == REQUEST_TYPE_BRIDGE_FDB);
assert_se(link = req->link); assert_se(link = req->link);
assert_se(fdb = req->fdb);
if (!bridge_fdb_is_ready_to_configure(req->fdb, link)) if (!bridge_fdb_is_ready_to_configure(fdb, link))
return 0; return 0;
/* create new RTM message */ r = bridge_fdb_configure(fdb, link, req->netlink_handler);
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_BRIDGE);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate netlink message: %m"); return log_link_warning_errno(link, r, "Failed to configure bridge FDB: %m");
r = bridge_fdb_configure_message(req->fdb, link, m);
if (r < 0)
return log_link_error_errno(link, r, "Could not create netlink message: %m");
/* send message to the kernel to update its internal static MAC table. */
r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send netlink message: %m");
link_ref(link);
return 1; return 1;
} }
int link_request_static_bridge_fdb(Link *link) {
BridgeFDB *fdb;
int r;
assert(link);
assert(link->network);
link->static_bridge_fdb_configured = false;
HASHMAP_FOREACH(fdb, link->network->bridge_fdb_entries_by_section) {
r = link_queue_request(link, REQUEST_TYPE_BRIDGE_FDB, fdb, false,
&link->static_bridge_fdb_messages, bridge_fdb_configure_handler, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request static bridge FDB entry: %m");
}
if (link->static_bridge_fdb_messages == 0) {
link->static_bridge_fdb_configured = true;
link_check_ready(link);
} else {
log_link_debug(link, "Setting bridge FDB entries");
link_set_state(link, LINK_STATE_CONFIGURING);
}
return 0;
}
void network_drop_invalid_bridge_fdb_entries(Network *network) { void network_drop_invalid_bridge_fdb_entries(Network *network) {
BridgeFDB *fdb; BridgeFDB *fdb;

View File

@ -115,7 +115,7 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m,
/* send a request to the kernel to add an MDB entry */ /* send a request to the kernel to add an MDB entry */
static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) { static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
struct br_mdb_entry entry; struct br_mdb_entry entry;
int r; int r;
@ -156,22 +156,71 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message
assert_not_reached(); assert_not_reached();
} }
/* create new RTM message */ r = sd_rtnl_message_new_mdb(link->manager->rtnl, &m, RTM_NEWMDB,
r = sd_rtnl_message_new_mdb(link->manager->rtnl, &req, RTM_NEWMDB,
link->master_ifindex > 0 ? link->master_ifindex : link->ifindex); link->master_ifindex > 0 ? link->master_ifindex : link->ifindex);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWMDB message: %m"); return r;
r = sd_netlink_message_append_data(req, MDBA_SET_ENTRY, &entry, sizeof(entry)); r = sd_netlink_message_append_data(m, MDBA_SET_ENTRY, &entry, sizeof(entry));
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append MDBA_SET_ENTRY attribute: %m"); return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return r;
link_ref(link); link_ref(link);
return 0;
}
static bool bridge_mdb_is_ready_to_configure(Link *link) {
Link *master;
assert(link);
if (!link_is_ready_to_configure(link, false))
return false;
if (!link->master_set)
return false;
if (link->master_ifindex <= 0 && streq_ptr(link->kind, "bridge"))
return true; /* The interface is bridge master. */
if (link_get_master(link, &master) < 0)
return false;
if (!streq_ptr(master->kind, "bridge"))
return false;
if (!IN_SET(master->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return false;
if (master->set_flags_messages > 0)
return false;
if (!link_has_carrier(master))
return false;
return true;
}
int request_process_bridge_mdb(Request *req) {
Link *link;
int r;
assert(req);
assert(req->mdb);
assert(req->type == REQUEST_TYPE_BRIDGE_MDB);
assert_se(link = req->link);
if (!bridge_mdb_is_ready_to_configure(link))
return 0;
r = bridge_mdb_configure(req->mdb, link, req->netlink_handler);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure bridge MDB: %m");
return 1; return 1;
} }
@ -210,48 +259,6 @@ finish:
return 0; return 0;
} }
static bool bridge_mdb_is_ready_to_configure(Link *link) {
Link *master;
if (!link_is_ready_to_configure(link, false))
return false;
if (!link->master_set)
return false;
if (link->master_ifindex <= 0 && streq_ptr(link->kind, "bridge"))
return true; /* The interface is bridge master. */
if (link_get_master(link, &master) < 0)
return false;
if (!streq_ptr(master->kind, "bridge"))
return false;
if (!IN_SET(master->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return false;
if (master->set_flags_messages > 0)
return false;
if (!link_has_carrier(master))
return false;
return true;
}
int request_process_bridge_mdb(Request *req) {
assert(req);
assert(req->link);
assert(req->mdb);
assert(req->type == REQUEST_TYPE_BRIDGE_MDB);
if (!bridge_mdb_is_ready_to_configure(req->link))
return 0;
return bridge_mdb_configure(req->mdb, req->link, req->netlink_handler);
}
static int bridge_mdb_verify(BridgeMDB *mdb) { static int bridge_mdb_verify(BridgeMDB *mdb) {
if (section_is_invalid(mdb->section)) if (section_is_invalid(mdb->section))
return -EINVAL; return -EINVAL;

View File

@ -528,21 +528,7 @@ static int dhcp4_server_configure(Link *link) {
return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m"); return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m");
log_link_debug(link, "Offering DHCPv4 leases"); log_link_debug(link, "Offering DHCPv4 leases");
return 0;
return 1;
}
int link_request_dhcp_server(Link *link) {
assert(link);
if (!link_dhcp4_server_enabled(link))
return 0;
if (link->dhcp_server)
return 0;
log_link_debug(link, "Requesting DHCP server.");
return link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, NULL, false, NULL, NULL, NULL);
} }
static bool dhcp_server_is_ready_to_configure(Link *link) { static bool dhcp_server_is_ready_to_configure(Link *link) {
@ -582,14 +568,40 @@ static bool dhcp_server_is_ready_to_configure(Link *link) {
} }
int request_process_dhcp_server(Request *req) { int request_process_dhcp_server(Request *req) {
assert(req); Link *link;
assert(req->link); int r;
assert(req->type == REQUEST_TYPE_DHCP_SERVER);
if (!dhcp_server_is_ready_to_configure(req->link)) assert(req);
assert(req->type == REQUEST_TYPE_DHCP_SERVER);
assert_se(link = req->link);
if (!dhcp_server_is_ready_to_configure(link))
return 0; return 0;
return dhcp4_server_configure(req->link); r = dhcp4_server_configure(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure DHCP server: %m");
return 1;
}
int link_request_dhcp_server(Link *link) {
int r;
assert(link);
if (!link_dhcp4_server_enabled(link))
return 0;
if (link->dhcp_server)
return 0;
log_link_debug(link, "Requesting DHCP server.");
r = link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, NULL, false, NULL, NULL, NULL);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to request configuration of DHCP server: %m");
return 0;
} }
int config_parse_dhcp_server_relay_agent_suboption( int config_parse_dhcp_server_relay_agent_suboption(

View File

@ -53,7 +53,7 @@ static int ipv6_proxy_ndp_address_configure(
Link *link, Link *link,
link_netlink_message_handler_t callback) { link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r; int r;
assert(address); assert(address);
@ -63,24 +63,42 @@ static int ipv6_proxy_ndp_address_configure(
assert(callback); assert(callback);
/* create new netlink message */ /* create new netlink message */
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_INET6); r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_INET6);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWNEIGH message: %m"); return r;
r = sd_rtnl_message_neigh_set_flags(req, NTF_PROXY); r = sd_rtnl_message_neigh_set_flags(m, NTF_PROXY);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set neighbor flags: %m"); return r;
r = sd_netlink_message_append_in6_addr(req, NDA_DST, address); r = sd_netlink_message_append_in6_addr(m, NDA_DST, address);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return r;
link_ref(link); link_ref(link);
return 0;
}
int request_process_ipv6_proxy_ndp_address(Request *req) {
Link *link;
int r;
assert(req);
assert(req->ipv6_proxy_ndp);
assert(req->type == REQUEST_TYPE_IPV6_PROXY_NDP);
assert_se(link = req->link);
if (!link_is_ready_to_configure(link, false))
return 0;
r = ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, link, req->netlink_handler);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure IPv6 proxy NDP address: %m");
return 1; return 1;
} }
@ -113,18 +131,6 @@ int link_request_static_ipv6_proxy_ndp_addresses(Link *link) {
return 0; return 0;
} }
int request_process_ipv6_proxy_ndp_address(Request *req) {
assert(req);
assert(req->link);
assert(req->ipv6_proxy_ndp);
assert(req->type == REQUEST_TYPE_IPV6_PROXY_NDP);
if (!link_is_ready_to_configure(req->link, false))
return 0;
return ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, req->link, req->netlink_handler);
}
int config_parse_ipv6_proxy_ndp_address( int config_parse_ipv6_proxy_ndp_address(
const char *unit, const char *unit,
const char *filename, const char *filename,

View File

@ -198,7 +198,7 @@ static int neighbor_configure(
Link *link, Link *link,
link_netlink_message_handler_t callback) { link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r; int r;
assert(neighbor); assert(neighbor);
@ -210,24 +210,45 @@ static int neighbor_configure(
log_neighbor_debug(neighbor, "Configuring", link); log_neighbor_debug(neighbor, "Configuring", link);
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH,
link->ifindex, neighbor->family); link->ifindex, neighbor->family);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate netlink message: %m"); return r;
r = neighbor_configure_message(neighbor, link, req); r = neighbor_configure_message(neighbor, link, m);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create netlink message: %m"); return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send netlink message: %m"); return r;
link_ref(link); link_ref(link);
return 0;
}
int request_process_neighbor(Request *req) {
Neighbor *neighbor;
Link *link;
int r;
assert(req);
assert(req->type == REQUEST_TYPE_NEIGHBOR);
neighbor = ASSERT_PTR(req->neighbor);
link = ASSERT_PTR(req->link);
if (!link_is_ready_to_configure(link, false))
return 0;
r = neighbor_configure(neighbor, link, req->netlink_handler);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure neighbor: %m");
neighbor_enter_configuring(neighbor); neighbor_enter_configuring(neighbor);
return r; return 1;
} }
static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@ -448,24 +469,6 @@ void link_foreignize_neighbors(Link *link) {
neighbor->source = NETWORK_CONFIG_SOURCE_FOREIGN; neighbor->source = NETWORK_CONFIG_SOURCE_FOREIGN;
} }
int request_process_neighbor(Request *req) {
int r;
assert(req);
assert(req->link);
assert(req->neighbor);
assert(req->type == REQUEST_TYPE_NEIGHBOR);
if (!link_is_ready_to_configure(req->link, false))
return 0;
r = neighbor_configure(req->neighbor, req->link, req->netlink_handler);
if (r < 0)
return r;
return 1;
}
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
_cleanup_(neighbor_freep) Neighbor *tmp = NULL; _cleanup_(neighbor_freep) Neighbor *tmp = NULL;
Neighbor *neighbor = NULL; Neighbor *neighbor = NULL;

View File

@ -430,7 +430,7 @@ static int nexthop_configure(
Link *link, Link *link,
link_netlink_message_handler_t callback) { link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r; int r;
assert(link); assert(link);
@ -442,16 +442,14 @@ static int nexthop_configure(
log_nexthop_debug(nexthop, "Configuring", link); log_nexthop_debug(nexthop, "Configuring", link);
r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &req, r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &m, RTM_NEWNEXTHOP, nexthop->family, nexthop->protocol);
RTM_NEWNEXTHOP, nexthop->family,
nexthop->protocol);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWNEXTHOP message: %m"); return r;
if (nexthop->id > 0) { if (nexthop->id > 0) {
r = sd_netlink_message_append_u32(req, NHA_ID, nexthop->id); r = sd_netlink_message_append_u32(m, NHA_ID, nexthop->id);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append NHA_ID attribute: %m"); return r;
} }
if (!hashmap_isempty(nexthop->group)) { if (!hashmap_isempty(nexthop->group)) {
@ -466,38 +464,36 @@ static int nexthop_configure(
HASHMAP_FOREACH(nhg, nexthop->group) HASHMAP_FOREACH(nhg, nexthop->group)
*p++ = *nhg; *p++ = *nhg;
r = sd_netlink_message_append_data(req, NHA_GROUP, group, sizeof(struct nexthop_grp) * hashmap_size(nexthop->group)); r = sd_netlink_message_append_data(m, NHA_GROUP, group, sizeof(struct nexthop_grp) * hashmap_size(nexthop->group));
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append NHA_GROUP attribute: %m"); return r;
} else if (nexthop->blackhole) { } else if (nexthop->blackhole) {
r = sd_netlink_message_append_flag(req, NHA_BLACKHOLE); r = sd_netlink_message_append_flag(m, NHA_BLACKHOLE);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append NHA_BLACKHOLE attribute: %m"); return r;
} else { } else {
r = sd_netlink_message_append_u32(req, NHA_OIF, link->ifindex); r = sd_netlink_message_append_u32(m, NHA_OIF, link->ifindex);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append NHA_OIF attribute: %m"); return r;
if (in_addr_is_set(nexthop->family, &nexthop->gw)) { if (in_addr_is_set(nexthop->family, &nexthop->gw)) {
r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw); r = netlink_message_append_in_addr_union(m, NHA_GATEWAY, nexthop->family, &nexthop->gw);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m"); return r;
r = sd_rtnl_message_nexthop_set_flags(req, nexthop->flags & RTNH_F_ONLINK); r = sd_rtnl_message_nexthop_set_flags(m, nexthop->flags & RTNH_F_ONLINK);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to set nexthop flags: %m"); return r;
} }
} }
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return r;
link_ref(link); link_ref(link);
nexthop_enter_configuring(nexthop);
return 0; return 0;
} }
@ -528,6 +524,72 @@ static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
return 1; return 1;
} }
static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
struct nexthop_grp *nhg;
assert(link);
assert(nexthop);
if (!link_is_ready_to_configure(link, false))
return false;
if (nexthop_owned_by_link(nexthop)) {
/* TODO: fdb nexthop does not require IFF_UP. The conditions below needs to be updated
* when fdb nexthop support is added. See rtm_to_nh_config() in net/ipv4/nexthop.c of
* kernel. */
if (link->set_flags_messages > 0)
return false;
if (!FLAGS_SET(link->flags, IFF_UP))
return false;
}
/* All group members must be configured first. */
HASHMAP_FOREACH(nhg, nexthop->group) {
NextHop *g;
if (manager_get_nexthop_by_id(link->manager, nhg->id, &g) < 0)
return false;
if (!nexthop_exists(g))
return false;
}
if (nexthop->id == 0) {
Request *req;
ORDERED_SET_FOREACH(req, link->manager->request_queue) {
if (req->type != REQUEST_TYPE_NEXTHOP)
continue;
if (req->nexthop->id != 0)
return false; /* first configure nexthop with id. */
}
}
return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw);
}
int request_process_nexthop(Request *req) {
NextHop *nexthop;
Link *link;
int r;
assert(req);
assert(req->type == REQUEST_TYPE_NEXTHOP);
nexthop = ASSERT_PTR(req->nexthop);
link = ASSERT_PTR(req->link);
if (!nexthop_is_ready_to_configure(link, nexthop))
return 0;
r = nexthop_configure(nexthop, link, req->netlink_handler);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure nexthop");
nexthop_enter_configuring(nexthop);
return 1;
}
static int link_request_nexthop( static int link_request_nexthop(
Link *link, Link *link,
NextHop *nexthop, NextHop *nexthop,
@ -763,68 +825,6 @@ void link_foreignize_nexthops(Link *link) {
} }
} }
static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
struct nexthop_grp *nhg;
assert(link);
assert(nexthop);
if (!link_is_ready_to_configure(link, false))
return false;
if (nexthop_owned_by_link(nexthop)) {
/* TODO: fdb nexthop does not require IFF_UP. The conditions below needs to be updated
* when fdb nexthop support is added. See rtm_to_nh_config() in net/ipv4/nexthop.c of
* kernel. */
if (link->set_flags_messages > 0)
return false;
if (!FLAGS_SET(link->flags, IFF_UP))
return false;
}
/* All group members must be configured first. */
HASHMAP_FOREACH(nhg, nexthop->group) {
NextHop *g;
if (manager_get_nexthop_by_id(link->manager, nhg->id, &g) < 0)
return false;
if (!nexthop_exists(g))
return false;
}
if (nexthop->id == 0) {
Request *req;
ORDERED_SET_FOREACH(req, link->manager->request_queue) {
if (req->type != REQUEST_TYPE_NEXTHOP)
continue;
if (req->nexthop->id != 0)
return false; /* first configure nexthop with id. */
}
}
return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw);
}
int request_process_nexthop(Request *req) {
int r;
assert(req);
assert(req->link);
assert(req->nexthop);
assert(req->type == REQUEST_TYPE_NEXTHOP);
if (!nexthop_is_ready_to_configure(req->link, req->nexthop))
return 0;
r = nexthop_configure(req->nexthop, req->link, req->netlink_handler);
if (r < 0)
return r;
return 1;
}
int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
_cleanup_(nexthop_freep) NextHop *tmp = NULL; _cleanup_(nexthop_freep) NextHop *tmp = NULL;
_cleanup_free_ void *raw_group = NULL; _cleanup_free_ void *raw_group = NULL;

View File

@ -1166,7 +1166,7 @@ static int route_configure(
Link *link, Link *link,
link_netlink_message_handler_t callback) { link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r; int r;
assert(route); assert(route);
@ -1179,279 +1179,93 @@ static int route_configure(
log_route_debug(route, "Configuring", link, link->manager); log_route_debug(route, "Configuring", link, link->manager);
r = sd_rtnl_message_new_route(link->manager->rtnl, &req, r = sd_rtnl_message_new_route(link->manager->rtnl, &m, RTM_NEWROUTE, route->family, route->protocol);
RTM_NEWROUTE, route->family,
route->protocol);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create netlink message: %m"); return r;
r = sd_rtnl_message_route_set_type(req, route->type); r = sd_rtnl_message_route_set_type(m, route->type);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m"); return r;
r = route_set_netlink_message(route, req, link); r = route_set_netlink_message(route, m, link);
if (r < 0) if (r < 0)
return log_error_errno(r, "Could not fill netlink message: %m"); return r;
if (route->lifetime_usec != USEC_INFINITY) { if (route->lifetime_usec != USEC_INFINITY) {
r = sd_netlink_message_append_u32(req, RTA_EXPIRES, r = sd_netlink_message_append_u32(m, RTA_EXPIRES,
MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX)); MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX));
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m"); return r;
} }
if (route->ttl_propagate >= 0) { if (route->ttl_propagate >= 0) {
r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate); r = sd_netlink_message_append_u8(m, RTA_TTL_PROPAGATE, route->ttl_propagate);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_TTL_PROPAGATE attribute: %m"); return r;
} }
r = sd_netlink_message_open_container(req, RTA_METRICS); r = sd_netlink_message_open_container(m, RTA_METRICS);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m"); return r;
if (route->mtu > 0) { if (route->mtu > 0) {
r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu); r = sd_netlink_message_append_u32(m, RTAX_MTU, route->mtu);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m"); return r;
} }
if (route->initcwnd > 0) { if (route->initcwnd > 0) {
r = sd_netlink_message_append_u32(req, RTAX_INITCWND, route->initcwnd); r = sd_netlink_message_append_u32(m, RTAX_INITCWND, route->initcwnd);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m"); return r;
} }
if (route->initrwnd > 0) { if (route->initrwnd > 0) {
r = sd_netlink_message_append_u32(req, RTAX_INITRWND, route->initrwnd); r = sd_netlink_message_append_u32(m, RTAX_INITRWND, route->initrwnd);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m"); return r;
} }
if (route->quickack >= 0) { if (route->quickack >= 0) {
r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack); r = sd_netlink_message_append_u32(m, RTAX_QUICKACK, route->quickack);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m"); return r;
} }
if (route->fast_open_no_cookie >= 0) { if (route->fast_open_no_cookie >= 0) {
r = sd_netlink_message_append_u32(req, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie); r = sd_netlink_message_append_u32(m, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m"); return r;
} }
if (route->advmss > 0) { if (route->advmss > 0) {
r = sd_netlink_message_append_u32(req, RTAX_ADVMSS, route->advmss); r = sd_netlink_message_append_u32(m, RTAX_ADVMSS, route->advmss);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTAX_ADVMSS attribute: %m"); return r;
} }
r = sd_netlink_message_close_container(req); r = sd_netlink_message_close_container(m);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m"); return r;
if (!ordered_set_isempty(route->multipath_routes)) { if (!ordered_set_isempty(route->multipath_routes)) {
assert(route->nexthop_id == 0); assert(route->nexthop_id == 0);
assert(!in_addr_is_set(route->gw_family, &route->gw)); assert(!in_addr_is_set(route->gw_family, &route->gw));
r = append_nexthops(link, route, req); r = append_nexthops(link, route, m);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m"); return r;
} }
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return r;
link_ref(link); link_ref(link);
return 0; return 0;
} }
void route_cancel_request(Route *route, Link *link) {
Request req;
assert(route);
link = route->link ?: link;
assert(link);
if (!route_is_requesting(route))
return;
req = (Request) {
.link = link,
.type = REQUEST_TYPE_ROUTE,
.route = route,
};
request_drop(ordered_set_get(link->manager->request_queue, &req));
route_cancel_requesting(route);
}
static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(link);
assert(link->static_route_messages > 0);
link->static_route_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Could not set route");
if (r <= 0)
return r;
if (link->static_route_messages == 0) {
log_link_debug(link, "Routes set");
link->static_routes_configured = true;
link_check_ready(link);
}
return 1;
}
int link_request_route(
Link *link,
Route *route,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
Route *existing;
int r;
assert(link);
assert(link->manager);
assert(route);
assert(route->source != NETWORK_CONFIG_SOURCE_FOREIGN);
assert(!route_needs_convert(route));
if (route_get(link->manager, link, route, &existing) < 0) {
_cleanup_(route_freep) Route *tmp = NULL;
if (consume_object)
tmp = route;
else {
r = route_dup(route, &tmp);
if (r < 0)
return r;
}
r = route_add(link->manager, link, tmp);
if (r < 0)
return r;
existing = TAKE_PTR(tmp);
} else {
existing->source = route->source;
existing->provider = route->provider;
existing->lifetime_usec = route->lifetime_usec;
if (consume_object)
route_free(route);
if (existing->expire) {
/* When re-configuring an existing route, kernel does not send RTM_NEWROUTE
* message, so we need to update the timer here. */
r = route_setup_timer(existing, NULL);
if (r < 0)
log_link_warning_errno(link, r, "Failed to update expiration timer for route, ignoring: %m");
if (r > 0)
log_route_debug(existing, "Updated expiration timer for", link, link->manager);
}
}
log_route_debug(existing, "Requesting", link, link->manager);
r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false,
message_counter, netlink_handler, ret);
if (r <= 0)
return r;
route_enter_requesting(existing);
return 1;
}
static int link_request_static_route(Link *link, Route *route) {
assert(link);
assert(link->manager);
assert(route);
if (!route_needs_convert(route))
return link_request_route(link, route, false, &link->static_route_messages,
static_route_handler, NULL);
log_route_debug(route, "Requesting", link, link->manager);
return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false,
&link->static_route_messages, static_route_handler, NULL);
}
static int link_request_wireguard_routes(Link *link, bool only_ipv4) {
NetDev *netdev;
Wireguard *w;
Route *route;
int r;
assert(link);
if (!streq_ptr(link->kind, "wireguard"))
return 0;
if (netdev_get(link->manager, link->ifname, &netdev) < 0)
return 0;
w = WIREGUARD(netdev);
if (!w)
return 0;
SET_FOREACH(route, w->routes) {
if (only_ipv4 && route->family != AF_INET)
continue;
r = link_request_static_route(link, route);
if (r < 0)
return r;
}
return 0;
}
int link_request_static_routes(Link *link, bool only_ipv4) {
Route *route;
int r;
assert(link);
assert(link->network);
link->static_routes_configured = false;
HASHMAP_FOREACH(route, link->network->routes_by_section) {
if (route->gateway_from_dhcp_or_ra)
continue;
if (only_ipv4 && route->family != AF_INET)
continue;
r = link_request_static_route(link, route);
if (r < 0)
return r;
}
r = link_request_wireguard_routes(link, only_ipv4);
if (r < 0)
return r;
if (link->static_route_messages == 0) {
link->static_routes_configured = true;
link_check_ready(link);
} else {
log_link_debug(link, "Requesting routes");
link_set_state(link, LINK_STATE_CONFIGURING);
}
return 0;
}
static int route_is_ready_to_configure(const Route *route, Link *link) { static int route_is_ready_to_configure(const Route *route, Link *link) {
int r; int r;
@ -1583,6 +1397,190 @@ int request_process_route(Request *req) {
return 1; return 1;
} }
int link_request_route(
Link *link,
Route *route,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
Route *existing;
int r;
assert(link);
assert(link->manager);
assert(route);
assert(route->source != NETWORK_CONFIG_SOURCE_FOREIGN);
assert(!route_needs_convert(route));
if (route_get(link->manager, link, route, &existing) < 0) {
_cleanup_(route_freep) Route *tmp = NULL;
if (consume_object)
tmp = route;
else {
r = route_dup(route, &tmp);
if (r < 0)
return r;
}
r = route_add(link->manager, link, tmp);
if (r < 0)
return r;
existing = TAKE_PTR(tmp);
} else {
existing->source = route->source;
existing->provider = route->provider;
existing->lifetime_usec = route->lifetime_usec;
if (consume_object)
route_free(route);
if (existing->expire) {
/* When re-configuring an existing route, kernel does not send RTM_NEWROUTE
* message, so we need to update the timer here. */
r = route_setup_timer(existing, NULL);
if (r < 0)
log_link_warning_errno(link, r, "Failed to update expiration timer for route, ignoring: %m");
if (r > 0)
log_route_debug(existing, "Updated expiration timer for", link, link->manager);
}
}
log_route_debug(existing, "Requesting", link, link->manager);
r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false,
message_counter, netlink_handler, ret);
if (r <= 0)
return r;
route_enter_requesting(existing);
return 1;
}
static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(link);
assert(link->static_route_messages > 0);
link->static_route_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Could not set route");
if (r <= 0)
return r;
if (link->static_route_messages == 0) {
log_link_debug(link, "Routes set");
link->static_routes_configured = true;
link_check_ready(link);
}
return 1;
}
static int link_request_static_route(Link *link, Route *route) {
assert(link);
assert(link->manager);
assert(route);
if (!route_needs_convert(route))
return link_request_route(link, route, false, &link->static_route_messages,
static_route_handler, NULL);
log_route_debug(route, "Requesting", link, link->manager);
return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false,
&link->static_route_messages, static_route_handler, NULL);
}
static int link_request_wireguard_routes(Link *link, bool only_ipv4) {
NetDev *netdev;
Wireguard *w;
Route *route;
int r;
assert(link);
if (!streq_ptr(link->kind, "wireguard"))
return 0;
if (netdev_get(link->manager, link->ifname, &netdev) < 0)
return 0;
w = WIREGUARD(netdev);
if (!w)
return 0;
SET_FOREACH(route, w->routes) {
if (only_ipv4 && route->family != AF_INET)
continue;
r = link_request_static_route(link, route);
if (r < 0)
return r;
}
return 0;
}
int link_request_static_routes(Link *link, bool only_ipv4) {
Route *route;
int r;
assert(link);
assert(link->network);
link->static_routes_configured = false;
HASHMAP_FOREACH(route, link->network->routes_by_section) {
if (route->gateway_from_dhcp_or_ra)
continue;
if (only_ipv4 && route->family != AF_INET)
continue;
r = link_request_static_route(link, route);
if (r < 0)
return r;
}
r = link_request_wireguard_routes(link, only_ipv4);
if (r < 0)
return r;
if (link->static_route_messages == 0) {
link->static_routes_configured = true;
link_check_ready(link);
} else {
log_link_debug(link, "Requesting routes");
link_set_state(link, LINK_STATE_CONFIGURING);
}
return 0;
}
void route_cancel_request(Route *route, Link *link) {
Request req;
assert(route);
link = route->link ?: link;
assert(link);
if (!route_is_requesting(route))
return;
req = (Request) {
.link = link,
.type = REQUEST_TYPE_ROUTE,
.route = route,
};
request_drop(ordered_set_get(link->manager->request_queue, &req));
route_cancel_requesting(route);
}
static int process_route_one( static int process_route_one(
Manager *manager, Manager *manager,
Link *link, Link *link,

View File

@ -588,17 +588,17 @@ static int routing_policy_rule_remove(RoutingPolicyRule *rule) {
r = sd_rtnl_message_new_routing_policy_rule(rule->manager->rtnl, &m, RTM_DELRULE, rule->family); r = sd_rtnl_message_new_routing_policy_rule(rule->manager->rtnl, &m, RTM_DELRULE, rule->family);
if (r < 0) if (r < 0)
return log_error_errno(r, "Could not allocate netlink message: %m"); return log_warning_errno(r, "Could not allocate netlink message: %m");
r = routing_policy_rule_set_netlink_message(rule, m, NULL); r = routing_policy_rule_set_netlink_message(rule, m, NULL);
if (r < 0) if (r < 0)
return log_error_errno(r, "Could not create netlink message: %m"); return log_warning_errno(r, "Could not create netlink message: %m");
r = netlink_call_async(rule->manager->rtnl, NULL, m, r = netlink_call_async(rule->manager->rtnl, NULL, m,
routing_policy_rule_remove_handler, routing_policy_rule_remove_handler,
NULL, NULL); NULL, NULL);
if (r < 0) if (r < 0)
return log_error_errno(r, "Could not send netlink message: %m"); return log_warning_errno(r, "Could not send netlink message: %m");
routing_policy_rule_enter_removing(rule); routing_policy_rule_enter_removing(rule);
return 0; return 0;
@ -624,21 +624,19 @@ static int routing_policy_rule_configure(
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family); r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate netlink message: %m"); return r;
r = routing_policy_rule_set_netlink_message(rule, m, link); r = routing_policy_rule_set_netlink_message(rule, m, link);
if (r < 0) if (r < 0)
return log_error_errno(r, "Could not create netlink message: %m"); return r;
r = netlink_call_async(link->manager->rtnl, NULL, m, callback, r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send netlink message: %m"); return r;
link_ref(link); link_ref(link);
return 0;
routing_policy_rule_enter_configuring(rule);
return r;
} }
static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) { static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) {
@ -730,6 +728,28 @@ void link_foreignize_routing_policy_rules(Link *link) {
} }
} }
int request_process_routing_policy_rule(Request *req) {
RoutingPolicyRule *rule;
Link *link;
int r;
assert(req);
assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE);
link = ASSERT_PTR(req->link);
rule = ASSERT_PTR(req->rule);
if (!link_is_ready_to_configure(link, false))
return 0;
r = routing_policy_rule_configure(rule, link, req->netlink_handler);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure routing policy rule: %m");
routing_policy_rule_enter_configuring(rule);
return 1;
}
static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
@ -858,24 +878,6 @@ int link_request_static_routing_policy_rules(Link *link) {
return 0; return 0;
} }
int request_process_routing_policy_rule(Request *req) {
int r;
assert(req);
assert(req->link);
assert(req->rule);
assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE);
if (!link_is_ready_to_configure(req->link, false))
return 0;
r = routing_policy_rule_configure(req->rule, req->link, req->netlink_handler);
if (r < 0)
return r;
return 1;
}
static const RoutingPolicyRule kernel_rules[] = { static const RoutingPolicyRule kernel_rules[] = {
{ .family = AF_INET, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, { .family = AF_INET, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, },
{ .family = AF_INET, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, { .family = AF_INET, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, },

View File

@ -546,7 +546,7 @@ static bool link_is_ready_to_call_set_link(Request *req) {
* is outdated, and checking the counter causes a deadlock. */ * is outdated, and checking the counter causes a deadlock. */
if (FLAGS_SET(link->flags, IFF_UP)) { if (FLAGS_SET(link->flags, IFF_UP)) {
/* The CAN interface must be down to configure bitrate, etc... */ /* The CAN interface must be down to configure bitrate, etc... */
r = link_down(link); r = link_down_now(link);
if (r < 0) { if (r < 0) {
link_enter_failed(link); link_enter_failed(link);
return false; return false;
@ -558,7 +558,7 @@ static bool link_is_ready_to_call_set_link(Request *req) {
/* This is the second attempt to set hardware address. On the first attempt /* This is the second attempt to set hardware address. On the first attempt
* req->netlink_handler points to link_set_mac_allow_retry_handler(). * req->netlink_handler points to link_set_mac_allow_retry_handler().
* The first attempt failed as the interface was up. */ * The first attempt failed as the interface was up. */
r = link_down(link); r = link_down_now(link);
if (r < 0) { if (r < 0) {
link_enter_failed(link); link_enter_failed(link);
return false; return false;
@ -588,7 +588,7 @@ static bool link_is_ready_to_call_set_link(Request *req) {
* is outdated, and checking the counter causes a deadlock. */ * is outdated, and checking the counter causes a deadlock. */
if (FLAGS_SET(link->flags, IFF_UP)) { if (FLAGS_SET(link->flags, IFF_UP)) {
/* link must be down when joining to bond master. */ /* link must be down when joining to bond master. */
r = link_down(link); r = link_down_now(link);
if (r < 0) { if (r < 0) {
link_enter_failed(link); link_enter_failed(link);
return false; return false;
@ -1068,35 +1068,22 @@ static int link_up_or_down(Link *link, bool up, link_netlink_message_handler_t c
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0) if (r < 0)
return log_link_debug_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); return r;
r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP); r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP);
if (r < 0) if (r < 0)
return log_link_debug_errno(link, r, "Could not set link flags: %m"); return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_debug_errno(link, r, "Could not send rtnetlink message: %m"); return r;
link_ref(link); link_ref(link);
return 0; return 0;
} }
int link_down(Link *link) {
int r;
assert(link);
r = link_up_or_down(link, false, link_down_handler);
if (r < 0)
return log_link_error_errno(link, r, "Failed to bring down interface: %m");
link->set_flags_messages++;
return 0;
}
static bool link_is_ready_to_activate(Link *link) { static bool link_is_ready_to_activate(Link *link) {
assert(link); assert(link);
@ -1127,7 +1114,7 @@ int request_process_activation(Request *req) {
r = link_up_or_down(link, up, req->netlink_handler); r = link_up_or_down(link, up, req->netlink_handler);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to bring %s: %m", up_or_down(up)); return log_link_warning_errno(link, r, "Failed to activate link: %m");
return 1; return 1;
} }
@ -1222,7 +1209,7 @@ int request_process_link_up_or_down(Request *req) {
r = link_up_or_down(link, up, req->netlink_handler); r = link_up_or_down(link, up, req->netlink_handler);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to bring %s: %m", up_or_down(up)); return log_link_warning_errno(link, r, "Failed to bring link %s: %m", up_or_down(up));
return 1; return 1;
} }
@ -1236,8 +1223,8 @@ int link_request_to_bring_up_or_down(Link *link, bool up) {
r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages, r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages,
up ? link_up_handler : link_down_handler, &req); up ? link_up_handler : link_down_handler, &req);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to request to bring %s link: %m", return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m",
up_or_down(up)); up_or_down(up));
req->userdata = INT_TO_PTR(up); req->userdata = INT_TO_PTR(up);
@ -1245,6 +1232,60 @@ int link_request_to_bring_up_or_down(Link *link, bool up) {
return 0; return 0;
} }
static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(m);
assert(link);
assert(link->set_flags_messages > 0);
link->set_flags_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r < 0)
log_link_message_warning_errno(link, m, r, "Could not bring down interface, ignoring");
r = link_call_getlink(link, get_link_update_flag_handler);
if (r < 0) {
link_enter_failed(link);
return 0;
}
link->set_flags_messages++;
return 0;
}
int link_down_now(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
assert(link->manager);
assert(link->manager->rtnl);
log_link_debug(link, "Bringing link down");
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0)
return log_link_warning_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
if (r < 0)
return log_link_warning_errno(link, r, "Could not set link flags: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req, link_down_now_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m");
link->set_flags_messages++;
link_ref(link);
return 0;
}
static int link_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int link_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;

View File

@ -42,12 +42,11 @@ int link_configure_mtu(Link *link);
int request_process_set_link(Request *req); int request_process_set_link(Request *req);
int link_down(Link *link);
int request_process_activation(Request *req); int request_process_activation(Request *req);
int link_request_to_activate(Link *link); int link_request_to_activate(Link *link);
int request_process_link_up_or_down(Request *req); int request_process_link_up_or_down(Request *req);
int link_request_to_bring_up_or_down(Link *link, bool up); int link_request_to_bring_up_or_down(Link *link, bool up);
int link_down_now(Link *link);
int link_remove(Link *link); int link_remove(Link *link);