- nbytes2 = recvmsg(sock->fd, &msg, MSG_DONTWAIT);
- } while (nbytes2 < 0 && errno == EINTR);
- if (nbytes2 < 0) {
- if (errno == ENOBUFS) {
- /* The kernel is notifying us that a message it tried to send to us
- * was dropped. We have to pass this along to the caller in case
- * it wants to retry a request. So kill the buffer, which we can
- * re-read next time. */
- COVERAGE_INC(netlink_overflow);
- ofpbuf_delete(buf);
- return ENOBUFS;
+ error = sendmsg(sock->fd, &msg, 0) < 0 ? errno : 0;
+ } while (error == EINTR);
+
+ for (i = 0; i < n; i++) {
+ struct nl_transaction *txn = transactions[i];
+
+ log_nlmsg(__func__, error, ofpbuf_data(txn->request), ofpbuf_size(txn->request),
+ sock->protocol);
+ }
+ if (!error) {
+ COVERAGE_ADD(netlink_sent, n);
+ }
+
+ if (error) {
+ return error;
+ }
+
+ ofpbuf_use_stub(&tmp_reply, tmp_reply_stub, sizeof tmp_reply_stub);
+ tmp_txn.request = NULL;
+ tmp_txn.reply = &tmp_reply;
+ tmp_txn.error = 0;
+ while (n > 0) {
+ struct nl_transaction *buf_txn, *txn;
+ uint32_t seq;
+
+ /* Find a transaction whose buffer we can use for receiving a reply.
+ * If no such transaction is left, use tmp_txn. */
+ buf_txn = &tmp_txn;
+ for (i = 0; i < n; i++) {
+ if (transactions[i]->reply) {
+ buf_txn = transactions[i];
+ break;
+ }
+ }
+
+ /* Receive a reply. */
+ error = nl_sock_recv__(sock, buf_txn->reply, false);
+ if (error) {
+ if (error == EAGAIN) {
+ nl_sock_record_errors__(transactions, n, 0);
+ *done += n;
+ error = 0;
+ }
+ break;
+ }
+
+ /* Match the reply up with a transaction. */
+ seq = nl_msg_nlmsghdr(buf_txn->reply)->nlmsg_seq;
+ if (seq < base_seq || seq >= base_seq + n) {
+ VLOG_DBG_RL(&rl, "ignoring unexpected seq %#"PRIx32, seq);
+ continue;
+ }
+ i = seq - base_seq;
+ txn = transactions[i];
+
+ /* Fill in the results for 'txn'. */
+ if (nl_msg_nlmsgerr(buf_txn->reply, &txn->error)) {
+ if (txn->reply) {
+ ofpbuf_clear(txn->reply);
+ }
+ if (txn->error) {
+ VLOG_DBG_RL(&rl, "received NAK error=%d (%s)",
+ error, ovs_strerror(txn->error));
+ }