Ben, socket.h in master does include sendmmsg https://github.com/openvswitch/ovs/blob/master/include/sparse/sys/socket.h#L165
Per your explanation, I understood why you call recvmsg there, so I don't have other comments. As William explained in his RFC patch, I think TPACKET_V3 is the best way to fix this. I tried af_packet to use veth in OVS DPDK, it's performance is 2 times more than my patch, about 4Gbps, for my patch, veth performance is about 1.47Gbps, af_packet just used TPACKET_V2, TPACKET_V3 should be much better than TPACKET_V2 per William's explanation. -----邮件原件----- 发件人: Ben Pfaff [mailto:b...@ovn.org] 发送时间: 2019年12月21日 4:51 收件人: Yi Yang (杨燚)-云服务集团 <yangy...@inspur.com> 抄送: d...@openvswitch.org 主题: Re: 答复: [PATCH] socket-util: Introduce emulation and wrapper for recvmmsg(). On Fri, Dec 20, 2019 at 01:25:29AM +0000, Yi Yang (杨 D)-云服务集团 wrote: > Current ovs matser has included sendmmsg declaration in > include/sparse/sys/socket.h I believe you are mistaken. > int sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int); > > I saw "+^L" in your patch. Yes, OVS uses page breaks to separate logical sections of code. The coding style document mentions this. > --- a/lib/socket-util.c > +++ b/lib/socket-util.c > @@ -1283,3 +1283,59 @@ wrap_sendmmsg(int fd, struct mmsghdr *msgs, > unsigned int n, unsigned int flags) } #endif #endif > +^L > +#ifndef _WIN32 /* Avoid using recvmsg on Windows entirely. */ > > +#undef recvmmsg > +int > +wrap_recvmmsg(int fd, struct mmsghdr *msgs, unsigned int n, > + int flags, struct timespec *timeout) { > + ovs_assert(!timeout); /* XXX not emulated */ > + > + static bool recvmmsg_broken = false; > + if (!recvmmsg_broken) { > + int save_errno = errno; > + int retval = recvmmsg(fd, msgs, n, flags, timeout); > + if (retval >= 0 || errno != ENOSYS) { > + return retval; > + } > + recvmmsg_broken = true; > + errno = save_errno; > + } > + return emulate_recvmmsg(fd, msgs, n, flags, timeout); } #endif > > I don't understand why call recvmmsg here although we have known > recvmmsg isn't defined, Can you explain that comment? I don't believe that the code tries to call recvmmsg() when it is not defined. The code inside #ifndef HAVE_SENDMMSG only uses emulate_recvmmsg(), which itself only calls recvmsg(), not recvmmsg(). > I don't think "static bool recvmmsg_broken" is thread-safe. It is thread-safe enough, because it is merely an optimization: if the value is wrong, then at most the code gets a little bit slower. > I think we can completely remove the below part if we do know recvmmsg > isn't defined (I think autoconf can detect it very precisely, we > needn't to do runtime check for this) > + static bool recvmmsg_broken = false; > + if (!recvmmsg_broken) { > + int save_errno = errno; > + int retval = recvmmsg(fd, msgs, n, flags, timeout); > + if (retval >= 0 || errno != ENOSYS) { > + return retval; > + } > + recvmmsg_broken = true; > + errno = save_errno; > + } There are three cases: 1. The C library does not have recvmmsg(). Then we cannot call it at all. In this case, HAVE_SENDMMSG is false and the "#ifndef HAVE_SENDMMSG" fork will use emulate_recvmmsg(). 2. The C library has recvmmsg() but the kernel does not, because it is too old. Then wrap_recvmmsg() will receive an ENOSYS error from the kernel, call emulate_recvmmsg(), and set recvmmsg_broken so that future calls don't have to bother going into the kernel at all. 3. The C library and the kernel both have recvmmsg(). Then wrap_recvmmsg() will call recvmmsg() and either succeed or get back some error other than ENOSYS. recvmmsg_broken will remain false, and all future calls to recvmmsg() will also take the kernel fast path. Autoconf cannot distinguish cases 2 and 3, nor can anything that runs at build time, because there is no way to guess whether the runtime kernel matches the build time kernel. _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev