Projects
openEuler:C
gazelle
_service:tar_scm:0139-diff-udp-and-tcp-read-fro...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0139-diff-udp-and-tcp-read-from-stack.patch of Package gazelle
From 472e2f00b3fda7dad4396704fd94715d91be4642 Mon Sep 17 00:00:00 2001 From: jiangheng <jiangheng14@huawei.com> Date: Wed, 21 Feb 2024 04:25:43 +0800 Subject: [PATCH] diff udp and tcp read from stack --- src/lstack/core/lstack_lwip.c | 211 +++++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 65 deletions(-) diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c index 50a3389..0b339fe 100644 --- a/src/lstack/core/lstack_lwip.c +++ b/src/lstack/core/lstack_lwip.c @@ -831,74 +831,96 @@ static struct pbuf *pbuf_free_partial(struct pbuf *pbuf, uint16_t free_len) return pbuf; } -ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags, - struct sockaddr *addr, socklen_t *addrlen) +static bool recv_break_for_err(struct lwip_sock *sock) { - size_t recv_left = len; - struct pbuf *pbuf = NULL; - ssize_t recvd = 0; - uint32_t copy_len; - struct lwip_sock *sock = get_socket_by_fd(fd); - bool latency_enable = get_protocol_stack_group()->latency_start; - - if (sock->errevent > 0 && !NETCONN_IS_DATAIN(sock)) { - errno = err_to_errno(netconn_err(sock->conn)); - return -1; - } + bool break_wait = (sock->errevent > 0) && (!NETCONN_IS_DATAIN(sock)); + errno = err_to_errno(netconn_err(sock->conn)); + return break_wait; +} - thread_bind_stack(sock); +static void recv_block_wait(struct lwip_sock *sock) +{ + lstack_block_wait(sock->wakeup); +} - if (sock->same_node_rx_ring != NULL) { - return gazelle_same_node_ring_recv(sock, buf, len, flags); +/* + * return 0 on success, -1 on error + * pbuf maybe NULL(tcp fin packet) + */ +static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf **pbuf) +{ + if (sock->recv_lastdata != NULL) { + *pbuf = sock->recv_lastdata; + sock->recv_lastdata = NULL; + return 0; } - while (recv_left > 0) { - if (sock->recv_lastdata) { - pbuf = sock->recv_lastdata; - sock->recv_lastdata = NULL; + if (noblock) { + if (gazelle_ring_read(sock->recv_ring, (void **)pbuf, 1) != 1) { + errno = EAGAIN; + return -1; } else { - if (netconn_is_nonblocking(sock->conn)) { - if (gazelle_ring_read(sock->recv_ring, (void **)&pbuf, 1) != 1) { - break; - } - } else { - while (gazelle_ring_read(sock->recv_ring, (void **)&pbuf, 1) != 1 && recvd == 0) { - /* if the connection is disconnected, recv return 0 */ - if (sock->errevent > 0 && !NETCONN_IS_DATAIN(sock)) { - errno = err_to_errno(netconn_err(sock->conn)); - return -1; - } - - lstack_block_wait(sock->wakeup); - } + return 0; + } + } else { + while (gazelle_ring_read(sock->recv_ring, (void **)pbuf, 1) != 1) { + if (recv_break_for_err(sock)) { + return -1; } + recv_block_wait(sock); } + return 0; + } +} - /* if udp recv a packet whose len is 0, return 0 */ - if (NETCONN_IS_UDP(sock) && pbuf->tot_len == 0) { - return 0; +/* return true: fin is read to user, false: pend fin */ +static bool recv_ring_handle_fin(struct lwip_sock *sock, struct pbuf *pbuf, ssize_t recvd) +{ + if (pbuf == NULL) { + if (recvd > 0) { + /* handle data first, then handle fin */ + sock->recv_lastdata = (void *)&fin_packet; + gazelle_ring_read_over(sock->recv_ring); + return false; } + gazelle_ring_read_over(sock->recv_ring); + return true; + } + /* pending fin */ + if (pbuf == (void *)&fin_packet) { + return true; + } - /* fin */ - if (unlikely(pbuf == NULL)) { - if (recvd > 0) { - /* read data first, then read fin */ - sock->recv_lastdata = (void *)&fin_packet; - gazelle_ring_read_over(sock->recv_ring); - break; - } - gazelle_ring_read_over(sock->recv_ring); - return 0; + return false; +} + +static ssize_t recv_ring_tcp_read(struct lwip_sock *sock, void *buf, size_t len, bool noblock) +{ + ssize_t recvd = 0; + size_t recv_left = len; + uint32_t copy_len; + struct pbuf *pbuf = NULL; + + if (len == 0) { + return 0; + } + + while (recv_left > 0) { + if (recv_ring_get_one(sock, noblock, &pbuf) != 0) { + break; } - /* pending fin */ - if (unlikely(pbuf == (void *)&fin_packet)) { - return 0; + if (unlikely((pbuf == NULL) || (pbuf == (void *)&fin_packet))) { + if (recv_ring_handle_fin(sock, pbuf, recvd)) { + return 0; + } else { + break; /* recvd > 0, pending fin, handle data */ + } } copy_len = (recv_left > pbuf->tot_len) ? pbuf->tot_len : recv_left; if (copy_len > UINT16_MAX) { - copy_len = UINT16_MAX; + copy_len = UINT16_MAX; /* it's impossible to get here */ } pbuf_copy_partial(pbuf, (char *)buf + recvd, copy_len, 0); @@ -907,39 +929,98 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags if (pbuf->tot_len > copy_len) { sock->recv_lastdata = pbuf_free_partial(pbuf, copy_len); - break; } else { if (sock->wakeup) { sock->wakeup->stat.app_read_cnt += 1; } - if (latency_enable) { + + if (get_protocol_stack_group()->latency_start) { calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK); } - gazelle_ring_read_over(sock->recv_ring); - /* in udp, if pbuf remaining len less than copy_len, discard these packets */ - if (recvd > 0 && NETCONN_IS_UDP(sock)) { - sock->stack->stats.sock_rx_drop++; - break; - } + gazelle_ring_read_over(sock->recv_ring); } } - /* rte_ring_count reduce lock */ - if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLIN) - && (!NETCONN_IS_DATAIN(sock))) { - del_sock_event(sock, EPOLLIN); + if (recvd > 0) { + errno = 0; + } else { + recvd = -1; } + return recvd; +} + +static ssize_t recv_ring_udp_read(struct lwip_sock *sock, void *buf, size_t len, bool noblock, + struct sockaddr *addr, socklen_t *addrlen) +{ + size_t recv_left = len; + struct pbuf *pbuf = NULL; + uint32_t copy_len; + + sock->recv_lastdata = NULL; + + if (recv_ring_get_one(sock, noblock, &pbuf) != 0) { + /* errno have set */ + return -1; + } + + copy_len = (recv_left > pbuf->tot_len) ? pbuf->tot_len : recv_left; + pbuf_copy_partial(pbuf, (char *)buf, copy_len, 0); + /* drop remaining data if have */ + gazelle_ring_read_over(sock->recv_ring); + if (pbuf && addr && addrlen) { lwip_sock_make_addr(sock->conn, &(pbuf->addr), pbuf->port, addr, addrlen); } - if (recvd == 0) { + if (copy_len < pbuf->tot_len) { + sock->stack->stats.sock_rx_drop++; + } + + if (sock->wakeup) { + sock->wakeup->stat.app_read_cnt++; + } + if (get_protocol_stack_group()->latency_start) { + calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK); + } + + return copy_len; +} + +ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags, + struct sockaddr *addr, socklen_t *addrlen) +{ + ssize_t recvd = 0; + struct lwip_sock *sock = get_socket_by_fd(fd); + + if (recv_break_for_err(sock)) { + return -1; + } + + thread_bind_stack(sock); + + if (sock->same_node_rx_ring != NULL) { + return gazelle_same_node_ring_recv(sock, buf, len, flags); + } + + if (NETCONN_IS_UDP(sock)) { + recvd = recv_ring_udp_read(sock, buf, len, netconn_is_nonblocking(sock->conn), addr, addrlen); + } else { + recvd = recv_ring_tcp_read(sock, buf, len, netconn_is_nonblocking(sock->conn)); + } + + /* rte_ring_count reduce lock */ + if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLIN) + && (!NETCONN_IS_DATAIN(sock))) { + del_sock_event(sock, EPOLLIN); + } + + if (recvd < 0) { if (sock->wakeup) { sock->wakeup->stat.read_null++; } - GAZELLE_RETURN(EAGAIN); + return -1; } return recvd; } -- 2.27.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.