diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-05-29 20:23:23 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-05-31 17:57:35 +0200 |
commit | 89c82c261bb53bfb0b671437a1323830dd7e4019 (patch) | |
tree | a9a1cd8f03fbdf8e4ad735c1e91990887bb6c27d /src/mnl.c | |
parent | f718751f306d0de7ae2976f0003f6c1892fd0094 (diff) |
mnl: estimate receiver buffer size
Set a receiver buffer size based on the number of commands and the
average message size, this is useful for the --echo option in order to
avoid ENOBUFS errors.
On the kernel side, each skbuff consumes truesize from the socket queue
(although it uses NLMSG_GOODSIZE to allocate it), which is approximately
four times the estimated size per message that we get in turn for each
echo message to ensure enough receiver buffer space.
We could also explore increasing the buffer and retry if
mnl_nft_socket_sendmsg() hits ENOBUFS if we ever hit this problem again.
Reported-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/mnl.c')
-rw-r--r-- | src/mnl.c | 9 |
1 files changed, 7 insertions, 2 deletions
@@ -299,12 +299,14 @@ static ssize_t mnl_nft_socket_sendmsg(struct netlink_ctx *ctx, return sendmsg(mnl_socket_get_fd(ctx->nft->nf_sock), msg, 0); } -int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list) +int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list, + uint32_t num_cmds) { struct mnl_socket *nl = ctx->nft->nf_sock; int ret, fd = mnl_socket_get_fd(nl), portid = mnl_socket_get_portid(nl); uint32_t iov_len = nftnl_batch_iovec_len(ctx->batch); char rcv_buf[MNL_SOCKET_BUFFER_SIZE]; + size_t avg_msg_size, batch_size; const struct sockaddr_nl snl = { .nl_family = AF_NETLINK }; @@ -319,7 +321,10 @@ int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list) mnl_set_sndbuffer(ctx->nft->nf_sock, ctx->batch); - mnl_nft_batch_to_msg(ctx, &msg, &snl, iov, iov_len); + batch_size = mnl_nft_batch_to_msg(ctx, &msg, &snl, iov, iov_len); + avg_msg_size = div_round_up(batch_size, num_cmds); + + mnl_set_rcvbuffer(ctx->nft->nf_sock, num_cmds * avg_msg_size * 4); ret = mnl_nft_socket_sendmsg(ctx, &msg); if (ret == -1) |