Skip to content

Commit 1c55b91

Browse files
committed
issue: 1792164 Support MSG_ERRQUEUE in sockinfo::rx()
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]>
1 parent 23f0f7f commit 1c55b91

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

src/vma/sock/sockinfo_tcp.cpp

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,7 +1910,7 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19101910
int total_rx = 0;
19111911
int poll_count = 0;
19121912
int bytes_to_tcp_recved;
1913-
size_t total_iov_sz = 1;
1913+
size_t total_iov_sz = 0;
19141914
int out_flags = 0;
19151915
int in_flags = *p_flags;
19161916
bool block_this_run = BLOCK_THIS_RUN(m_b_blocking, in_flags);
@@ -1932,23 +1932,43 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19321932
TAKE_T_RX_START;
19331933
#endif
19341934

1935-
if (unlikely((in_flags & MSG_WAITALL) && !(in_flags & MSG_PEEK))) {
1936-
total_iov_sz = 0;
1937-
for (int i = 0; i < sz_iov; i++) {
1938-
total_iov_sz += p_iov[i].iov_len;
1935+
/* In general, without any special flags, socket options, or ioctls being set,
1936+
* a recv call on a blocking TCP socket will return any number of bytes less than
1937+
* or equal to the size being requested. But unless the socket is closed remotely,
1938+
* interrupted by signal, or in an error state,
1939+
* it will block until at least 1 byte is available.
1940+
* With MSG_ERRQUEUE flag user application can request just information from
1941+
* error queue without any income data.
1942+
*/
1943+
if (p_iov && (sz_iov > 0)) {
1944+
total_iov_sz = 1;
1945+
if (unlikely((in_flags & MSG_WAITALL) && !(in_flags & MSG_PEEK))) {
1946+
total_iov_sz = 0;
1947+
for (int i = 0; i < sz_iov; i++) {
1948+
total_iov_sz += p_iov[i].iov_len;
1949+
}
1950+
if (total_iov_sz == 0)
1951+
return 0;
19391952
}
1940-
if (total_iov_sz == 0)
1941-
return 0;
19421953
}
19431954

19441955
si_tcp_logfunc("rx: iov=%p niovs=%d", p_iov, sz_iov);
1945-
/* poll rx queue till we have something */
1956+
1957+
/* poll rx queue till we have something */
19461958
lock_tcp_con();
1959+
if (__msg) {
1960+
handle_cmsg(__msg, in_flags);
1961+
if (__msg->msg_controllen == 0) {
1962+
errno = EAGAIN;
1963+
unlock_tcp_con();
1964+
return -1;
1965+
}
1966+
}
19471967
return_reuse_buffers_postponed();
19481968
unlock_tcp_con();
19491969

19501970
while (m_rx_ready_byte_count < total_iov_sz) {
1951-
if (unlikely(g_b_exit ||!is_rtr() || (rx_wait_lockless(poll_count, block_this_run) < 0))) {
1971+
if (unlikely(g_b_exit || !is_rtr() || (rx_wait_lockless(poll_count, block_this_run) < 0))) {
19521972
return handle_rx_error(block_this_run);
19531973
}
19541974
}
@@ -1957,8 +1977,9 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19571977

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

1960-
total_rx = dequeue_packet(p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
1961-
if (__msg) handle_cmsg(__msg, in_flags);
1980+
if (total_iov_sz > 0) {
1981+
total_rx = dequeue_packet(p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
1982+
}
19621983

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

0 commit comments

Comments
 (0)