]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: fix netlink batching 7017/head
authorJakub Urbańczyk <xthaid@gmail.com>
Thu, 27 Aug 2020 19:41:37 +0000 (21:41 +0200)
committerJakub Urbańczyk <xthaid@gmail.com>
Thu, 27 Aug 2020 20:06:14 +0000 (22:06 +0200)
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>
zebra/kernel_netlink.c

index d0c1bc812de4d2c102d46700cd6df0fd9e669b0f..cd2594f68a152477e35f1c829456e12794033a1e 100644 (file)
  */
 #define NL_DEFAULT_BATCH_SEND_THRESHOLD (15 * NL_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)
+#define NL_BATCH_RX_BUFSIZE NL_RCV_PKT_BUF_SIZE
 
 static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"},
                                           {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_namelen = sizeof(snl);
 
-       status = netlink_recv_msg(nl, msg, nl_batch_rx_buf,
-                                 sizeof(nl_batch_rx_buf));
-       if (status == -1 || status == 0)
-               return status;
+       /*
+        * The responses are not batched, so we need to read and process one
+        * message at a time.
+        */
+       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;
-            (status >= 0 && NLMSG_OK(h, (unsigned int)status));
-            h = NLMSG_NEXT(h, status)) {
+               h = (struct nlmsghdr *)nl_batch_rx_buf;
                ignore_msg = false;
                seq = h->nlmsg_seq;
                /*