Hi, I am on CentOS 6.5 with kernel version kernel-2.6.32-431.el6. I was trying to find the implementation of recvmmsg(), and hopefully, I am not looking at the wrong source ~/rpmbuild/BUILD/kernel-2.6.32-431.el6/linux-2.6.32-431.el6.x86_64/net/socket.c. If I am, please kindly point me to the right source. int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags, struct timespec *timeout) { int fput_needed, err, datagrams; struct socket *sock; struct mmsghdr __user *entry; struct compat_mmsghdr __user *compat_entry; struct msghdr msg_sys; struct timespec end_time; if (timeout && poll_select_set_timeout(&end_time, timeout->tv_sec, timeout->tv_nsec)) return -EINVAL; datagrams = 0; sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) return err; err = sock_error(sock->sk); if (err) goto out_put; entry = mmsg; compat_entry = (struct compat_mmsghdr __user *)mmsg; while (datagrams < vlen) { /* * No need to ask LSM for more than the first datagram. */ if (MSG_CMSG_COMPAT & flags) { err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry, &msg_sys, flags, datagrams); if (err < 0) break; err = __put_user(err, &compat_entry->msg_len); ++compat_entry; } else { err = __sys_recvmsg(sock, (struct msghdr __user *)entry, &msg_sys, flags, datagrams); if (err < 0) break; err = put_user(err, &entry->msg_len); ++entry; } if (err) break; ++datagrams; if (timeout) { ktime_get_ts(timeout); *timeout = timespec_sub(end_time, *timeout); if (timeout->tv_sec < 0) { timeout->tv_sec = timeout->tv_nsec = 0; break; } /* Timeout, return less than vlen datagrams */ if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) break; } /* Out of band data, return right away */ if (msg_sys.msg_flags & MSG_OOB) break; } out_put: fput_light(sock->file, fput_needed); if (err == 0) return datagrams; if (datagrams != 0) { /* * We may return less entries than requested (vlen) if the * sock is non block and there aren't enough datagrams... */ if (err != -EAGAIN) { /* * ... or if recvmsg returns an error after we * received some datagrams, where we record the * error to return on the next call or if the * app asks about it using getsockopt(SO_ERROR). */ sock->sk->sk_err = -err; } return datagrams; } return err; } Let's say there are 2 packets at the socket, and I try: timespec t = {0, 0}; recvmmsg(fd, mmsg, vlen, 0, &t); Then, because of these lines: if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) break; recvmmsg() will just return 1 packet instead of 2. Am I right? It seems defecting the one of the main purposes of recvmmsg() -- trying to reduce # of system calls when there are packet queued. Maybe I miss something? I created a small test case that it waits for epoll callback, sleeps for 2-5 seconds and then calls recvmmsg() with timeout=0 (not null; just like above). Then, I found that recvmmsg() doesn't return all the packets that queued in 1 single call.
On Thu, 23 Oct 2014 19:43:07 -0700, Hei Chan said:
Then, I found that recvmmsg() doesn't return all the packets that queued in 1 single call.
You want to receive *all* of them? Call recv() with a *buf and a len big enough to get a *lot* of msgs, and pass MSG_ALL in the flags. Why were you expecting recvmsg() to return more than one message?
First of all, I apologize for the wrong subject. It should be recvmmsg() not sendmmsg(). Based on the source code (in my previous email), it doesn't seem like MSG_ALL has any effect (I don't know MSG_ALL exists either). Yes, I expect (or at least wish) recvmmsg() will return as many packet as possible before timeout, and if timeout is zero, it should keep trying to fill up the buffer until it is full or there is no more packet. The reason I expect or wish such behavior is that the main idea behind recvmmsg() is that application can reduce the number system call, and so the throughput will go up and latency will go down. Otherwise, the user could just simply use recvmsg() to mimic what recvmmsg() is doing. I don't expect recvmsg() returns more than 1 message but I do expect and wish recvmmsg() returns more than 1 message. On Friday, October 24, 2014 11:41 AM, "Valdis.Kletnieks@vt.edu" <Valdis.Kletnieks@vt.edu> wrote: On Thu, 23 Oct 2014 19:43:07 -0700, Hei Chan said:
Then, I found that recvmmsg() doesn't return all the packets that queued in 1 single call.
You want to receive *all* of them? Call recv() with a *buf and a len big enough to get a *lot* of msgs, and pass MSG_ALL in the flags. Why were you expecting recvmsg() to return more than one message? _______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
participants (2)
-
Hei Chan -
Valdis.Kletnieks@vt.edu