Skip to content

Commit

Permalink
issue: 1792164 Support MSG_ERRQUEUE in sockinfo::rx()
Browse files Browse the repository at this point in the history
rx() processing should allow return information from error queue
and income data in single call.
Depending on user application it means that rx() logic should
return:
1. only income data
2. only error queue data
3. income and error queue data
Error processing logic is done accordingly.

Signed-off-by: Igor Ivanov <[email protected]>
  • Loading branch information
igor-ivanov committed Jul 1, 2020
1 parent 23f0f7f commit af63e14
Showing 1 changed file with 27 additions and 5 deletions.
32 changes: 27 additions & 5 deletions src/vma/sock/sockinfo_tcp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1910,7 +1910,7 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
int total_rx = 0;
int poll_count = 0;
int bytes_to_tcp_recved;
size_t total_iov_sz = 1;
size_t total_iov_sz = 0;
int out_flags = 0;
int in_flags = *p_flags;
bool block_this_run = BLOCK_THIS_RUN(m_b_blocking, in_flags);
Expand All @@ -1932,6 +1932,18 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
TAKE_T_RX_START;
#endif

/* In general, without any special flags, socket options, or ioctls being set,
* a recv call on a blocking TCP socket will return any number of bytes less than
* or equal to the size being requested. But unless the socket is closed remotely,
* interrupted by signal, or in an error state,
* it will block until at least 1 byte is available.
* With MSG_ERRQUEUE flag user application can request just information from
* error queue without any income data.
*/
if (p_iov && (sz_iov > 0)) {
total_iov_sz = 1;
}

if (unlikely((in_flags & MSG_WAITALL) && !(in_flags & MSG_PEEK))) {
total_iov_sz = 0;
for (int i = 0; i < sz_iov; i++) {
Expand All @@ -1942,13 +1954,22 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
}

si_tcp_logfunc("rx: iov=%p niovs=%d", p_iov, sz_iov);
/* poll rx queue till we have something */

/* poll rx queue till we have something */
lock_tcp_con();
if (__msg) {
handle_cmsg(__msg, in_flags);
if (__msg->msg_controllen == 0) {
errno = EAGAIN;
unlock_tcp_con();
return -1;
}
}
return_reuse_buffers_postponed();
unlock_tcp_con();

while (m_rx_ready_byte_count < total_iov_sz) {
if (unlikely(g_b_exit ||!is_rtr() || (rx_wait_lockless(poll_count, block_this_run) < 0))) {
if (unlikely(g_b_exit || !is_rtr() || (rx_wait_lockless(poll_count, block_this_run) < 0))) {
return handle_rx_error(block_this_run);
}
}
Expand All @@ -1957,8 +1978,9 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov

si_tcp_logfunc("something in rx queues: %d %p", m_n_rx_pkt_ready_list_count, m_rx_pkt_ready_list.front());

total_rx = dequeue_packet(p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
if (__msg) handle_cmsg(__msg, in_flags);
if (total_iov_sz > 0) {
total_rx = dequeue_packet(p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
}

/*
* RCVBUFF Accounting: Going 'out' of the internal buffer: if some bytes are not tcp_recved yet - do that.
Expand Down

0 comments on commit af63e14

Please sign in to comment.