Matias Elo(matiaselo) replied on github web page:

platform/linux-generic/pktio/socket.c
line 60
@@ -693,6 +693,88 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int 
index ODP_UNUSED,
        return nb_rx;
 }
 
+static int sock_fd_set(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
+                      fd_set *readfds)
+{
+       pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock;
+       const int sockfd = pkt_sock->sockfd;
+
+       FD_SET(sockfd, readfds);
+       return sockfd;
+}
+
+static int sock_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_fd_set(pktio_entry, index, &readfds);
+
+       ret = sock_mmsg_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_mmsg_recv(pktio_entry, index, pkt_table, num);
+}
+
+static int sock_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_fd_set(pktio_entry[i], index[i], &readfds);
+               if (maxfd2 > maxfd)
+                       maxfd = maxfd2;
+       }
+
+       for (i = 0; i < num_q; i++) {
+               ret = sock_mmsg_recv(pktio_entry[i], index[i], pkt_table, num);


Comment:
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_r157676448
updated_at 2017-12-19 07:01:30

Reply via email to