zebra: fix netlink batching

It was wrongly assumed that the kernel is replying in batches when multiple
requests fail. The kernel sends one error message at a time, so we can
simply keep reading data from the socket as long as possible.

Signed-off-by: Jakub Urbańczyk <xthaid@gmail.com>
This commit is contained in:
Jakub Urbańczyk 2020-08-27 21:41:37 +02:00
parent da2f670078
commit 2f9dbd3ab3

View File

@ -96,14 +96,7 @@
*/ */
#define NL_DEFAULT_BATCH_SEND_THRESHOLD (15 * NL_PKT_BUF_SIZE) #define NL_DEFAULT_BATCH_SEND_THRESHOLD (15 * NL_PKT_BUF_SIZE)
/* #define NL_BATCH_RX_BUFSIZE NL_RCV_PKT_BUF_SIZE
* For every request sent to the kernel that has failed we get an error message,
* which contains a standard netlink message header and the payload consisting
* of an error code and the original netlink mesage. So the receiving buffer
* must be at least as big as the transmitting buffer increased by some space
* for headers.
*/
#define NL_BATCH_RX_BUFSIZE (NL_DEFAULT_BATCH_BUFSIZE + NL_PKT_BUF_SIZE)
static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"}, static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"},
{RTM_DELROUTE, "RTM_DELROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"},
@ -1173,14 +1166,17 @@ static int nl_batch_read_resp(struct nl_batch *bth)
msg.msg_name = (void *)&snl; msg.msg_name = (void *)&snl;
msg.msg_namelen = sizeof(snl); msg.msg_namelen = sizeof(snl);
status = netlink_recv_msg(nl, msg, nl_batch_rx_buf, /*
sizeof(nl_batch_rx_buf)); * The responses are not batched, so we need to read and process one
if (status == -1 || status == 0) * message at a time.
return status; */
while (true) {
status = netlink_recv_msg(nl, msg, nl_batch_rx_buf,
sizeof(nl_batch_rx_buf));
if (status == -1 || status == 0)
return status;
for (h = (struct nlmsghdr *)nl_batch_rx_buf; h = (struct nlmsghdr *)nl_batch_rx_buf;
(status >= 0 && NLMSG_OK(h, (unsigned int)status));
h = NLMSG_NEXT(h, status)) {
ignore_msg = false; ignore_msg = false;
seq = h->nlmsg_seq; seq = h->nlmsg_seq;
/* /*