Matias Elo(matiaselo) replied on github web page: platform/linux-generic/pktio/socket_mmap.c line 71 @@ -614,6 +628,78 @@ static int sock_mmap_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, return ret; } +static int sock_mmap_recv_tmo(pktio_entry_t *pktio_entry, int index, + odp_packet_t pkt_table[], int num, uint64_t usecs) +{ + struct timeval timeout; + int ret; + int maxfd; + fd_set readfds; + + timeout.tv_sec = usecs / 1000 / 1000; + timeout.tv_usec = usecs % (1000 * 1000); + FD_ZERO(&readfds); + maxfd = sock_mmap_fd_set(pktio_entry, index, &readfds); + + ret = sock_mmap_recv(pktio_entry, index, pkt_table, num); + if (ret != 0) + return ret; + + if (select(maxfd + 1, &readfds, NULL, NULL, + usecs == ODP_PKTIN_WAIT ? NULL : &timeout) == 0) + return 0; + + return sock_mmap_recv(pktio_entry, index, pkt_table, num); +} + +static int sock_mmap_recv_mq_tmo(pktio_entry_t *pktio_entry[], int index[], + int num_q, odp_packet_t pkt_table[], int num, + unsigned *from, uint64_t usecs) +{ + struct timeval timeout; + int i; + int ret; + int maxfd = -1, maxfd2; + fd_set readfds; + + timeout.tv_sec = usecs / 1000 / 1000; + timeout.tv_usec = usecs % (1000 * 1000); + + FD_ZERO(&readfds); + + for (i = 0; i < num_q; i++) { + maxfd2 = sock_mmap_fd_set(pktio_entry[i], index[i], &readfds); + if (maxfd2 > maxfd) + maxfd = maxfd2; + } + + for (i = 0; i < num_q; i++) { + ret = sock_mmap_recv(pktio_entry[i], index[i], pkt_table, num);
Comment: Same thing with the loop order than with netmap. > Matias Elo(matiaselo) wrote: > Couple comment lines describing the different stages of this function > wouldn't hurt when someone is reading this code later on. >> Matias Elo(matiaselo) wrote: >> Same thing with the loop order than with netmap. >>> Matias Elo(matiaselo) wrote: >>> Since this loop is a performance optimization I would move it before the >>> loop which sets the read descriptors. No use to set the descriptors if >>> packets are already available. >>>> Matias Elo(matiaselo) wrote: >>>> The motivation for a separate `odp_pktin_wait_time()` function was to >>>> avoid having to do time conversions in the fast path functions. As >>>> `odp_pktin_wait_time()` already returns the time in microseconds no >>>> additional conversions are needed here. Same thing for >>>> `odp_pktin_recv_mq_tmo()`. >>>> >>>> Currently, the value returned by `odp_pktin_recv_mq_tmo()` depends on >>>> `SLEEP_NSEC` definition. This should be modified so that the returned >>>> value is always in microseconds. >>>>> Matias Elo(matiaselo) wrote: >>>>> Every pktio type we currenly have uses microseconds for timeout, so you >>>>> could change `recv_tmo()` and `recv_mq_tmo()` to use microseconds instead >>>>> of nanoseconds. This removes the need for per operation conversions. >>>>>> Matias Elo(matiaselo) wrote: >>>>>> > Are you entirely sure about this? This is a function pointer, and if >>>>>> > two pktio devices have the same function pointer for recv_mq_tmo(), >>>>>> > the other function pointers including the recv() function pointer >>>>>> > should be identical as well. We do pass the device (entry[i]) to the >>>>>> > function pointed to by recv_mq_tmo as well, so it should be able to >>>>>> > update the correct counters. The ops structure is const, after all... >>>>>> >>>>>> I stand corrected, didn't notice the pktio_entry_t array parameter. A >>>>>> bit confusing as `recv_mq_tmo()` behaves differently than pretty much >>>>>> every other pktio op. >>>>>>> muvarov wrote >>>>>>> just pass nsec to drivers or you will have double calculation like in >>>>>>> netmap code. >>>>>>>> Juha-Matti Tilli(jmtilli) wrote: >>>>>>>> Are you entirely sure about this? This is a function pointer, and if >>>>>>>> two pktio devices have the same function pointer for recv_mq_tmo(), >>>>>>>> the other function pointers including the recv() function pointer >>>>>>>> should be identical as well. We do pass the device (entry[i]) to the >>>>>>>> function pointed to by recv_mq_tmo as well, so it should be able to >>>>>>>> update the correct counters. The ops structure is const, after all... >>>>>>>> >>>>>>>> So, when receiving packets from a particular device using netmap, we >>>>>>>> do call netmap_recv() and pass to it the pktio_entry[i] and also >>>>>>>> index[i] for the queue index. This is the same that the >>>>>>>> odp_pktin_recv_mq_tmo() function already did. It calls >>>>>>>> odp_pktin_recv() in a loop, and the latter function calls >>>>>>>> entry->s.ops->recv(entry, queue.index, packets, num); which to me >>>>>>>> seems to be exactly the same thing -- you pass exactly the same entry >>>>>>>> and the same queue.index. Same function, same arguments, I can't see >>>>>>>> how the behavior would be different... >>>>>>>> >>>>>>>> Now, if somebody opposes the .recv_mq_tmo function pointer due to >>>>>>>> added code line count, I might perhaps agree. But it seems to be the >>>>>>>> only way the DPDK support for genuine sleep could be added, so I see >>>>>>>> some value in it. >>>>>>>>> Juha-Matti Tilli(jmtilli) wrote: >>>>>>>>> Several options: (1) I could implement a binary search algorithm that >>>>>>>>> incrementally checks various usec values and uses >>>>>>>>> odp_pktin_wait_time() to check which one of these trial attempts >>>>>>>>> result in the same sleep wait value, but that would be slow; (2) I >>>>>>>>> could implement odp_pktin_wait_time_reverse() that does the >>>>>>>>> conversion in the other direction, but that would be an API change; >>>>>>>>> (3) I could just do the conversion and pass usec values instead of >>>>>>>>> sleep wait values. I carefully considered each and selected (3), but >>>>>>>>> do you think (2) or (1) would be better? >>>>>>>>>> Juha-Matti Tilli(jmtilli) wrote: >>>>>>>>>> Will fix. >>>>>>>>>>> Juha-Matti Tilli(jmtilli) wrote: >>>>>>>>>>> I disagree. SLEEP_NSEC is a private #define in odp_packet_io.c so >>>>>>>>>>> what the wait parameter actually means cannot be interpreted in the >>>>>>>>>>> drivers. (Believe me, I tried it!) Thus, the conversion from the >>>>>>>>>>> sleep wait parameter to microseconds is needed. >>>>>>>>>>>> Matias Elo(matiaselo) wrote: >>>>>>>>>>>> As I noted in the previous comment, I think this check isn't >>>>>>>>>>>> enough. The input queues would have to be from the same pktio >>>>>>>>>>>> device for this to work. >>>>>>>>>>>>> Matias Elo(matiaselo) wrote: >>>>>>>>>>>>> Internal functions should not use odp_ prefix. >>>>>>>>>>>>>> Matias Elo(matiaselo) wrote: >>>>>>>>>>>>>> You should pass the `wait` parameter to >>>>>>>>>>>>>> `entry->s.ops->recv_tmo()` and not do any conversions here. >>>>>>>>>>>>>>> Matias Elo(matiaselo) wrote: >>>>>>>>>>>>>>> ODP_TIME_SEC_IN_NS would work here. https://github.com/Linaro/odp/pull/341#discussion_r157677836 updated_at 2017-12-19 07:13:32