From 3d52c34bd9a3a2b9a526047d69c8bfef510975b8 Mon Sep 17 00:00:00 2001 From: yinbin6 Date: Fri, 9 Aug 2024 16:37:47 +0800 Subject: [PATCH] sync refector fill udp sendring (cherry picked from commit e01eabee7ca1b1993bc4262a74e783baa978c8c2) --- ...ouble-connect-lead-posix-api-disable.patch | 25 ++ ...vlan-info-for-kernerl-packets-when-v.patch | 51 ++++ ...e-the-issue-that-failed-to-bind-virt.patch | 88 +++++++ 0237-refector-fill-udp-sendring.patch | 223 ++++++++++++++++++ gazelle.spec | 14 +- 5 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 0234-WRAP-fix-double-connect-lead-posix-api-disable.patch create mode 100644 0235-virtio_user-add-vlan-info-for-kernerl-packets-when-v.patch create mode 100644 0236-virtio_user-solve-the-issue-that-failed-to-bind-virt.patch create mode 100644 0237-refector-fill-udp-sendring.patch diff --git a/0234-WRAP-fix-double-connect-lead-posix-api-disable.patch b/0234-WRAP-fix-double-connect-lead-posix-api-disable.patch new file mode 100644 index 0000000..dbb7ace --- /dev/null +++ b/0234-WRAP-fix-double-connect-lead-posix-api-disable.patch @@ -0,0 +1,25 @@ +From 4ab3c2ccc73f6a935e05b914adcdafdf416a0f2f Mon Sep 17 00:00:00 2001 +From: yinbin +Date: Fri, 2 Aug 2024 17:09:02 +0800 +Subject: [PATCH] WRAP:fix double connect lead posix api disable + +--- + src/lstack/api/lstack_wrap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c +index 947b273..5e60c36 100644 +--- a/src/lstack/api/lstack_wrap.c ++++ b/src/lstack/api/lstack_wrap.c +@@ -319,7 +319,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name + } else { + /* When the socket is POSIX_LWIP_OR_KERNEL, connect to lwip first and then connect to kernel. */ + ret = g_wrap_api->connect_fn(s, name, namelen); +- if (ret == 0) { ++ if (ret == 0 || (ret != 0 && errno == EINPROGRESS)) { + POSIX_SET_TYPE(sock, POSIX_LWIP); + } else { + ret = posix_api->connect_fn(s, name, namelen); +-- +2.33.0 + diff --git a/0235-virtio_user-add-vlan-info-for-kernerl-packets-when-v.patch b/0235-virtio_user-add-vlan-info-for-kernerl-packets-when-v.patch new file mode 100644 index 0000000..70dde64 --- /dev/null +++ b/0235-virtio_user-add-vlan-info-for-kernerl-packets-when-v.patch @@ -0,0 +1,51 @@ +From a547e495321969074b72331c0ae6b65a39975f6a Mon Sep 17 00:00:00 2001 +From: hkk +Date: Mon, 5 Aug 2024 21:58:46 +0800 +Subject: [PATCH] virtio_user: add vlan info for kernerl packets when vlan + switch is on + +--- + src/lstack/core/lstack_virtio.c | 14 ++++++++++++++ + src/lstack/netif/lstack_vdev.c | 1 + + 2 files changed, 15 insertions(+) + +diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c +index 70b025c..f95b289 100644 +--- a/src/lstack/core/lstack_virtio.c ++++ b/src/lstack/core/lstack_virtio.c +@@ -179,6 +179,20 @@ void virtio_tap_process_rx(uint16_t port, uint32_t queue_id) + uint32_t pkg_num; + + pkg_num = rte_eth_rx_burst(g_virtio_instance.virtio_port_id, queue_id, pkts_burst, VIRTIO_TX_RX_RING_SIZE); ++ /* ++ * For VLAN, the tap device defaults to tx-vlan-ofload as enabled and will not be modified by default, ++ * so the judgment is skipped. ++ * For checksum, tap devices are turned off by default, and it is assumed that they will not be modified, ++ * so no action will be taken. ++ * For TSO, tap devices do not support it, so no action will be taken. ++ */ ++ if (get_global_cfg_params()->nic.vlan_mode != -1) { ++ for (int i = 0; i< pkg_num; i++) { ++ pkts_burst[i]->ol_flags |= RTE_MBUF_F_TX_VLAN; ++ pkts_burst[i]->vlan_tci = (u16_t)get_global_cfg_params()->nic.vlan_mode; ++ } ++ } ++ + if (pkg_num > 0) { + g_virtio_instance.rx_pkg[queue_id] += pkg_num; + uint16_t nb_rx = rte_eth_tx_burst(lstack_net_port, queue_id, pkts_burst, pkg_num); +diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c +index a590b30..9ca77ba 100644 +--- a/src/lstack/netif/lstack_vdev.c ++++ b/src/lstack/netif/lstack_vdev.c +@@ -87,6 +87,7 @@ static inline void vdev_pkts_parse(struct rte_mbuf **pkts, int pkt_num) + pkts[i]->l2_len = sizeof(struct rte_ether_hdr); + } + ++ pkts[i]->packet_type = 0; + if (type == RTE_BE16(RTE_ETHER_TYPE_IPV4)) { + struct rte_ipv4_hdr *iph = rte_pktmbuf_mtod_offset(pkts[i], struct rte_ipv4_hdr *, + pkts[i]->l2_len); +-- +2.33.0 + diff --git a/0236-virtio_user-solve-the-issue-that-failed-to-bind-virt.patch b/0236-virtio_user-solve-the-issue-that-failed-to-bind-virt.patch new file mode 100644 index 0000000..b9445e2 --- /dev/null +++ b/0236-virtio_user-solve-the-issue-that-failed-to-bind-virt.patch @@ -0,0 +1,88 @@ +From b193256f4e3e5967ec2fc85600ec0883edc4bcc1 Mon Sep 17 00:00:00 2001 +From: hkk +Date: Thu, 8 Aug 2024 10:54:40 +0800 +Subject: [PATCH] virtio_user: solve the issue that failed to bind + virtio_user's IPv6 address + +--- + src/lstack/api/lstack_wrap.c | 57 ++++++++++++++++++++++++++---------- + 1 file changed, 42 insertions(+), 15 deletions(-) + +diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c +index 5e60c36..afcd227 100644 +--- a/src/lstack/api/lstack_wrap.c ++++ b/src/lstack/api/lstack_wrap.c +@@ -199,6 +199,46 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, + return posix_api->accept4_fn(s, addr, addrlen, flags); + } + ++static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t namelen) ++{ ++ struct lwip_sock *sock = NULL; ++ int times = 10; ++ int ret = 0; ++ ++ if (get_global_cfg_params()->kni_switch == 0 && get_global_cfg_params()->flow_bifurcation == 0) { ++ return 0; ++ } ++ ret = posix_api->bind_fn(s, name, namelen); ++ /* maybe kni addr, ipv6 addr maybe is tentative,need to wait a few seconds */ ++ if (name->sa_family == AF_INET6 && ret < 0 && errno == EADDRNOTAVAIL) { ++ LSTACK_LOG(WARNING, LSTACK, "virtio_user addr is tentative, please wait... \n"); ++ while (ret != 0 && times-- > 0) { ++ sleep(1); ++ ret = posix_api->bind_fn(s, name, namelen); ++ } ++ } ++ ++ if (ret == 0) { ++ /* reuse the port allocated by kernel when port == 0 */ ++ if (((struct sockaddr_in *)name)->sin_port == 0) { ++ struct sockaddr_in kerneladdr; ++ socklen_t len = sizeof(kerneladdr); ++ if (posix_api->getsockname_fn(s, (struct sockaddr *)&kerneladdr, &len) < 0) { ++ LSTACK_LOG(ERR, LSTACK, "kernel getsockname failed, fd=%d, errno=%d\n", s, errno); ++ return -1; ++ } ++ ((struct sockaddr_in *)name)->sin_port = kerneladdr.sin_port; ++ } ++ /* not sure POSIX_LWIP or POSIX_KERNEL */ ++ } else { ++ sock = lwip_get_socket(s); ++ POSIX_SET_TYPE(sock, POSIX_LWIP); ++ LSTACK_LOG(ERR, LSTACK, "kernel bind failed ret %d errno %d sa_family %u times %u\n", ++ ret, errno, name->sa_family, times); ++ } ++ return 0; ++} ++ + static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen) + { + if (name == NULL) { +@@ -231,21 +271,8 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen + return posix_api->bind_fn(s, name, namelen); + } + +- /* maybe kni addr */ +- if (posix_api->bind_fn(s, name, namelen) == 0) { +- /* reuse the port allocated by kernel when port == 0 */ +- if (((struct sockaddr_in *)name)->sin_port == 0) { +- struct sockaddr_in kerneladdr; +- socklen_t len = sizeof(kerneladdr); +- if (posix_api->getsockname_fn(s, (struct sockaddr *)&kerneladdr, &len) < 0) { +- LSTACK_LOG(ERR, LSTACK, "kernel getsockname failed, fd=%d, errno=%d\n", s, errno); +- return -1; +- } +- ((struct sockaddr_in *)name)->sin_port = kerneladdr.sin_port; +- } +- /* not sure POSIX_LWIP or POSIX_KERNEL */ +- } else { +- POSIX_SET_TYPE(sock, POSIX_LWIP); ++ if (kernel_bind_process(s, name, namelen) < 0) { ++ return -1; + } + return g_wrap_api->bind_fn(s, name, namelen); + } +-- +2.33.0 + diff --git a/0237-refector-fill-udp-sendring.patch b/0237-refector-fill-udp-sendring.patch new file mode 100644 index 0000000..29d6f3f --- /dev/null +++ b/0237-refector-fill-udp-sendring.patch @@ -0,0 +1,223 @@ +From eedeee26cb113f550339d54238ca41eb012697e3 Mon Sep 17 00:00:00 2001 +From: yinbin +Date: Wed, 31 Jul 2024 20:31:57 +0800 +Subject: [PATCH] refector fill udp sendring + +--- + src/lstack/core/lstack_lwip.c | 109 ++++++++++++++++++------ + src/lstack/core/lstack_protocol_stack.c | 11 +-- + 2 files changed, 84 insertions(+), 36 deletions(-) + +diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c +index 271e94f..19ff22d 100644 +--- a/src/lstack/core/lstack_lwip.c ++++ b/src/lstack/core/lstack_lwip.c +@@ -457,22 +457,67 @@ int sem_timedwait_nsecs(sem_t *sem) + return sem_timedwait(sem, &ts); + } + +-static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, size_t len, +- const struct sockaddr *addr, socklen_t addrlen) ++static ssize_t do_lwip_udp_fill_sendring(struct lwip_sock *sock, const void *buf, size_t len, ++ const struct sockaddr *addr, socklen_t addrlen) + { +- if (sock->errevent > 0) { +- GAZELLE_RETURN(ENOTCONN); ++ if (len > GAZELLE_UDP_PKGLEN_MAX) { ++ LSTACK_LOG(ERR, LSTACK, "Message too long\n"); ++ GAZELLE_RETURN(EMSGSIZE); ++ } ++ ++ ssize_t send_len = 0; ++ uint32_t write_num = (len + MBUF_MAX_DATA_LEN - 1) / MBUF_MAX_DATA_LEN; ++ uint32_t write_avail = gazelle_ring_readable_count(sock->send_ring); ++ struct wakeup_poll *wakeup = sock->wakeup; ++ ++ if (write_num > rte_ring_get_capacity(sock->send_ring)) { ++ LSTACK_LOG(ERR, LSTACK, "sock send_ring size is not enough\n"); ++ GAZELLE_RETURN(ENOMEM); ++ } ++ ++ /* if udp send 0 packet, set write_num to at least 1 */ ++ if (write_num == 0) { ++ write_num = 1; ++ } ++ ++ while (!netconn_is_nonblocking(sock->conn) && (write_avail < write_num)) { ++ if (sock->errevent > 0) { ++ GAZELLE_RETURN(ENOTCONN); ++ } ++ write_avail = gazelle_ring_readable_count(sock->send_ring); ++ } ++ ++ if (write_avail < write_num) { ++ sem_timedwait_nsecs(&sock->snd_ring_sem); ++ GAZELLE_RETURN(ENOMEM); ++ } ++ ++ send_len = app_buff_write(sock, (char *)buf, len, write_num, addr, addrlen); ++ ++ if (wakeup && wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLOUT) ++ && !NETCONN_IS_OUTIDLE(sock)) { ++ del_sock_event(sock, EPOLLOUT); ++ } ++ ++ if (wakeup) { ++ wakeup->stat.app_write_cnt += write_num; + } + +- struct protocol_stack *stack = sock->stack; +- if (!stack) { ++ return send_len; ++} ++ ++static ssize_t do_lwip_tcp_fill_sendring(struct lwip_sock *sock, const void *buf, size_t len, ++ const struct sockaddr *addr, socklen_t addrlen) ++{ ++ /* refer to the lwip implementation. */ ++ if (len == 0) { + return 0; + } + + ssize_t send_len = 0; + + /* merge data into last pbuf */ +- if (!NETCONN_IS_UDP(sock) && sock->remain_len) { ++ if (sock->remain_len) { + sock->stack->stats.sock_tx_merge++; + send_len = merge_data_lastpbuf(sock, (char *)buf, len); + if (send_len >= len) { +@@ -485,11 +530,6 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si + uint32_t write_avail = gazelle_ring_readable_count(sock->send_ring); + struct wakeup_poll *wakeup = sock->wakeup; + +- /* if udp send 0 packet, set write_num to at least 1 */ +- if (NETCONN_IS_UDP(sock) && write_num == 0) { +- write_num = 1; +- } +- + while (!netconn_is_nonblocking(sock->conn) && (write_avail < write_num)) { + if (sock->errevent > 0) { + GAZELLE_RETURN(ENOTCONN); +@@ -500,9 +540,6 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si + /* send_ring is full, data attach last pbuf */ + if (write_avail == 0) { + sem_timedwait_nsecs(&sock->snd_ring_sem); +- if (likely(sock->send_ring != NULL)) { +- write_avail = gazelle_ring_readable_count(sock->send_ring); +- } + goto END; + } + +@@ -523,10 +560,11 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si + } + + END: +- if (send_len == 0 && !NETCONN_IS_UDP(sock)) { ++ if (send_len == 0) { + errno = EAGAIN; + return -1; + } ++ + return send_len; + } + +@@ -817,28 +855,39 @@ static inline void thread_bind_stack(struct lwip_sock *sock) + ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t flags, + const struct sockaddr *addr, socklen_t addrlen) + { ++ ssize_t send = 0; ++ + if (buf == NULL) { + GAZELLE_RETURN(EINVAL); + } + +- struct lwip_sock *sock = lwip_get_socket(fd); +- if (len == 0 && !NETCONN_IS_UDP(sock)) { +- return 0; +- } +- +- if (NETCONN_IS_UDP(sock) && (len > GAZELLE_UDP_PKGLEN_MAX)) { +- LSTACK_LOG(ERR, LSTACK, "Message too long\n"); +- GAZELLE_RETURN(EMSGSIZE); ++ if (addr && addr->sa_family != AF_INET && addr->sa_family != AF_INET6) { ++ GAZELLE_RETURN(EINVAL); + } ++ ++ struct lwip_sock *sock = lwip_get_socket(fd); + + thread_bind_stack(sock); + + if (sock->same_node_tx_ring != NULL) { + return gazelle_same_node_ring_send(sock, buf, len, flags); + } +- ssize_t send = do_lwip_fill_sendring(sock, buf, len, addr, addrlen); +- if (send < 0 || (send == 0 && !NETCONN_IS_UDP(sock))) { +- return send; ++ if (sock->errevent > 0 || sock->stack == NULL) { ++ GAZELLE_RETURN(ENOTCONN); ++ } ++ ++ if (NETCONN_IS_UDP(sock)) { ++ send = do_lwip_udp_fill_sendring(sock, buf, len, addr, addrlen); ++ /* send = 0: udp send a empty package */ ++ if (send < 0) { ++ return send; ++ } ++ } else { ++ send = do_lwip_tcp_fill_sendring(sock, buf, len, addr, addrlen); ++ // send = 0 : tcp peer close connection ? ++ if (send <= 0) { ++ return send; ++ } + } + + notice_stack_send(sock, fd, send, flags); +@@ -860,7 +909,11 @@ ssize_t do_lwip_sendmsg_to_stack(struct lwip_sock *sock, int32_t s, const struct + continue; + } + +- ret = do_lwip_fill_sendring(sock, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, NULL, 0); ++ if (NETCONN_IS_UDP(sock)) { ++ ret = do_lwip_udp_fill_sendring(sock, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, NULL, 0); ++ } else { ++ ret = do_lwip_tcp_fill_sendring(sock, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, NULL, 0); ++ } + if (ret <= 0) { + buflen = (buflen == 0) ? ret : buflen; + break; +diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c +index 2867711..f433d0d 100644 +--- a/src/lstack/core/lstack_protocol_stack.c ++++ b/src/lstack/core/lstack_protocol_stack.c +@@ -916,7 +916,6 @@ void stack_udp_send(struct rpc_msg *msg) + size_t len = msg->args[MSG_ARG_1].size; + struct protocol_stack *stack = get_protocol_stack(); + int replenish_again; +- uint32_t call_num; + + struct lwip_sock *sock = lwip_get_socket(fd); + if (sock == NULL) { +@@ -930,16 +929,12 @@ void stack_udp_send(struct rpc_msg *msg) + } + + replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 0); +- call_num = __sync_fetch_and_sub(&sock->call_num, 1); +- if (replenish_again < 0) { +- return; +- } +- +- if ((call_num == 1) && (replenish_again > 0)) { ++ if ((replenish_again > 0) && (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1)) { + rpc_call_replenish(&stack->rpc_queue, sock); + return; + } +- ++ ++ __sync_fetch_and_sub(&sock->call_num, 1); + return; + } + +-- +2.33.0 + diff --git a/gazelle.spec b/gazelle.spec index eccb505..d84e314 100644 --- a/gazelle.spec +++ b/gazelle.spec @@ -2,14 +2,14 @@ Name: gazelle Version: 1.0.2 -Release: 53 +Release: 54 Summary: gazelle is a high performance user-mode stack License: MulanPSL-2.0 URL: https://gitee.com/openeuler/gazelle Source0: %{name}-%{version}.tar.gz BuildRequires: cmake gcc-c++ -BuildRequires: lwip >= 2.1.3-78 +BuildRequires: lwip >= 2.2.0-51 BuildRequires: dpdk-devel >= 21.11-5 BuildRequires: numactl-devel libpcap-devel libconfig-devel libboundscheck uthash-devel %ifarch ppc64le @@ -250,6 +250,10 @@ Patch9230: 0230-dfx-optimize-gazellectl-x-for-bond.patch Patch9231: 0231-virtio-fix-dfx-error-with-multiple-cpus.patch Patch9232: 0232-fix-issue-create-virtio_user-based-on-bond4-main-net.patch Patch9233: 0233-virtio_user-modify-mbuf-index-for-bond4.patch +Patch9234: 0234-WRAP-fix-double-connect-lead-posix-api-disable.patch +Patch9235: 0235-virtio_user-add-vlan-info-for-kernerl-packets-when-v.patch +Patch9236: 0236-virtio_user-solve-the-issue-that-failed-to-bind-virt.patch +Patch9237: 0237-refector-fill-udp-sendring.patch %description %{name} is a high performance user-mode stack. @@ -291,6 +295,12 @@ install -Dpm 0640 %{_builddir}/%{name}-%{version}/src/ltran/ltran.conf %{b %config(noreplace) %{conf_path}/ltran.conf %changelog +* Fri Aug 9 2024 yinbin6 - 1.0.2-54 +- refector fill udp sendring +- virtio_user: solve the issue that failed to bind virtio_user's IPv6 address +- virtio_user: add vlan info for kernerl packets when vlan switch is on +- WRAP:fix double connect lead posix api disable + * Fri Aug 2 2024 yinbin6 - 1.0.2-53 - virtio_user: modify mbuf index for bond4 - fix issue: create virtio_user based on bond4 main network card -- Gitee