Merge pull request #30268 from yuwata/network-fix-too-many-waiting-replies

network: fix issue caused by too many waiting replies
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2023-12-01 19:54:18 +01:00 committed by GitHub
commit ac116f8c27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 28 additions and 1 deletions

View file

@ -107,5 +107,7 @@ int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, O
void netlink_seal_message(sd_netlink *nl, sd_netlink_message *m);
size_t netlink_get_reply_callback_count(sd_netlink *nl);
/* TODO: to be exported later */
int sd_netlink_sendv(sd_netlink *nl, sd_netlink_message **messages, size_t msgcnt, uint32_t **ret_serial);

View file

@ -458,6 +458,12 @@ static int timeout_compare(const void *a, const void *b) {
return CMP(x->timeout, y->timeout);
}
size_t netlink_get_reply_callback_count(sd_netlink *nl) {
assert(nl);
return hashmap_size(nl->reply_callbacks);
}
int sd_netlink_call_async(
sd_netlink *nl,
sd_netlink_slot **ret_slot,
@ -477,7 +483,7 @@ int sd_netlink_call_async(
assert_return(!netlink_pid_changed(nl), -ECHILD);
if (hashmap_size(nl->reply_callbacks) >= REPLY_CALLBACKS_MAX)
return -ERANGE;
return -EXFULL;
r = hashmap_ensure_allocated(&nl->reply_callbacks, &trivial_hash_ops);
if (r < 0)

View file

@ -7,6 +7,8 @@
#include "networkd-queue.h"
#include "string-table.h"
#define REPLY_CALLBACK_COUNT_THRESHOLD 128
static Request *request_free(Request *req) {
if (!req)
return NULL;
@ -220,6 +222,13 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
if (req->waiting_reply)
continue; /* Waiting for netlink reply. */
/* Typically, requests send netlink message asynchronously. If there are many requests
* queued, then this event may make reply callback queue in sd-netlink full. */
if (netlink_get_reply_callback_count(manager->rtnl) >= REPLY_CALLBACK_COUNT_THRESHOLD ||
netlink_get_reply_callback_count(manager->genl) >= REPLY_CALLBACK_COUNT_THRESHOLD ||
fw_ctx_get_reply_callback_count(manager->fw_ctx) >= REPLY_CALLBACK_COUNT_THRESHOLD)
return 0;
r = req->process(req, link, req->userdata);
if (r == 0)
continue;

View file

@ -8,6 +8,7 @@
#include "firewall-util.h"
#include "firewall-util-private.h"
#include "log.h"
#include "netlink-util.h"
#include "string-table.h"
static const char * const firewall_backend_table[_FW_BACKEND_MAX] = {
@ -90,6 +91,13 @@ FirewallContext *fw_ctx_free(FirewallContext *ctx) {
return mfree(ctx);
}
size_t fw_ctx_get_reply_callback_count(FirewallContext *ctx) {
if (!ctx || !ctx->nfnl)
return 0;
return netlink_get_reply_callback_count(ctx->nfnl);
}
int fw_add_masquerade(
FirewallContext **ctx,
bool add,

View file

@ -15,6 +15,8 @@ FirewallContext *fw_ctx_free(FirewallContext *ctx);
DEFINE_TRIVIAL_CLEANUP_FUNC(FirewallContext *, fw_ctx_free);
size_t fw_ctx_get_reply_callback_count(FirewallContext *ctx);
int fw_add_masquerade(
FirewallContext **ctx,
bool add,